Я использую библиотеку поддержки, и у меня есть фрагмент (я назову «MyFragment»), реализующий метод, вызываемый одним из представлений фрагмента во время события OnClick. OnClickListener устанавливается в методе OnActivityCreate следующим образом:
@Override
public void onActivityCreated(Bundle inState) {
super.onActivityCreated(inState);
ViewGroup base = (ViewGroup) getView();
TextView tv = (TextView) base.findViewById(R.id.monografiat);
tv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showStuff(); // MyFragment:150
}
});
}
где showStuff() запускает изменение представления фрагмента, что-то столь же простое, как обновление видимости элемента:
private void showStuff() { //MyFragment:95
ViewGroup base = (ViewGroup) getView();
LinearLayout ll = (LinearLayout) base.findViewById(R.id.someview); // MyFragment:97
ll.setVisibility(View.VISIBLE);
}
В моих тестах все работает нормально, и то же самое можно сказать о большинстве моих пользователей, однако сегодня я получил единственный отчет ANR из консоли разработчика Google Play, в котором говорится, что приложение аварийно завершилось для пользователя с NullPointerException в строке:
LinearLayout ll = (LinearLayout) base.findViewById(R.id.someview);
Который означает, что:
ViewGroup base = (ViewGroup) getView();
вернул ноль. Это отчет:
java.lang.NullPointerException
at mypackage.MyFragment.showStuff(MyFragment.java:97)
at mypackage.MyFragment.access$0(MyFragment.java:95)
at mypackage.MyFragment$2.onClick(MyFragment.java:150)
at android.view.View.performClick(View.java:2538)
at android.view.View$PerformClick.run(View.java:9152)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Я решил проблему (или так я думаю, поскольку у меня нет метода воспроизведения...), просто окружив оскорбительные строки:
if(base != null) {
}
мое лучшее предположение состоит в том, что обратный вызов был запланирован после вызова onDestroyView для MyFragment, в результате чего getView() возвращает значение null.
Тем не менее, я весьма озадачен этой ошибкой, поэтому мне хотелось бы узнать ваше мнение по этому вопросу:
предполагая, что моя гипотеза верна, является ли нормальным выполнение обратного вызова OnClick при отсутствии макета, или я могу рассматривать это поведение как ошибку (честно: представление было явно там, когда я щелкнул его, почему он должен умереть на меня)?
Связана ли эта проблема с тем, что я использую библиотеку поддержки (последняя версия, 13 мая 2013 г.)?
Если это не ошибка и я что-то упустил, не могли бы вы указать мне соответствующую документацию?
Спасибо за Ваше внимание!
ViewGroup
вместоView
? Можете ли вы также проверить, определено лиR.id.someview
в представлении, которое возвращаетgetView()
? - person Vikram   schedule 22.07.2013onActivityCreated()
предназначен дляMyFragment
, верно? Кроме того, переменнаяbase
, используемая вonActivityCreated()
, это ...? - person user   schedule 22.07.2013l1
один раз в своем onCreateView или что-то в этом роде? Еще одна вещь: еслиshowStuff
являетсяprivate
членом вашего фрагмента, вам даже не нужно вызыватьgetView
, чтобы получить переменнуюbase
. - person Soroush   schedule 06.12.2014onCreateView
(по производительности и памяти), и я предпочитаю (по причине DRY/опрятности) избегать кэширования переменных в экземпляре, если их легко вычислить и их сохранение не критично (кстати, код, который я написал, отлично работает на младшем GT5500). Что касается второго вопроса, извините, но я не думаю, что понял его: насколько я знаю,getView
- это правильный метод для получения базового вида фрагмента (если он есть). - person Rick77   schedule 06.12.2014