Ява.ленг.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 ответов


эта ошибка происходит из-за комбинированного влияния двух факторов:

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

жизненный цикл фрагмента очень сложный и полный ошибок, попробуйте добавить:

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

Я Нашел Очень Простое Решение isAdded() метод, который является одним из методов фрагмента, чтобы определить, что этот текущий фрагмент прикреплен к его деятельности или нет.

мы можем использовать это как везде в классе фрагмента как:

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

исключения: java.ленг.IllegalStateException: Фрагмент

DeadlineListFragment{ad2ef970} не присоединен к Activity

категория: жизненный цикл

описание: при выполнении трудоемкой операции в фоновом потоке (e.g, AsyncTask), новый фрагмент был создан тем временем и был отделен от действия до завершения фонового потока. Код в потоке пользовательского интерфейса (например,onPostExecute) вызывает отдельный фрагмент, выбрасывающий такое исключение.

решение:

  1. отмена фонового потока при приостановке или остановке Фрагмент

  2. используйте isAdded (), чтобы проверить, прикреплен ли фрагмент а затем getResources () из activity.


эта ошибка может произойти, если вы создаете экземпляр фрагмента, который каким-то образом не может быть создан:

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

Я принят следующий подход для решения этой проблемы. Создал новый класс, который действует как оболочка для методов действия, подобных этому

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, он передает значение по умолчанию (которое также указывается вызывающим функция.)

важно это не решение, это эффективный способ, где вы можете справиться с этой аварии изящно. Вы хотели бы добавить некоторые журналы в случаях, когда вы получаете экземпляр activity как null и пытаетесь исправить это, если это возможно.


это происходит, когда фрагмент не имеет контекста ,поэтому метод getActivity()возвращает null. проверьте, используете ли вы контекст, прежде чем получить его,или если действие больше не существует . используйте контекст во фрагменте.onCreate и после ответа api обычно бывает эта проблема


иногда это исключение вызвано ошибкой в реализации библиотеки поддержки. Недавно мне пришлось понизить рейтинг с 26.1.0 до 25.4.0, чтобы избавиться от него.


Если вы используете 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;
        }
    }

эта проблема возникает при вызове контекста, который недоступен или null при вызове. Это может быть ситуация, когда вы вызываете контекст основного потока действия в фоновом потоке или контекст фонового потока в основном потоке действия.

например, я обновил свою общую строку предпочтений следующим образом.

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

и вызвал finish () сразу после него. Теперь он делает то, что AS commit работает в основном потоке и останавливает любые другие асинхронные коммиты, если иду, пока не закончу. Таким образом, его контекст жив, пока запись не будет завершена. Следовательно, предыдущий контекст является живым, вызывая ошибку.

поэтому убедитесь, что ваш код перепроверен, если есть какой-то код, имеющий эту проблему контекста.


В использовать фрагмент isAdded() Он вернет true, если фрагмент в настоящее время присоединен к Activity.

Если вы хотите проверить внутри действия

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

надеюсь, что это поможет кому-то