android - Fragment 的 getView() 在 OnClickListener 回调中返回 null

标签 android android-fragments android-lifecycle android-support-library

我正在使用支持库,并且我有一个 fragment (我将称之为“MyFragment”)实现了在 OnClick 事件期间由 fragment 的 View 之一调用的方法。 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() 触发 Fragment View 中的更改,就像更新项目的可见性一样简单:

private void showStuff() {  //MyFragment:95
    ViewGroup base = (ViewGroup) getView();
    LinearLayout ll = (LinearLayout) base.findViewById(R.id.someview); // MyFragment:97
    ll.setVisibility(View.VISIBLE);
}

在我的测试中一切正常,我的大多数用户也是如此,但是今天我从 Google Play 开发者控制台收到了一份 ANR 报告,指出该应用程序因用户出现 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) {
}

我最好的猜测是,在 MyFragment 上调用 onDestroyView 之后,回调已安排在 之后,因此导致 getView() 返回 null。

不过,我对这个错误感到很困惑,所以我想听听您对此事的见解:

  1. 假设我的 hypotesys 是正确的,当不存在布局时执行 OnClick 回调是否正常,或者我是否可以将此行为视为错误(老实说:当我点击它时 View 显然存在,它为什么要死在我身上)?

  2. 这个问题是否与我使用的支持库(最新版本,2013 年 5 月 13 日)有关?

  3. 如果这不是错误并且我遗漏了一些东西,你能指点我相关的文档吗?

感谢您的关注!

最佳答案

在 Gingerbread 之前,View 点击机制中存在一个错误,当 View 从中分离时,执行点击的回调不会从消息队列中删除窗口。这已在 ICS(或可能在 Honeycomb)中得到修复。因此,如果您支持 Gingerbread 或更低版本,并且您的点击监听器访问在分离 View 时删除的其他引用,那么您应该确保在分离时也删除您的点击监听器。

请注意,这适用于所有类型的点击监听器,而不仅仅是 OnClickListener。但是,它不适用于长按监听器,因为它们的回调从一开始就被正确删除了。

关于android - Fragment 的 getView() 在 OnClickListener 回调中返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17785388/

相关文章:

android - 启动器如何访问图标包?

android - Windows 7 下的 adb shell 自动完成

android - 如何调用来自不同 Activity 的 View 寻呼机中的 fragment ?

android - 动态注册的 BroadcastReceivers 是否在组件/应用程序死亡后仍然存在?

android - 如果调用不可靠,为什么要覆盖 Activity.onDestroy()?

android - 如何在 onCreate 后立即启动动画?

java - 如何访问 Firebase 数据库的这些部分?

java - 在android中的EdiTtext中删除/修改选定的文本

android - 在 PreferenceFragmentCompat 内部实现 PreferenceFragmentCompat

android - 如果方向改变, Activity 在 onActivityReenter 之后销毁