IllegalStateException: 未附加到 Activity 的片段

在进行 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();
}
}
});
183347 次浏览

这一错误是由两个因素的综合作用造成的:

  • HTTP 请求完成后,调用 onResponse()onError()(它们在主线程上工作) ,而不知道 Activity是否仍然在前台。如果 Activity消失(用户导航到其他地方) ,则 getActivity()返回 null。
  • Volley Response表示为一个匿名内部类,它隐式地保存对外部 Activity类的强引用。这将导致典型的内存泄漏。

要解决这个问题,你应该经常这样做:

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

片段生命周期非常复杂,充满了 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);

我发现非常简单的解决方案 增补()方法,这是片段方法之一,以确定这个当前的片段是附加到其活动或没有。

我们可以像在片段类的任何地方一样使用它,比如:

if(isAdded())
{


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


}

我可能会迟到,但可能会帮助别人... ..。 最好的解决方案是创建一个全局应用程序类实例,并在没有附加活动的特定片段中调用它

如下所示

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

这是应用程序类

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 ()方法返回 null。 检查您是否在获取之前使用了上下文,或者该活动是否不再存在。OnCreate 和 after api 响应中使用 context 通常可以解决这个问题

有时,此异常是由支持库实现中的 bug 引起的。最近我不得不把它从26.1.0降级到25.4。

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

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,则传递一个默认值(也由函数的调用方指定)。

重点 这不是一个解决方案,这是一个有效的方法,您可以妥善处理这个崩溃。在活动实例为 null 的情况下,需要添加一些日志,如果可能的话,尝试修复这个问题。

例外: java.lang. IllegalStateException: 片段

没有附加到活动的 DeadlineListFragment { ad2ef970}

类别: 生命周期

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

解决方案:

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

  2. 使用 isAdd ()检查是否附加了片段 然后从 activity 转到 getResources ()

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

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

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

然后马上调用 Finish ()。现在它所做的就是在主线程上运行提交,并且在提交完成之前停止任何其他异步提交。所以它的上下文是活的,直到写完为止。因此,前面的上下文是活动的,从而导致错误发生。

因此,如果有代码出现上下文问题,一定要重新检查代码。

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

如果您想检查活动内部

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

希望能帮到别人

因此,基本的想法是,您正在 分离生命周期中的一个片段上运行一个 UI 操作

当这种情况发生时,片段正在离开堆栈并丢失 活动的上下文。

因此,当你调用 UI 相关函数时,比如调用进度旋转器,你想检查片段是否被添加到堆栈中,像这样:

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

这能解决你的问题。

把这个添加到你的碎片上

Activity activity;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
activity = context instanceof Activity ? (Activity) context : null;
}

然后用 活动改变 GetContext ()、 getActivity ()、饥饿活动()或饥饿情境()