11

Я использую фрагменты в своем приложении. И очень распространенная проблема при использовании их - это NPE при использовании getActivity(). Я знаю, что мы можем решить это, проверив, getActivity() != null каждый раз, или проверяя, есть ли фрагмент isAdded().Android Fragment getActivity() = null

В одном из моих классов я получаю контекст активности более чем в 60 местах. Если getActivity() не является нулевым или если фрагмент по-прежнему добавлен к активности во всех местах, он делает код уродливым, большим и не ремонтируемым. Есть ли другой способ справиться с этим? Можно ли даже уничтожить фрагмент (и остановить любую работу, которую он делал при удалении), когда он удален из этой операции?

Also Is this way a suggested one?

ответ

7

По моему опыту, большинство случаев getActivity(), возвращающих null, находятся в асинхронных обратных вызовах.

Например, ваш фрагмент запускает AsyncTask, а затем удаляется перед выполнением фонового задания, а затем, когда фоновое задание завершается и вызывает getActivity() в onPostExecute(), он получает нуль, поскольку фрагмент уже отделен от деятельности.

Мое решение:

1.Check getActivity() == нуль в начале каждого асинхронного обратного вызова, если это так, то просто прервать метод.

2.Отмена асинхронных заданий в onDetach().

И я думаю, что это лучшее решение, чем сохранение экземпляра активности в onAttach(), потому что, поскольку ваш фрагмент удален, зачем беспокоиться о выполнении всех заданий, оставшихся в обратных вызовах (в большинстве случаев, кодах UI)?

+0

Мне кажется, это лучшее решение.! – Uma

0

Я думаю, вы должны использовать метод onAttach(Activity)Fragment «s.

Я думаю, что это должно помочь вам избежать всех этих NPE.

+0

Если я использую это, и я удаляю фрагмент во время загрузки пользовательского интерфейса, и все же это не вызовет NPE? – Uma

+0

Использование @Rani может использовать ссылку для активности, а затем проверить, не является ли оно нулевым и не помечать его как null в onDetach – sector11

-1

Я не нашел для этого решения, возможно, потому что, если вы думаете о lifecycle of a fragment, вы должны уметь понять, когда вы проверите нулевое значение.

+1

Yup Я понимаю, что отдельный фрагмент все еще жив :(Я надеюсь, что есть какой-то способ! – Uma

+1

Я вижу, что В основном, я стараюсь проверить свою активность/контекст, когда я сделал что-то асинхронное, и я хочу быть уверенным, что этот фрагмент все еще привязан к активности (например, проверка того, isedded http://developer.android .com/reference/android/app/Fragment.html # isAdded()). Но если вы прокрутите среднюю часть связанной страницы, вы найдете, как скоординировать два «разных» жизненных цикла. –

+0

Жаль, что я не 't получить то, что вы говорите в последней строке. – Uma

4

getActivity будет повторно инициализирован в методе - onActivityCreated().

Так безопаснее называть getActivity() сразу после onActivityCreated() (в соответствии с жизненным циклом фрагментов http://developer.android.com/guide/components/fragments.html) - например, в OnStart() - в таком случае это будет НИКОГДА не NULL - нет необходимости делать бесполезные чеки, как isAdded и getActivity! = null.

P.S. Если мы используем это решение:

@Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     mActivity = activity; 
    } 

mActivity никогда не будет нулевым - но позже в методе onActivityCreated() getActivity() стал другим с mActivity. Моего мнение - что мы можем сохранить всю активность в переменном, но это безопаснее следовать андроид документооборота фрагменты жизненного цикла и получить активность сразу после onActivityCreated()

+0

Если ваш фрагмент статичен, тогда может возникнуть утечка памяти. Я лично столкнулся с этой проблемой. Никогда не собирайте ссылку на активность в фрагменте. Если это так сильно обозначить ее как null в o nDetach() – sector11

+0

Yeap, это разумно в отношении активности, даже если оно не является статичным. Также я никогда не использую статические фрагменты - это просто опасно (как вы сказали - утечка памяти), и я никогда не видел ситуации, когда это может быть полезно. –

0

Моего решения переопределить onSaveInstanceState метода в BaseActivity:

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    //solution of fragment.getActivity() is null 
    outState.remove("android:support:fragments"); 
} 
Смежные вопросы