4

Я использую библиотеку поддержки, и у меня есть фрагмент (я буду называть «MyFragment»), реализующий метод, вызванный одним из просмотра фрагмента во время события OnClick. OnClickListener устанавливается в OnActivityCreate метод так:GetView(), возвращающий null в обратном вызове OnClickListener

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

Everything отлично работает на моих тестах, и то же самое можно сказать о большинстве моих пользователей, однако сегодня я получил один отчет 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.

Тем не менее, я весьма озадачен этой ошибкой, поэтому я хотел бы ваши идеи по этому вопросу:

  1. при условии, что мой hypotesys правильно, это нормально для обратного вызова OnClick будет выполняться когда макет отсутствует, или я могу рассматривать это поведение как ошибку (честно: вид был явно там, когда я щелкнул его, почему он должен умереть на мне)?

  2. Эта проблема связана с тем, что я пользуюсь библиотекой поддержки (последняя версия, 13 мая 2013 г.)?

  3. Если это не ошибка, и мне что-то не хватает, не могли бы вы указать мне соответствующую документацию?

Благодарим за внимание!

+0

Любые причины, по которым вы используете 'ViewGroup' вместо просто' View'? Можете ли вы также проверить, определено ли 'R.id.someview' в представлении' getView() '? – Vikram

+0

Не в этот конкретный момент, однако я знаю, что макет является подклассом ViewGroup (а Java в противном случае бросает ClassCastException). Что касается R.id.someview, если соответствующее представление не будет найдено, исключение было бы выбрано в строке 98 (вместо этого на 97) – Rick77

+0

Вы правы, я полностью это пропустил. – Vikram

ответ

1

До Gingerbread была ошибкой в ​​механизме View щелчка в том, что обратный вызов для выполнения щелчка не был удален из очереди сообщений, когда View был отделен от Window. Это было исправлено в ICS (или, возможно, в Honeycomb). Поэтому, если вы поддерживаете Gingerbread или ниже, и ваши слушатели кликов получают доступ к другим ссылкам, которые удаляются при отсоединении View, тогда вы должны обязательно удалить слушателей кликов после отстранения.

Обратите внимание, что это относится ко всем видам прослушивателей кликов, а не только к OnClickListener. Однако это не относится к длинным кликам, так как их обратные вызовы были удалены с самого начала.

+0

Это отлично подходит для проблемы (жаль, что я не узнал об этом, когда я разрабатывал приложение, о котором идет речь ...: |): можете ли вы предоставить какой-то авторитетный источник этой проблемы? Тогда я помету ваш ответ как решение. Спасибо – Rick77

+1

Я не знаю ни одного старого отчета об ошибке, ссылающегося на это, но наиболее авторитетным источником является [_source_] (http://grepcode.com/file_/repository.grepcode.com/java/ext/com. google.android/android/4.0.1_r1/android/view/View.java/?v=diff&id2=2.3.7_r1#9791);) – corsair992

+0

Я вижу: из беглого взгляда, я бы сказал, проблема в строке 5843 (отсутствует «removeTapCallback»), когда окно теряет фокус. Отличная работа, действительно! Спасибо! – Rick77

Смежные вопросы