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

java.lang.IllegalStateException: Fragment not attached to Activity

我在拨打 API 电话时很少遇到此错误。

java.lang.IllegalStateException: Fragment  not attached to Activity

我尝试将代码放入 isAdded() 方法中以检查片段当前是否已添加到其 activity 中,但我仍然很少收到此错误。我不明白为什么我仍然收到此错误。我该如何预防?

在线显示错误-

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

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

  • HTTP 请求完成后会调用 onResponse()onError()(在主线程上工作),而不知道 Activity 是否仍在前台。如果 Activity 消失了(用户导航到其他地方),getActivity() returns null.
  • Volley Response 表示为匿名内部 class,它隐含地持有对外部 Activity class 的强引用。这会导致 classic 内存泄漏。

要解决这个问题,你应该总是这样做:

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

    // etc ...

}

此外,在 onError() 方法中也使用 isAdded()

@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();
        }
    }
}

Fragment生命周期很复杂,bug多,尝试补充:

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

如果您正在实例化无法实例化的片段,则会发生此错误:

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);

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

我们可以在片段 class 的任何地方使用它,例如:

if(isAdded())
{

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

}

我可能会迟到但可能会帮助某人..... 最好的解决方案是创建一个全局应用程序 class 实例并在未附加 activity 的特定片段中调用它

如下图

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

这是应用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;
    }
}

当片段没有上下文时会发生这种情况,因此 getActivity() 方法 return 无效。 在获取上下文之前检查是否使用了它,或者 Activity 是否不再存在。在 fragment.onCreate 和 api 响应之后使用上下文通常会导致此问题

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

我采用了以下方法来处理这个问题。创建了一个新的 class 作为 activity 方法的包装器,例如

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

}

现在,无论我需要从片段或活动访问资源,而不是直接调用方法,我都使用这个 class。如果 activity context 不是 null 它 returns 资产的价值,如果 context 为空,它会传递一个默认值(也由函数的调用者指定。

重要 这不是解决方案,而是一种可以优雅地处理此崩溃的有效方法。如果您将 activity 实例设置为 null,您可能希望添加一些日志,并在可能的情况下尝试修复该问题。

异常: java.lang.IllegalStateException:片段

DeadlineListFragment{ad2ef970} 未附加到 Activity

类别:生命周期

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

修复方案:

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

  2. 使用isAdded()检查片段是否被附加 然后从 activity.

  3. 到 getResources()

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

例如,我更新了我的共享偏好字符串,如下所示。

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

然后立即调用 finish()。现在它所做的是当提交在主线程上运行并停止任何其他异步提交,直到它完成。因此它的上下文在写入完成之前一直有效。因此之前的上下文是实时的,导致错误发生。

因此,如果某些代码存在此上下文问题,请务必重新检查您的代码。

在片段中使用isAdded() 如果片段当前附加到 Activity.

,它将 return 为真

如果你想在里面查看Activity

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

希望对大家有所帮助

所以基本的想法是,你是 运行 一个 UI 操作 在进入 onDetach[ 的片段上=22=]生命周期。

当发生这种情况时,片段将离开堆栈并丢失 Activity.

的上下文

因此,当您调用 UI 相关函数时,例如调用进度微调器并且您想离开片段时,请检查片段是否已添加到堆栈中,如下所示:

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