java.lang.IllegalStateException:未附加到Activity的片段

时间:2015-02-23 11:36:24

标签: android android-fragments android-activity android-volley illegalstateexception

在进行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();
                        }
                    }
                });

12 个答案:

答案 0 :(得分:178)

由于两个因素的综合影响,会发生此错误:

  • HTTP请求完成后,调用onResponse()onError()(在主线程上工作),而不知道Activity是否仍在前台。如果Activity消失(用户在别处导航),getActivity()将返回null。
  • Volley 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();
        }
    }
}

答案 1 :(得分:44)

片段生命周期非常复杂且充满了错误,请尝试添加:

Activity activity = getActivity(); 
if (isAdded() && activity != null) {
...
}

答案 2 :(得分:13)

我找到了非常简单的解决方案isAdded()方法,它是识别此当前片段是否附加到其活动的片段方法之一。

我们可以在片段类中随处使用它,如:

if(isAdded())
{

// using this method, we can do whatever we want which will prevent   **java.lang.IllegalStateException: Fragment not attached to Activity** exception.

}

答案 3 :(得分:8)

i may be late but may help someone ..... The best solution for this is to create a global application class instance and call it in the particular fragment where your activity is not being attached

as like below

icon = MyApplication.getInstance().getString(R.string.weather_thunder);

Here is application class

public class MyApplication extends Application {

    private static MyApplication mInstance;
    private RequestQueue mRequestQueue;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    public static synchronized MyApplication getInstance() {
        return mInstance;
    }
}

答案 4 :(得分:8)

例外: java.lang.IllegalStateException:Fragment

DeadlineListFragment {ad2ef970}未附加到活动

类别:生命周期

描述:在后台线程(例如AsyncTask)中执行耗时的操作时,同时创建了一个新的Fragment,并在后台线程完成之前将其分离到Activity。 UI线程中的代码(例如,onPostExecute)调用分离的片段,抛出此类异常。

修复解决方案:

  1. 暂停或停止时取消后台线程 片段

  2. 使用isAdded()检查片段是否已附加 然后从活动中获取getResources()。

答案 5 :(得分:2)

如果要实例化某个无法实例化的片段,则会发生此错误:

Fragment myFragment = MyFragment.NewInstance();


public classs MyFragment extends Fragment {
  public void onCreate() {
   // Some error here, or anywhere inside the class is preventing it from being instantiated
  }
}

在我的情况下,当我尝试使用时,我遇到了这个:

private String loading = getString(R.string.loading);

答案 6 :(得分:2)

在片段中使用isAdded() 如果片段当前附加到Activity,它将返回true。

如果要查看活动内部

 Fragment fragment = new MyFragment();
   if(fragment.getActivity()!=null)
      { // your code here}
      else{
       //do something
       }

希望它会帮助某人

答案 7 :(得分:1)

我采用以下方法来处理此问题。创建了一个新类,它充当了像这样的活动方法的包装器

public class ContextWrapper {
    public static String getString(Activity activity, int resourceId, String defaultValue) {
        if (activity != null) {
            return activity.getString(resourceId);
        } else {
            return defaultValue;
        }
    }

    //similar methods like getDrawable(), getResources() etc

}

现在我需要从片段或活动中访问资源,而不是直接调用方法,我使用此类。如果活动context不是null,它会返回资产的值,如果context为空,它会传递一个默认值(也是由调用者指定的功能)。

重要这不是一个解决方案,这是一种可以优雅地处理此崩溃的有效方法。如果你将活动实例变为null,你会想要添加一些日志,如果可能的话,尝试修复它。

答案 8 :(得分:0)

当片段没有上下文时会发生这种情况,因此getActivity()方法返回null。 检查您是否在获取之前使用上下文,或者活动是否不再存在。在fragment.onCreate和api响应之后使用context通常会出现这个问题

答案 9 :(得分:0)

有时,此异常是由支持库实现中的错误引起的。最近我不得不从26.1.0降级到25.4.0以摆脱它。

答案 10 :(得分:0)

每当调用不可用的上下文或调用它时为null时,就会出现此问题。当您在主活动线程的后台线程或后台线程的上下文中调用主活动线程的上下文时,可能会出现这种情况。

例如,我更新了我的共享首选项字符串,如下所示。

editor.putString("penname",penNameEditeText.getText().toString());
editor.commit();
finish();

在它之后调用finish()。现在它的作用是,当提交在主线程上运行并停止任何其他Async提交,直到它完成为止。所以它的上下文一直存在,直到写完成。因此,先前的上下文是实时的,导致错误发生。

因此,如果某些代码存在此上下文问题,请确保重新检查代码。

答案 11 :(得分:0)

因此,基本思路是,您正在进入 onDetach 生命周期的片段上运行 UI操作

发生这种情况时,片段将脱离堆栈并丢失 Activity 的上下文。

因此,当您调用与UI相关的功能(例如,调用进度微调器)并且要离开片段时,请检查片段是否已添加到堆栈中,如下所示:

if(isAdded){ progressBar.visibility=View.VISIBLE }