java.lang.IllegalStateException:片段未附加到活动


148

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

cameraInfo.setId(getActivity()。getResources()。getString(R.string.camera_id));
Ashwin H

Answers:


203

由于两个因素的共同作用,导致发生此错误:

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

2
AsyncTask从中使用Volley请求和s时Activity,没有避免NPE的简单方法。Activity当线程之一在后台执行某项操作时,用户总是有可能远离当前导航,然后当线程完成onPostExecute()或被onResponse()调用时,就没有了Activity。您所能做的就是检查代码中各个点的空引用,但这不是防弹的方法:)
YS 2015年

2
如果您尚未以通用/全局方式进行说明,则android猴子测试(adb shell猴子)非常擅长于根除此错误。
Groovee60年

5
则i长满,最后一个公共布尔值i长满(返回){return mActivity!= null && mAdded; }
lannyf '16

2
@ruselli:检查added布尔值标志和当前Activity实例是否null存在。
YS

1
@gauravjain避免直接从Fragments发出异步请求(例如HTTP调用)。从活动中执行此操作,应该没问题。另外,从FragmentManager中清除Fragment引用,这是一个好习惯,也是避免内存泄漏的最佳方法。
YS

56

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

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

2
我应该放在哪里?
VaclovasRekašiusJr.

1
@VaclovasRekašiusJr。您似乎很想从片段内部访问Activity的任何地方。好玩!
TylerJames

2
如果activity == null我应该怎么做。保持我的应用程序@Miroslav的有效性
Pavel

查看iFyreed(),您可能会发现“ activity!= null”不是多余的
BertKing

@BertKing- return mHost != null && mAdded;这就是fragment.iwego()方法中的内容。我以为如果跟踪mHost就是一个Activity,但似乎mHost在FragmentActivity内部。所以,也许你是对的。有什么补充吗?
约翰尼五号

14

我发现了一个非常简单的解决方案 iwego()方法,该方法是一种片段方法,用于识别此当前片段是否已附加到其活动中。

我们可以像这样在片段类中的任何地方使用它:

if(isAdded())
{

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

}

12

例外: java.lang.IllegalStateException:片段

DeadlineListFragment {ad2ef970}未附加到活动

类别:生命周期

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

解决方案:

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

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


11

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

如下所示

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

1
是的,这种方法也被广泛使用。
CoolMind

1
这不是明智的选择。FragmentContext和ApplicationContext具有不同的样式。片段上下文可能具有深色主题,自定义样式,语言环境等。这将从不同文件中提取颜色,字符串资源。虽然ApplicationContext可能无法提取正确的资源。如果没有Context,则不应尝试呈现该资源。
Jemshit Iskenderov

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

2

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

如果您想检查活动内部

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

希望对别人有帮助


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则返回资产的值,如果活动为contextnull,则传递默认值(该值也由函数的调用者指定)。

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


0

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


0

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


不,我没有,但也许我应该创建一个。
Bord81年

0

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

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

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

然后在其后调用finish()。现在所做的是,当提交在主线程上运行时,它将停止所有其他异步提交(如果要提交,直到完成)。因此,它的上下文仍然有效,直到写入完成。因此,先前的上下文处于活动状态,从而导致发生错误。

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


您如何设法解决此问题?我在异步线程中调用它,现在遇到了这个问题。
西蒙

只需确保写操作完成,然后仅在写操作完成之前杀死上下文。
Prashant Paliwal
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.