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

时间:2022-12-05 20:32:44

I am rarely getting this error while making an API call.

在进行API调用时,我很少收到此错误。

java.lang.IllegalStateException: Fragment  not attached to Activity

I tried putting the code inside isAdded() method to check whether fragment is currently added to its activity but still i rarely gets this error. I fail to understand why I am still getting this error. How can i prevent it?

我尝试将代码放在isAdded()方法中,以检查片段当前是否已添加到其活动中但仍然很少出现此错误。我不明白为什么我仍然会收到此错误。我怎么能阻止它?

Its showing error on the line-

它在线上显示错误 -

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

Below is the sample api call that i am making.

以下是我正在制作的示例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 个解决方案

#1


133  

This error happens due to the combined effect of two factors:

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

  • The HTTP request, when complete, invokes either onResponse() or onError() (which work on the main thread) without knowing whether the Activity is still in the foreground or not. If the Activity is gone (the user navigated elsewhere), getActivity() returns null.
  • HTTP请求完成后,调用onResponse()或onError()(在主线程上工作),而不知道Activity是否仍在前台。如果Activity消失(用户在其他地方导航),getActivity()将返回null。
  • The Volley Response is expressed as an anonymous inner class, which implicitly holds a strong reference to the outer Activity class. This results in a classic memory leak.
  • Volley Response表示为一个匿名内部类,它隐含地保存了对外部Activity类的强引用。这导致经典的内存泄漏。

To solve this problem, you should always do:

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

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

    // etc ...

}

and also, use isAdded() in the onError() method as well:

而且,在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();
        }
    }
}

#2


32  

Fragment lifecycle is very complex and full of bugs, try to add:

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

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

#3


8  

I Found Very Simple Solution isAdded() method which is one of the fragment method to identify that this current fragment is attached to its Activity or not.

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

we can use this like everywhere in fragment class like:

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

if(isAdded())
{

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

}

#4


5  

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

#5


3  

Exception: java.lang.IllegalStateException: Fragment

例外:java.lang.IllegalStateException:Fragment

DeadlineListFragment{ad2ef970} not attached to Activity

DeadlineListFragment {ad2ef970}未附加到Activity

Category: Lifecycle

类别:生命周期

Description: When doing time-consuming operation in background thread(e.g, AsyncTask), a new Fragment has been created in the meantime, and was detached to the Activity before the background thread finished. The code in UI thread(e.g.,onPostExecute) calls upon a detached Fragment, throwing such exception.

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

Fix solution:

解决方案:

  1. Cancel the background thread when pausing or stopping the Fragment

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

  2. Use isAdded() to check whether the fragment is attached and then to getResources() from activity.

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

#6


2  

This error can happen if you are instantiating a fragment that somehow can't be instantiated:

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

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

In my case, i have met this when i tried to use:

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

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

#7


1  

I adopted the following approach for handling this issue. Created a new class which act as a wrapper for activity methods like this

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

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

}

Now wherever I need to access resources from fragments or activities, instead of directly calling the method, I use this class. In case the activity context is not null it returns the value of the asset and in case the context is null, it passes a default value (which is also specified by the caller of the function).

现在我需要从片段或活动中访问资源,而不是直接调用该方法,我使用此类。如果活动上下文不为null,则返回资产的值,如果上下文为null,则传递默认值(也由函数的调用者指定)。

Important This is not a solution, this is an effective way where you can handle this crash gracefully. You would want to add some logs in cases where you are getting activity instance as null and try to fix that, if possible.

重要这不是一个解决方案,这是一种可以优雅地处理此崩溃的有效方法。如果您将活动实例作为null,并且尝试解决此问题(如果可能),您可能希望添加一些日志。

#8


0  

this happen when the fragment does not have a context ,thus the getActivity()method return null. check if you use the context before you get it,or if the Activity is not exist anymore . use context in fragment.onCreate and after api response usually case this problem

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

#9


0  

Sometimes this exception is caused by a bug in the support library implementation. Recently I had to downgrade from 26.1.0 to 25.4.0 to get rid of it.

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

#10


0  

if you are using fragment

如果你使用片段

private HomePageActivity homePageActivity;

@Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        mView = inflater.inflate(R.layout.fragment_wish_list, container, false);

        initializeViews();

rowTextView.setBackgroundColor(homePageActivity.getResources().getColor(R.color.colorPrimary));


        return mView;
    }

private void initializeViews() {
        homePageActivity = (HomePageActivity) getActivity();
}


 @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof HomePageActivity) {
            homePageActivity = (HomePageActivity) context;
        }
    }

#11


0  

This issue occurs whenever you call a context which is unavailable or null when you call it. This can be a situation when you are calling main activity thread's context on a background thread or background thread's context on main activity thread.

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

For instance , I updated my shared preference string like following.

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

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

And called finish() right after it. Now what it does is that as commit runs on main thread and stops any other Async commits if coming until it finishes. So its context is alive until the write is completed. Hence previous context is live , causing the error to occur.

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

So make sure to have your code rechecked if there is some code having this context issue.

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

#12


0  

In Fragment use isAdded() It will return true if the fragment is currently attached to Activity.

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

If you want to check inside the Activity

如果要查看活动内部

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

Hope it will help someone

希望它会帮助某人

#1


133  

This error happens due to the combined effect of two factors:

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

  • The HTTP request, when complete, invokes either onResponse() or onError() (which work on the main thread) without knowing whether the Activity is still in the foreground or not. If the Activity is gone (the user navigated elsewhere), getActivity() returns null.
  • HTTP请求完成后,调用onResponse()或onError()(在主线程上工作),而不知道Activity是否仍在前台。如果Activity消失(用户在其他地方导航),getActivity()将返回null。
  • The Volley Response is expressed as an anonymous inner class, which implicitly holds a strong reference to the outer Activity class. This results in a classic memory leak.
  • Volley Response表示为一个匿名内部类,它隐含地保存了对外部Activity类的强引用。这导致经典的内存泄漏。

To solve this problem, you should always do:

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

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

    // etc ...

}

and also, use isAdded() in the onError() method as well:

而且,在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();
        }
    }
}

#2


32  

Fragment lifecycle is very complex and full of bugs, try to add:

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

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

#3


8  

I Found Very Simple Solution isAdded() method which is one of the fragment method to identify that this current fragment is attached to its Activity or not.

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

we can use this like everywhere in fragment class like:

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

if(isAdded())
{

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

}

#4


5  

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

#5


3  

Exception: java.lang.IllegalStateException: Fragment

例外:java.lang.IllegalStateException:Fragment

DeadlineListFragment{ad2ef970} not attached to Activity

DeadlineListFragment {ad2ef970}未附加到Activity

Category: Lifecycle

类别:生命周期

Description: When doing time-consuming operation in background thread(e.g, AsyncTask), a new Fragment has been created in the meantime, and was detached to the Activity before the background thread finished. The code in UI thread(e.g.,onPostExecute) calls upon a detached Fragment, throwing such exception.

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

Fix solution:

解决方案:

  1. Cancel the background thread when pausing or stopping the Fragment

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

  2. Use isAdded() to check whether the fragment is attached and then to getResources() from activity.

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

#6


2  

This error can happen if you are instantiating a fragment that somehow can't be instantiated:

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

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

In my case, i have met this when i tried to use:

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

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

#7


1  

I adopted the following approach for handling this issue. Created a new class which act as a wrapper for activity methods like this

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

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

}

Now wherever I need to access resources from fragments or activities, instead of directly calling the method, I use this class. In case the activity context is not null it returns the value of the asset and in case the context is null, it passes a default value (which is also specified by the caller of the function).

现在我需要从片段或活动中访问资源,而不是直接调用该方法,我使用此类。如果活动上下文不为null,则返回资产的值,如果上下文为null,则传递默认值(也由函数的调用者指定)。

Important This is not a solution, this is an effective way where you can handle this crash gracefully. You would want to add some logs in cases where you are getting activity instance as null and try to fix that, if possible.

重要这不是一个解决方案,这是一种可以优雅地处理此崩溃的有效方法。如果您将活动实例作为null,并且尝试解决此问题(如果可能),您可能希望添加一些日志。

#8


0  

this happen when the fragment does not have a context ,thus the getActivity()method return null. check if you use the context before you get it,or if the Activity is not exist anymore . use context in fragment.onCreate and after api response usually case this problem

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

#9


0  

Sometimes this exception is caused by a bug in the support library implementation. Recently I had to downgrade from 26.1.0 to 25.4.0 to get rid of it.

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

#10


0  

if you are using fragment

如果你使用片段

private HomePageActivity homePageActivity;

@Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        mView = inflater.inflate(R.layout.fragment_wish_list, container, false);

        initializeViews();

rowTextView.setBackgroundColor(homePageActivity.getResources().getColor(R.color.colorPrimary));


        return mView;
    }

private void initializeViews() {
        homePageActivity = (HomePageActivity) getActivity();
}


 @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof HomePageActivity) {
            homePageActivity = (HomePageActivity) context;
        }
    }

#11


0  

This issue occurs whenever you call a context which is unavailable or null when you call it. This can be a situation when you are calling main activity thread's context on a background thread or background thread's context on main activity thread.

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

For instance , I updated my shared preference string like following.

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

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

And called finish() right after it. Now what it does is that as commit runs on main thread and stops any other Async commits if coming until it finishes. So its context is alive until the write is completed. Hence previous context is live , causing the error to occur.

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

So make sure to have your code rechecked if there is some code having this context issue.

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

#12


0  

In Fragment use isAdded() It will return true if the fragment is currently attached to Activity.

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

If you want to check inside the Activity

如果要查看活动内部

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

Hope it will help someone

希望它会帮助某人