🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
NullPointerException

null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

2回答

4487閲覧

beginTransaction()におけるNullPointerExceptionの解決方法を教えてください。

kashikoma

総合スコア8

NullPointerException

null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2019/12/18 08:02

編集2019/12/21 05:28

リストのアイテムをクリックしたら、フラグメントを切り替えて値を渡すようにする処理を、
リストのアダプタクラス内に記述しました。
実機で確認した際、この処理が実行される時点でエラーが出ました。

NullPointerExceptionについて発生する原因など調べてみたのですが、
自分のケースではどこをどうしたらよいのか分かりませんでした。
エラーになっている理由や解決策を教えて頂けないでしょうか
エラーメッセージ

12-17 20:28:42.115 18003-18003/com.kashikoma.memo E/AndroidRuntime: FATAL EXCEPTION: main Process: com.kashikoma.memo, PID: 18003 java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.app.FragmentTransaction android.support.v4.app.FragmentManager.beginTransaction()' on a null object reference at com.kashikoma.memo.MemoAdapter$1.onClick(MemoAdapter.java:45) at android.view.View.performClick(View.java:4799) at android.view.View$PerformClick.run(View.java:19938) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5384) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:702)

該当コード

エラーの該当部分は OnBindViewHolder > OnClick内 です。

public class MemoAdapter extends RealmRecyclerViewAdapter<Memo, MemoAdapter.MemoViewHolder> { private OrderedRealmCollection<Memo> mDataset; MemoAdapter(OrderedRealmCollection<Memo> memoDataset) { super(memoDataset, true); this.mDataset = memoDataset; setHasStableIds(true); } @Override public MemoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_memolist, parent, false); return new MemoViewHolder(view); } @Override public void onBindViewHolder(final MemoViewHolder holder, final int position) { final Memo obj = getItem(position); holder.memo.setText(obj.getMemo()); holder.id.setText(obj.getId()); // アイテムクリックされたら編集画面へ holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String id = obj.getId(); Bundle bundle = new Bundle(); bundle.putString("id", id); EditMemoFragment fragment = new EditMemoFragment(); fragment.setArguments(bundle); fragment.getFragmentManager().beginTransaction().replace(R.id.container, fragment).commit(); } }); } @Override public int getItemCount() { return mDataset.size(); } static class MemoViewHolder extends RecyclerView.ViewHolder { TextView memo; TextView id; MemoViewHolder(View view) { super(view); memo = view.findViewById(R.id.memoContent); id = view.findViewById(R.id.memoId); } } }

関連コード

・メインアクティビティ

public class MemoListActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_memolist); if (findViewById(R.id.container) != null) { if (savedInstanceState != null) {return;} TaskListFragment firstFragment = new TaskListFragment(); firstFragment.setArguments(getIntent().getExtras()); getSupportFragmentManager().beginTransaction().add(R.id.container, firstFragment).commit(); } //ボトムナビゲーション BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation); bottomNavigationView.setOnNavigationItemSelectedListener( new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_memo: { MemoListFragment fragment = MemoListFragment.newInstance(); getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).commit(); return true; } case R.id.action_task: { ... } } return false; } }); //Realm初期化・アプリ起動時のActivityに記述 Realm.init(this); RealmConfiguration config = new RealmConfiguration.Builder().build(); Realm.setDefaultConfiguration(config); } } ``` ・containerに表示されるフラグメント(onCreateView内でアダプタがnewされている) ```ここに言語を入力 public class MemoListFragment extends Fragment { private FloatingActionButton fab; private MemoListActivity memoListActivity; private RecyclerView recyclerView; private Realm realm; private MemoAdapter adapter; public static MemoListFragment newInstance(){ MemoListFragment f = new MemoListFragment(); Bundle args = new Bundle(); f.setArguments(args); return f; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_memo_list, container, false); fab = view.findViewById(R.id.intentEditMemo); realm = Realm.getDefaultInstance(); // Realmをインスタンス化 final RealmResults<Memo> result = realm.where(Memo.class).findAll() // テーブルから全レコード取得 .sort("id", Sort.DESCENDING);// 降順にソート adapter = new MemoAdapter(result); // その結果をアダプターに渡す recyclerView = view.findViewById(R.id.memoList); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setAdapter(adapter); recyclerView.setHasFixedSize(true); recyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL)); return view; } @Override public void onStart() { super.onStart(); //新規作成ボタン fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Bundle bundle = new Bundle(); bundle.putString("id", ""); EditMemoFragment fragment = new EditMemoFragment(); fragment.setArguments(bundle); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.container, fragment.newInstance(),"EditMemoFragment").commit(); } }); } @Override public void onDestroy() { super.onDestroy(); recyclerView.setAdapter(null); realm.close(); } } ```

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ドキュメントをご確認ください.

Fragment.getFragmentManager() は, そのフラグメントが Activity に接続した状態でなければ null を返します.


#追記

EditMemoFragment への遷移をアクティビティ(に新設したメソッド)に集約して, MemoListFragment での新規ボタン押下時および MemoAdapter (を設定した RecyclerView) による既存選択時(?)にそのメソッドを呼ぶように修正するコードです.

※テストは出来ていません

MemoListActivity.java

java

1//(前略) 2 3 //追加 4 //EditMemoFragment に遷移する 5 void replaceToEditMemoFragment(String id) { 6 Bundle bundle = new Bundle(); 7 bundle.putString("id", id); 8 EditMemoFragment fragment = new EditMemoFragment(); 9 fragment.setArguments(bundle); 10 getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).commit(); 11 } 12 13//(後略)

MemoListFragment.java

java

1//(前略) 2 3 //追加 4 //アクティビティに載せられると呼ばれる 5 @Override 6 public void onAttach(Context context) { 7 super.onAttach(context); 8 if (context instanceof MemoListActivity) { 9 memoListActivity = (MemoListActivity) context; 10 adapter.setActivity(memoListActivity); 11 } 12 } 13 14 //追加 15 //アクティビティから外されると呼ばれる 16 @Override 17 public void onDetach() { 18 super.onDetach(); 19 memoListActivity = null; 20 adapter.setActivity(null); 21 } 22 23//(中略) 24 25 //新規作成ボタン 26 fab.setOnClickListener(new View.OnClickListener() { 27 @Override 28 public void onClick(View view) { 29 memoListActivity.replaceToEditMemoFragment(""); 30 //以下削除 31 //Bundle bundle = new Bundle(); 32 //bundle.putString("id", ""); 33 //EditMemoFragment fragment = new EditMemoFragment(); 34 //fragment.setArguments(bundle); 35 //FragmentTransaction transaction = getFragmentManager().beginTransaction(); 36 //transaction.replace(R.id.container, fragment.newInstance(),"EditMemoFragment").commit(); 37 } 38 }); 39 40//(後略)

MemoAdapter.java

java

1public class MemoAdapter extends RealmRecyclerViewAdapter<Memo, MemoAdapter.MemoViewHolder> { 2 private MemoListActivity memoListActivity; //追加 3 private OrderedRealmCollection<Memo> mDataset; 4 5 //追加 6 //フラグメント遷移処理メソッドを持つアクティビティを設定 7 void setActivity(MemoListActivity memoListActivity) { 8 this.memoListActivity = memoListActivity; 9 } 10 11//(中略) 12 13 // アイテムクリックされたら編集画面へ 14 holder.itemView.setOnClickListener(new View.OnClickListener() { 15 @Override 16 public void onClick(View v) { 17 final String id = obj.getId(); 18 memoListActivity.replaceToEditMemoFragment(id); //追加 19 //以下削除 20 //Bundle bundle = new Bundle(); 21 //bundle.putString("id", id); 22 //EditMemoFragment fragment = new EditMemoFragment(); 23 //fragment.setArguments(bundle); 24 //fragment.getFragmentManager().beginTransaction().replace(R.id.container, fragment).commit(); 25 } 26 }); 27 28//(後略)

#追記2
上のコードでは onAttach 実行時は adapter がまだ new されていないため, NullPointerExeption が発生します.
onCreateView の adapter 生成部分を onAttack に移すことで解決します.
以下のコードでは adapter 生成部分をメソッド化しています.

MemoListFragment.java

java

1 @Override 2 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 3 View view = inflater.inflate(R.layout.fragment_memo_list, container, false); 4 fab = view.findViewById(R.id.intentEditMemo); 5 //以下を削除 6 //realm = Realm.getDefaultInstance(); // Realmをインスタンス化 7 //final RealmResults<Memo> result = realm.where(Memo.class).findAll() // テーブルから全レコード取得 8 // .sort("id", Sort.DESCENDING);// 降順にソート 9 //adapter = new MemoAdapter(result); // その結果をアダプターに渡す 10 11 recyclerView = view.findViewById(R.id.memoList); 12 recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 13 recyclerView.setAdapter(adapter); 14 recyclerView.setHasFixedSize(true); 15 recyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL)); 16 17 return view; 18 } 19 20 //追加 21 //MemoAdapter を生成する. 22 private MemoAdapter createMemoAdapter(MemoListActivity memoListActivity) { 23 realm = Realm.getDefaultInstance(); // Realmをインスタンス化 24 final RealmResults<Memo> result = realm.where(Memo.class).findAll() // テーブルから全レコード取得 25 .sort("id", Sort.DESCENDING);// 降順にソート 26 adapter = new MemoAdapter(result); // その結果をアダプターに渡す 27 adapter.setActivity(memoListActivity); 28 } 29 30 //アクティビティに載せられると呼ばれる 31 @Override 32 public void onAttach(Context context) { 33 super.onAttach(context); 34 if (context instanceof MemoListActivity) { 35 memoListActivity = (MemoListActivity) context; 36 //adapter.setActivity(memoListActivity); //削除 37 adapter = createMemoAdapter(memoListActivity); //追加 38 } 39 }

投稿2019/12/18 16:10

編集2019/12/21 08:43
jimbe

総合スコア13202

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kashikoma

2019/12/19 03:11

ありがとうございます。 getFragments()とかしないと、Activityに接続中のフラグメントは持ってこれないですよね?でもこのクラスでは普通はできないですし… Activityのインスタンスを渡す方法も試みましたがRealmのアダプタを使用しているせいか上手くいかず、リスナを使うことも考えましたがいいやり方が見つけられませんでした。 アクティビティの遷移ができることは知っているのですが、できれば同一アクティビティ上でフラグメントの遷移がしたいなと思っています。 このようなクラスでは諦めるしかないでしょうか。
jimbe

2019/12/19 03:30 編集

>EditMemoFragment fragment = new EditMemoFragment(); >fragment.setArguments(bundle); >fragment.getFragmentManager().beginTransaction().replace(R.id.container, fragment).commit(); getFragmentManager があるからと言って, 自分が生まれてすぐ自分を持ち上げるようなことは出来ません. この場合に必要な FragmentManager は, R.id.container があるアクティビティから getFragmentManager したものが妥当かと思います. (もちろん, そのアクティビティに既に接続してあるフラグメントでも出来ます.) ですので, この MemoAdapter とアクティビティとの関係は分かりませんが, onClick の処理が行われる時点でなんとか該当アクティビティを得るか, あらかじめ該当アクティビティから getFragmentManager しておいたものを使えるようにするかかと思います.
kashikoma

2019/12/19 07:04

newしたアクティビティは空っぽなので、そこからgetFragmentManagerしたら当然nullになっちゃうよってことで合っていますか? 前の質問でもアドバイス頂いていたことなのになかなか理解できずお恥ずかしい限りです 色々試してみたんですが自力では上手くいきませんでした。 このクラスでアクティビティやフラグメントのインスタンスを作っても今表示してるアクティビティとは別物なので、アクティビティでgetFragmentManagerとかgetActivity().getSupportFragmentManager()とかしたものを持ってくるとnullが帰ってきてしまいました。 >あらかじめ該当アクティビティから getFragmentManager しておいたものを使えるようにする よろしければこのやり方を詳しく教えて頂けますか? 無理であればあきらめて、アクティビティへの遷移に変えようと思います。
jimbe

2019/12/19 13:08

> newしたアクティビティは空っぽなので 「new したフラグメントはまだアクティビティと繋がっていないので」 ですね. 上のコメントで書きました通り, このクラスがフラグメントが乗るべき(R.id.containerがある)アクティビティとどういう関係にあるのかが分かりません. Realm がどういうものなのかを知らないということもあります. MemoAdapter は (R.id.containerがある)アクティビティで new されていたりはしないのでしょうか.
kashikoma

2019/12/19 14:10

newしたアクティビティについてご指摘ありがとうございます。 MemoAdapterクラスがnewされているフラグメントと、そのフラグメントが表示されるcontainerを持つアクティビティのコードを追記致しました。 アクティビティの中では、Adapterはnewされていません。 ご迷惑をおかけしてしまい申し訳ありません。
jimbe

2019/12/19 14:21 編集

ご提示いただきありがとうございます. 見た所, フラグメントの遷移ロジックが散らばっていて面倒な感じがします. フラグメントの置き換えロジックを MemoListActivity のメソッドとして定義し, MemoListActivity の参照を各フラグメントに渡して必要に応じて置き換えロジックを呼ぶ形にするのは如何でしょうか. 後ほど回答に追記してみます. (コンパイルが通らないのでテストは出来ないと思いますが.)
kashikoma

2019/12/20 09:12

とても良さそうな方法を考えて頂き本当に助かります。 確かに新規作成ボタンも同じ遷移先なので1か所にまとめた方がわかりやすいですね。 アダプタにアクティビティを設定するメソッドも以前自分でやってみた時は勘違いばかりで失敗したので、良い書き方が分かってためになりました。 エラーの原因についても理解が深まったので今後に活かしていきたいと思います。 MemoAdapterのsetActivityメソッドではmemoListActivityに値が渡されているのですが、アイテムクリックで遷移するときのonClick内でのmemoListActivityがnullとなってしまい、解決できません。 memoListActivity.replaceToEditMemoFragment(id); 遷移後の動作については問題ないことを新規作成ボタンから確認できました。 しつこくて申し訳ないのですが最後にこの部分について何かアドバイスをいただけますと幸いです。
jimbe

2019/12/20 09:30

> アイテムクリックで遷移するときのonClick内でのmemoListActivityがnullとなってしまい おや…新規作成ボタンでは遷移するのですね. MemoListFragment の onAttach/onDetach で MemoListFragment 内の memoListActivity への設定と同時に MemoAdapter へ設定していますので, MemoAdapter を作り直さない限り MemoListFragment の変数と同期していると思うのですが。 MemoListFragment.adapter は private ですから付け替えは出来ないですね. onAttach/onDetach や MemoAdapter の各所にログを入れる等で, MemoAdapter.memoListActivity への設定が出来ているか, いつ null になっているかを調べて頂けますでしょうか.
kashikoma

2019/12/20 11:46

文字数制限あるのでコメントにて失礼します。 //setActivity1,2は、それぞれMemoAdapter.setActivity()のthis.memoListActivity = mActivity;の直前・直後のログ //onDetach1,2は、それぞれMemoListFragment.onDetach()のmemoListActivity = null;の直前・直後のログ //1.MemoListFragmentを表示させたとき 12-20 18:52:21.462 8049-8049/com.j16390mf.memo D/MemoListFragment: onAttach = com.j16390mf.memo.MemoListActivity@39e0cf17 12-20 18:52:21.462 8049-8049/com.j16390mf.memo D/MemoAdapter: setActivity1 = null //setActivity()で アクティビティを設定する前 12-20 18:52:21.462 8049-8049/com.j16390mf.memo D/MemoAdapter: setActivity2 = com.j16390mf.memo.MemoListActivity@39e0cf17 //setActivity()でアクティビティを設定した後 -------------------------------- //2.新規作成ボタン押したとき 12-20 18:52:59.913 8049-8049/com.j16390mf.memo D/MemoListFragment: onClick fab = com.j16390mf.memo.MemoListActivity@39e0cf17 12-20 18:52:59.920 8049-8049/com.j16390mf.memo D/MemoListFragment: onDetach1 = com.j16390mf.memo.MemoListActivity@39e0cf17 //onDetach()でmemoListActivityにnullを設定する前 12-20 18:52:59.920 8049-8049/com.j16390mf.memo D/MemoListFragment: onDetach2 = null //nullを設定した後 12-20 18:52:59.920 8049-8049/com.j16390mf.memo D/MemoAdapter: setActivity1 = null //onDetach()からアクティビティをnullに設定する前 12-20 18:52:59.920 8049-8049/com.j16390mf.memo D/MemoAdapter: setActivity2 = null //onDetach()からアクティビティをnullに設定した後 -------------------------------- //3.遷移先のEditMemoFragmentからMemoListFragmentに戻った時 12-20 18:53:36.111 8049-8049/com.j16390mf.memo D/MemoListFragment: onAttach = com.j16390mf.memo.MemoListActivity@39e0cf17 12-20 18:53:36.111 8049-8049/com.j16390mf.memo D/MemoAdapter: setActivity1 = null //setActivity()で アクティビティを設定する前 12-20 18:53:36.111 8049-8049/com.j16390mf.memo D/MemoAdapter: setActivity2 = com.j16390mf.memo.MemoListActivity@39e0cf17 //setActivity()でアクティビティを設定した後 -------------------------------- //4.アイテムクリック 12-20 18:54:13.627 8049-8049/com.j16390mf.memo D/MemoAdapter: id onClick itemView = 20191217204811 //クリックしたアイテムのidは正しく入っている 12-20 18:54:13.627 8049-8049/com.j16390mf.memo D/MemoAdapter: onClick itemView = null //memoListActivityがnullになった 12-20 18:54:13.628 8049-8049/com.j16390mf.memo D/AndroidRuntime: Shutting down VM 12-20 18:54:13.628 8049-8049/com.j16390mf.memo E/AndroidRuntime: FATAL EXCEPTION: main Process: com.j16390mf.memo, PID: 8049 java.lang.NullPointerException: Attempt to invoke virtual method 'void com.j16390mf.memo.MemoListActivity.replaceToEditMemoFragment(java.lang.String)' on a null object reference at com.j16390mf.memo.MemoAdapter$1.onClick(MemoAdapter.java:56) at android.view.View.performClick(View.java:4799) at android.view.View$PerformClick.run(View.java:19938) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5384) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:702)
kashikoma

2019/12/20 12:26

見づらいですが4つの操作でそれぞれどうなってるか調べたつもりです。 2.新規作成ボタンを押したとき 12-20 18:52:59.920 8049-8049/com.j16390mf.memo D/MemoAdapter: setActivity1 = null //onDetach()からアクティビティをnullに設定する前 ここ気になったというか分からなかったんですが、 MemoListFragmentを表示させたときにアクティビティ設定したのにnullになっているのはおかしいですかね…
jimbe

2019/12/20 12:35 編集

3でMemoListFragmentに戻った時点で onAttach の setActivity で設定はされているのに, アイテムクリック時には null になっているんですか. その間に MemoAdapter.memoListActivity もしくは adapter が変わるような処理はあるでしょうか... 修正された MemoAdapter 等をご提示頂くほうが早いでしょうか.
jimbe

2019/12/20 12:35

新規作成ボタンを押すと, MemoListFragment が detach されて EditMemoFragment が attach されますので, 一旦 null になることになります. その後 MemoListFragment に戻ればまた attach されますので, setActivity が実行されることになります.
jimbe

2019/12/20 14:04

あ...上のコメント勘違いしてますね, null を設定する"前" ですか. ...何が起きているのでしょう.
kashikoma

2019/12/21 05:36 編集

・修正後 MemoAdapter public class MemoAdapter extends RealmRecyclerViewAdapter<Memo, MemoAdapter.MemoViewHolder> {  private OrderedRealmCollection<Memo> mDataset;  private MemoListActivity memoListActivity;  private static final String TAG = "MemoAdapter";  //フラグメント遷移処理メソッドを持つアクティビティを設定  void setActivity(MemoListActivity mActivity) {   Log.d(TAG, "setActivity1 = " + memoListActivity);   this.memoListActivity = mActivity;   Log.d(TAG, "setActivity2 = " + memoListActivity);  }  MemoAdapter(OrderedRealmCollection<Memo> memoDataset) {   super(memoDataset, true);   this.mDataset = memoDataset;   setHasStableIds(true);  }  @Override  public MemoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {   View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_memolist, parent, false);   return new MemoViewHolder(view);  }  @Override  public void onBindViewHolder(final MemoViewHolder holder, final int position){   final Memo obj = getItem(position);   holder.memo.setText(obj.getMemo());   holder.id.setText(obj.getId());   // アイテムクリックされたら編集画面へ   holder.itemView.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {     final String id = obj.getId();     Log.d(TAG, "id onClick itemView = " + id);     Log.d(TAG, "onClick itemView = " + memoListActivity);     memoListActivity.replaceToEditMemoFragment(id);    }   });  }  @Override  public int getItemCount() {   return mDataset.size();  }  static class MemoViewHolder extends RecyclerView.ViewHolder {   TextView memo;   TextView id;   MemoViewHolder(View view) {    super(view);    memo = view.findViewById(R.id.memoContent);    id = view.findViewById(R.id.memoId);   }  } }
kashikoma

2019/12/21 05:44

・修正後 MemoListFragment onAttachでは、adapterがnullにならないようデータを渡しておくため、 onCreateView内の一部と同じ処理を記述しました。 memoListActivityが途中でnullになってしまうのは、この同じ処理が2回行われていることと関係があったりするのかもと思いました。他にadapterが途中で変わるようなところはないと思うので…。 public class MemoListFragment extends Fragment {  private static final String TAG = "MemoListFragment";  private FloatingActionButton fab;  private RecyclerView recyclerView;  private Realm realm;  private MemoAdapter adapter;  private MemoListActivity memoListActivity;  // インスタンス生成  public static MemoListFragment newInstance(){   MemoListFragment f = new MemoListFragment();   Bundle args = new Bundle();   f.setArguments(args);   return f;  }  //アクティビティに載せられると呼ばれる  @Override  public void onAttach(Context context) {   super.onAttach(context);   if (context instanceof MemoListActivity) {    realm = Realm.getDefaultInstance(); // Realmをインスタンス化    final RealmResults<Memo> result = realm.where(Memo.class).findAll().sort("id", Sort.DESCENDING);    adapter = new MemoAdapter(result); // 結果をアダプターに渡す    memoListActivity = (MemoListActivity) context;    Log.d(TAG, "onAttach = " + memoListActivity);    adapter.setActivity(memoListActivity);    Log.d(TAG, "adapter.setActivity = " + memoListActivity);   }  }  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {   View view = inflater.inflate(R.layout.fragment_memo_list, container, false);   fab = view.findViewById(R.id.intentEditMemo);   realm = Realm.getDefaultInstance(); // Realmをインスタンス化   final RealmResults<Memo> result = realm.where(Memo.class).findAll().sort("id", Sort.DESCENDING);   adapter = new MemoAdapter(result); // 結果をアダプターに渡す   recyclerView = view.findViewById(R.id.memoList);   recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));   recyclerView.setAdapter(adapter);   recyclerView.setHasFixedSize(true);   recyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));   return view;  }  @Override  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {   super.onViewCreated(view, savedInstanceState);  }  @Override  public void onStart() {   super.onStart();   //新規作成ボタン   fab.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View view) {     memoListActivity.replaceToEditMemoFragment("");     Log.d(TAG, "onClick fab = " + memoListActivity);    }   });  }  @Override  public void onDestroy() {   super.onDestroy();   recyclerView.setAdapter(null);   realm.close();  }  //アクティビティから外されると呼ばれる  @Override  public void onDetach() {   super.onDetach();   Log.d(TAG, "onDetach1 = " + memoListActivity);   memoListActivity = null;   Log.d(TAG, "onDetach2 = " + memoListActivity);   adapter.setActivity(null);  } }
kashikoma

2019/12/21 05:46

onCreateView内のログもとってみます
kashikoma

2019/12/21 08:09

解決しました。 やっぱり、MemoListFragmentでadapterを2回newしてたのがよくなかったみたいです。 (1回目がonAttach内、2回目がonCreateView内) //MemoListFragment表示時 12-21 16:18:40.077 20312-20312/com.j16390mf.memo D/MemoListFragment: onAttach.adapter after new = com.j16390mf.memo.MemoAdapter@1bc35f61 12-21 16:18:40.077 20312-20312/com.j16390mf.memo D/MemoListFragment: onAttach = com.j16390mf.memo.MemoListActivity@39e0cf17 12-21 16:18:40.077 20312-20312/com.j16390mf.memo D/MemoAdapter: setActivity1 = null 12-21 16:18:40.078 20312-20312/com.j16390mf.memo D/MemoAdapter: setActivity2 = com.j16390mf.memo.MemoListActivity@39e0cf17 12-21 16:18:40.145 20312-20312/com.j16390mf.memo D/MemoListFragment: onCreateView.adapter before new = com.j16390mf.memo.MemoAdapter@1bc35f61 12-21 16:18:40.146 20312-20312/com.j16390mf.memo D/MemoListFragment: onCreateView.adapter after new = com.j16390mf.memo.MemoAdapter@39e4ad9c -------------------------------- adapterが最初に new されたときのadapter(onAttach内):@1bc35f61 adapterが2回目に new されたときのadapter(onCreateView内):@39e4ad9c こんな感じで、当たり前なんですがadapterが新しいものになってしまっていました。 ですのでonCreateView内の重複している部分を削除して、onAttachで1回だけnewするようにしたところ、onCreateViewに処理が移ったあともadapterが同じものになっていることが確認でき、遷移もできました。 12-21 16:34:14.081 21629-21629/com.j16390mf.memo D/MemoListFragment: onAttachでnewする前のadapter = com.j16390mf.memo.MemoAdapter@1bc35f61 12-21 16:34:14.081 21629-21629/com.j16390mf.memo D/MemoListFragment: memoListActivity = com.j16390mf.memo.MemoListActivity@39e27796 12-21 16:34:14.081 21629-21629/com.j16390mf.memo D/MemoAdapter: setActivity()で設定する前のmemoListActivity = null 12-21 16:34:14.081 21629-21629/com.j16390mf.memo D/MemoAdapter: setActivity()で設定した後のmemoListActivity = com.j16390mf.memo.MemoListActivity@39e27796 12-21 16:34:14.107 21629-21629/com.j16390mf.memo D/MemoListFragment: onCreateViewでのadapter = com.j16390mf.memo.MemoAdapter@1bc35f61 //onAttachでnewした時と同じ値 12-21 16:34:14.108 21629-21629/com.j16390mf.memo D/MemoListFragment: onCreateViewでのmemoListActivity = com.j16390mf.memo.MemoListActivity@39e27796 -------------------------------- 解決まで長い間お力添えを頂きまして誠にありがとうございました。
jimbe

2019/12/21 08:29 編集

解決されたようで良かったです. 私のほうで勘違いがありまして, ほぼ onAttach/onDetach を使ったことが無かったもので onCreate類の後に呼ばれるかと思っていたのですが, 調べると onCreate より前, ほぼ一番最初に呼ばれるようです. ですので, 私の書いたコードのみでは, onCreateView で MemoListAdapter を new する前に onAttach で使用することになり, onAttach 内で NullPointerException が発生することになるのですが, それがご提示頂いたログでは発生せず動作していたので少々疑問ではありました. kashikoma さんのほうで対策されて onCreateView の new の部分を onAttach に入れていらっしゃったということで納得しました. 結果 onCreateView と処理が重なってしまって分かり難いバグとなってしまいましたが, 元はと言えば onAttach でまだ生成されていない adapter を使用するようなコードを書いてしまった私の所為です. お手数お掛けして御免なさい.
jimbe

2019/12/21 08:58

そして, もっと大事といいますか, onAttach で アクティビティを得ていましたが, 考えてみれば onCreateView 時点で getActivity メソッドが機能する(onAttach の context パラメータと同じものが返される)と思います. ですので, MemoListFragment を最初に戻し(onAttach/onDetachを消し,onCreateView内でadapter を生成する), adapter 生成直後に memoListActivity = (MemoListActivity)getActivity(); adapter.setActivity(memoListActivity); の2行を加えることでも良かったかもしれません.
guest

0

NullPointerException とはnullのポインタに対してアクセスさせると出るものです

fragment.getFragmentManager().beginTransaction().replace(R.id.container, fragment).commit();

まずは、
fragment.getFragmentManager()
fragment.getFragmentManager().beginTransaction()
の返り値がnullになってないかチェックしてみてはどうでしょう

投稿2019/12/18 08:55

y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kashikoma

2019/12/18 12:32

回答いただきありがとうございます。 やり方が間違っているかもしれないですが、ログをとってみました。 fragment.getFragmentManager()がnullになっていて、そこでエラーとなりました。 でもこの結果から何を判断したらよいのかわかりません…orz //該当部分 EditMemoFragment fragment = new EditMemoFragment(); FragmentManager manager = fragment.getFragmentManager(); Log.d(TAG, "manager : " + manager); FragmentTransaction transaction = manager.beginTransaction(); Log.d(TAG, "transaction : " + transaction); //Log 12-18 21:21:19.375 15791-15791/com.kashikoma.memo D/MemoAdapter: manager : null 12-18 21:21:19.392 15791-15791/com.kashikoma.memo E/AndroidRuntime: FATAL EXCEPTION: main Process: com.j16390mf.memo, PID: 15791 java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.app.FragmentTransaction android.support.v4.app.FragmentManager.beginTransaction()' on a null object reference . . .
kashikoma

2019/12/18 12:34

Logのパッケージ名隠したかったので書き換えていたのですが最後のところで書き換え忘れてました。混乱してしまったらすみません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問