【问题标题】:Occasional NullPointerException in findViewById when called in onRestart在 onRestart 中调用 findViewById 时偶尔会出现 NullPointerException
【发布时间】:2016-08-30 18:14:08
【问题描述】:

我在根 Activity 的 onRestart() 方法中调用 findViewById() 时偶尔会收到空指针异常的 Crashlytics 报告。它很少发生,但经常发生,我想找出原因并修复它。显然,我可以检查一个空结果而不继续,但这感觉就像掩盖一个潜在问题而不是修复它。

我搜索了 SO 并没有找到任何符合我情况的内容。我在 onCreate() 中调用了 setContentView(),我已经验证了 xml 中存在的视图项(它是固定的并且应该始终存在),并且这段代码在绝大多数时间都有效(根据我的最佳估计,这个每 1000 个会话中发生少于 1 个会话)。

我没有遇到任何说明我应该对 onRestart 中的活动执行任何特殊操作以访问视图中的项目的文档。

相关代码sn-p:

 public class RootActivity extends FragmentActivity 
 {
     // more member variables, but this is the relevant one
     private StickyListHeadersListView m_layerMenuListView;

     @Override
     protected void onCreate( @Nullable Bundle savedInstanceState )
     {
         super.onCreate( savedInstanceState );

         // do some required initializations (omitted for snippet)

         setContentView( R.layout.main );

         // do more initializations (also omitted for snippet)
         // initializations include accessing m_layerMenuListView
     }

     @Override
     protected void onRestart()
     {
         super.onRestart();

         // accessing this view occasionally returns null
         m_layerMenuListView = (StickyListHeadersListView) findViewById( R.id.layer_menu );

         // more code, but if the above returns null, it will generate the NPE
     }
 }

这是 main.xml 的精简片段,显示 layer_menu 已定义:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:id="@+id/main_layout">

   <!--Layer menu-->
   <se.emilsjolander.stickylistheaders.StickyListHeadersListView
         android:id="@+id/layer_menu"
         android:layout_height="wrap_content"
         android:layout_width="210dp"
         android:layout_alignParentBottom="true"
         android:layout_alignParentRight="true"
         android:layout_marginBottom="@dimen/layer_menu_bottom"
         android:layout_marginRight="2dp"
         android:layout_marginTop="@dimen/layer_menu_top"
         android:visibility="invisible"
         android:background="@color/darkGray_with_transparency"
         android:divider="@color/white"
         android:dividerHeight="1dp"
         android:listSelector="@color/header_background"
         android:choiceMode="multipleChoice"
         />
</RelativeLayout>

为了完整起见,堆栈跟踪:

Fatal Exception: java.lang.RuntimeException: Unable to resume activity {crc.carsapp.la/crc.carsapp.activities.RootActivity}: java.lang.NullPointerException
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2790)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2819)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:137)
       at android.app.ActivityThread.main(ActivityThread.java:5103)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:525)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
       at dalvik.system.NativeStart.main(NativeStart.java)
Caused by java.lang.NullPointerException
       at crc.carsapp.activities.RootActivity.onRestart(RootActivity.java:473)
       at android.app.Instrumentation.callActivityOnRestart(Instrumentation.java:1181)
       at android.app.Activity.performRestart(Activity.java:5192)
       at android.app.Activity.performResume(Activity.java:5203)
       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2780)
       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2819)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:137)
       at android.app.ActivityThread.main(ActivityThread.java:5103)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:525)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
       at dalvik.system.NativeStart.main(NativeStart.java)

【问题讨论】:

  • 你能详细说明是哪一个吗?似乎视图未初始化,您正在尝试访问视图 ID。
  • 我希望如果视图有问题,它会在每次重新启动时抛出 NPE。本质上,onRestart() 几乎在所有时间都有效,但出于某种原因,有时可能为空。问题是什么会导致视图为空,而大多数情况下并非如此。

标签: android android-activity android-lifecycle


【解决方案1】:

尝试一下:

onRestart() 仅在 Activity 处于 onStop() 状态时调用。

我不能更好的 Android 文档,所以在这里引用它:Docs

但想法是在 onDestroy() 之后调用 onCreate()。如果您的活动没有被破坏并且它进入后台并且由于资源内存的过度需求而被释放而没有正确调用 onDestroy()。

更多参考:Ref

当您调用 onRestart() 时,可能不会创建视图并转到 onStart()。尝试在 onStart() 中调用 setContentView() 以查看是否存在差异,您仍然会得到 NPE。

【讨论】:

  • 感谢您的尝试。但是,如果我正确阅读了文档,onStart() 将在调用 onRestart() 之后被调用,所以如果内容视图有问题,即使我在 onStart() 中设置它,在 onRestart() 中仍然会为 null .如有必要,对 onStop() 的调用可能会清除内容视图,这有时会导致 NPE。文档对此不太清楚。
  • 我认为只有在 onDestroy() 的情况下才应该清除视图,并且似乎操作系统也可以调用它。调用它会使活动 onCreate() 被调用。但是 onDestroy() 并不总是被调用并且资源被释放。在这种特殊情况下,应用程序不知道是否需要重新创建活动是导致它的原因。 onStart() 总是在 onStop() 之后调用,但是它被调用了多次,所以需要有 null 检查是否要执行 setContentView。
  • 对不起,我不清楚。我并不是在提倡明确地清除内容视图,而是公开地想知道操作系统是否在某些条件下这样做,这会导致它在 onRestart() 中为空。但是,我没有发现任何文件或轶事证据。
  • 这是真的,这可能会有所帮助,因为它不能模拟操作系统来做,但人们有建议尝试一下。 stackoverflow.com/a/37978044/6114925
【解决方案2】:

不确定这是否能解决问题,我要等到发布带有修复程序的版本后才能知道,因为我无法重现 NPE,但我会尝试以下方法,看看这是否会阻止它:

@Override
protected void onRestart()
{
    super.onRestart();

    // check if there is a valid content view
    if ( findViewById( android.R.id.content ) == null )
    {
        // no content view, so set it back to the expected view
        setContentView( R.layout.main );
    }

    // continue restart code as before
}

不确定上述是否有任何负面影响。只有时间会证明一切。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    • 1970-01-01
    • 2020-09-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 2014-03-09
    相关资源
    最近更新 更多