美文网首页
一次艰难的 NullPointerException 排查

一次艰难的 NullPointerException 排查

作者: LilacZiyun | 来源:发表于2017-08-30 22:31 被阅读199次

    异常信息

    Fatal Exception: java.lang.NullPointerException: Attempt to invoke interface method 'void get(Context context) on a null object reference
           at com.snaptube.mixed_list.view.card.MultiSelectCardViewHolder.(Unknown Source)
           at com.snaptube.mixed_list.fragment.MultiSelectFragmentDelegate.onCreateViewHolder(Unknown Source:429)
           at com.snaptube.search.view.YouTubeMultiSelectFragment.onCreateViewHolder(Unknown Source:220)
           at com.snaptube.mixed_list.view.list.MixedAdapter.onCreateViewHolder(Unknown Source:61)
           at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(Unknown Source:6321)
           at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(Unknown Source:5509)
           at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(Unknown Source:5394)
           at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(Unknown Source:5390)
           at android.support.v7.widget.LinearLayoutManager$LayoutState.next(Unknown Source:2149)
           at android.support.v7.widget.LinearLayoutManager.layoutChunk(Unknown Source:1533)
           at android.support.v7.widget.LinearLayoutManager.fill(Unknown Source:1496)
           at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(Unknown Source:593)
           at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(Unknown Source:3537)
           at android.support.v7.widget.RecyclerView.dispatchLayout(Unknown Source:3266)
           at android.support.v7.widget.RecyclerView.consumePendingUpdateOperations(Unknown Source:1603)
           at android.support.v7.widget.RecyclerView$ViewFlinger.run(Unknown Source:4656)
           at android.os.Handler.handleCallback(Handler.java:739)
           at android.os.Handler.dispatchMessage(Handler.java:95)
           at android.os.Looper.loop(Looper.java:145)
           at android.app.ActivityThread.main(ActivityThread.java:6934)
           at java.lang.reflect.Method.invoke(Method.java)
           at java.lang.reflect.Method.invoke(Method.java:372)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
    

    具体而言,就是说在调用如下方法时,返回 null

    public static <T> T get(Context context) {
        return (T) context.getSystemService(SERVICE_NAME);
      }
    

    这个方法定义在 DaggerService 中:

    public class DaggerService {
      public static final String SERVICE_NAME = DaggerService.class.getName();
    
      public DaggerService() {
      }
    
      public static <T> T get(Context context) {
        return (T) context.getSystemService(SERVICE_NAME);
      }
    }
    

    既然问题已经定位,就需要排查原因了,可能原因如下:

    1. context 类型不符,即 context 不为 Activity/Application 类型,这时会导致 context.getSystemService() 方法中没有我们自定义的 SERVICE_NAME 方法,从而导致 context.getSystemService() ;
    2. context 为 Activity/Application 类型,这时就是因为由于我们自己的 getSystemService() 内部逻辑输出 null;

    根据分析,要定位具体原因的话,需要按如下步骤进行处理:

    1. 判断 context 类型,若 context 不为 Activity/Application 类型,那么说明问题产生的原因为“传入了一个错误的 context 类型”;
    2. 若 context 为 Activity 类型,则查看在哪些情况下,BaseActivity 的 getSystemService 返回 null;
    3. 若 context 为 Application 类型,则查看在哪些情况下,BaseApplication 的 getSystemService 返回 null。

    打日志显示获得的 Context 为 Activity 类型,所以现在只需要查看在什么情况下 BaseActivity 的 getSystemService 会返回 null 即可。查阅源码,我们发现 BaseActivity 的 getSystemService 代码如下:

    public Object getSystemService(@NonNull String name) {
        if (DaggerService.SERVICE_NAME.equals(name)) {
          return activityComponent;
        }
        return null;
      }
    

    同时在 BaseActivity 的 onDestory 方法中会将 activityComponent 置为 null,所以当 Activity 的 destory 方法调用后,activityComponent 就会返回 null,而我们的应用场景为,在 onLoadMore 方法中加载数据,然后数据加载完成后获取该 activityComponent,并更新主界面,因为数据加载为耗时操作,所以很有可能数据还未加载完成,所在的 Activity 已经由于某种原因被销毁了,此时就会出现 NPE,解决办法为在 RxJava 的事件流中添加 Activity 生命周期绑定,确保在 onDestory 方法被调用后不再进行后续操作。

    相关文章

      网友评论

          本文标题:一次艰难的 NullPointerException 排查

          本文链接:https://www.haomeiwen.com/subject/wreadxtx.html