1. ホーム
  2. android

[解決済み] java.lang.IllegalStateException: フラグメントがアクティビティにアタッチされていない

2022-04-23 17:33:40

質問

APIコール時に稀にこのエラーが発生することがあります。

java.lang.IllegalStateException: Fragment  not attached to Activity

の中にコードを入れてみました。 isAdded() メソッドを使用して、フラグメントが現在そのアクティビティに追加されているかどうかをチェックしますが、それでもこのエラーはほとんど発生しません。なぜこのエラーが発生するのか理解できません。どうすればこのエラーを防ぐことができるのでしょうか?

行にエラーが表示される...

cameraInfo.setId(getResources().getString(R.string.camera_id));

以下は、私が作っているapiコールのサンプルです。

SAPI.getInfo(getActivity(),
                new APIResponseListener() {
                    @Override
                    public void onResponse(Object response) {


                        cameraInfo = new SInfo();
                        if(isAdded()) {
                            cameraInfo.setId(getResources().getString(R.string.camera_id));
                            cameraInfo.setName(getResources().getString(R.string.camera_name));
                            cameraInfo.setColor(getResources().getString(R.string.camera_color));
                            cameraInfo.setEnabled(true);
                        }


                    }

                    @Override
                    public void onError(VolleyError error) {
                        mProgressDialog.setVisibility(View.GONE);
                        if (error instanceof NoConnectionError) {
                            String errormsg = getResources().getString(R.string.no_internet_error_msg);
                            Toast.makeText(getActivity(), errormsg, Toast.LENGTH_LONG).show();
                        }
                    }
                });

解決方法は?

このエラーは、2つの要因が複合的に作用することで発生します。

  • HTTP リクエストが完了したとき、次のいずれかを呼び出します。 onResponse() または onError() (メインスレッドで動作する)のかどうかがわからずに Activity がまだフォアグラウンドにあるかどうか。もし Activity が消えている(ユーザーが別の場所に移動した)。 getActivity() は null を返します。
  • ザ・ボレー Response は無名の内部クラスとして表現され、このクラスは暗黙のうちに外部の Activity クラスがあります。この結果、典型的なメモリーリークが発生します。

この問題を解決するために、必ず行うべきことは

Activity activity = getActivity();
if(activity != null){

    // etc ...

}

を使用し、さらに isAdded() の中に onError() メソッドも同様です。

@Override
public void onError(VolleyError error) {

    Activity activity = getActivity(); 
    if(activity != null && isAdded())
        mProgressDialog.setVisibility(View.GONE);
        if (error instanceof NoConnectionError) {
           String errormsg = getResources().getString(R.string.no_internet_error_msg);
           Toast.makeText(activity, errormsg, Toast.LENGTH_LONG).show();
        }
    }
}