在onRestart中调用时,findViewById中偶尔会出现NullPointerException

时间:2016-08-30 18:14:09

标签: android android-activity android-lifecycle

我在根活动中的onRestart()方法中调用findViewById()时偶尔会收到Crashlytics报告的Null Pointer Exception。它很少发生,但经常足以让我弄清楚原因并解决它。很明显,我可以检查一个空结果而不是继续,但这就像掩盖一个潜在的问题而不是修复它。

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

我没有遇到任何文档,说明我应该对onRestart中的活动做一些特别的事情来访问视图中的项目。

相关代码段:

 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)

2 个答案:

答案 0 :(得分:0)

尝试一下:

仅当Activity为onStop()状态时才会调用

onRestart()。

我无法提供更好的Android文档,因此请在此处引用它:Docs

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

更多参考资料:Ref

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

答案 1 :(得分:0)

不确定这是否能解决这个问题,直到我发布修复版本才会知道,因为我无法重现NPE,但我会尝试以下内容,看看是否会阻止它:< / p>

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

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