kotlin if判定分支中有范型方法和null返回造成的空指针

写了一段代码,造成了空指针

WallpaperUtil.displayWallpaper(pageLifecycle, item, helper.getView(R.id.wallpaper_image), if (item.isHot()) null else helper.getView(R.id.wallpaper_live_ic))

异常堆栈如下(第26行即为上部分代码):

2019-03-17 20:15:22.271 29062-29062/com.ss.android.tuchong E/CrashReport: java.lang.NullPointerException: throw with null exception
        at com.ss.android.tuchong.feed.model.RecommendWallpaperAdapter.convert(RecommendWallpaperAdapter.kt:26)
        at com.ss.android.tuchong.feed.model.RecommendWallpaperAdapter.convert(RecommendWallpaperAdapter.kt:15)
        at com.chad.library.adapter.base.BaseQuickAdapter.onBindViewHolder(BaseQuickAdapter.java:939)
        at com.chad.library.adapter.base.BaseQuickAdapter.onBindViewHolder(BaseQuickAdapter.java:68)
        at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6673)
        at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6714)
        at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5647)
        at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5913)
        at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:285)
        at android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:342)
        at android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:358)
        at android.support.v7.widget.GapWorker.prefetch(GapWorker.java:365)
        at android.support.v7.widget.GapWorker.run(GapWorker.java:396)
        at android.os.Handler.handleCallback(Handler.java:792)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:176)
        at android.app.ActivityThread.main(ActivityThread.java:6701)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:246)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)

其中,displayWallpaper()方法声明如下:

@JvmStatic
fun displayWallpaper(pageLifecycle: PageLifecycle, cardModel: WallpaperCardModel, imageView: ImageView, liveImageView: View? = null) {
     // ... 
}

helper.getView()方法定义如下:

public <T extends View> T getView(@IdRes int viewId) {
        View view = views.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            views.put(viewId, view);
        }
        return (T) view;
    }

找了一会,没找到,直接通过Android Studio的kotlin插件看字节码反编译后的java代码:

WallpaperUtil.displayWallpaper(var10000, item, (ImageView)var10002, (View)(item.isHot() ? null : (Void)helper.getView(-1001432)));

原来item.isHot()为true时,会出现null强转为View的情况,而非我预期的转为View?。
那是不是显示写上转为View?可以呢?

WallpaperUtil.displayWallpaper(pageLifecycle, item, helper.getView(R.id.wallpaper_image), (if (item.isHot()) null else helper.getView(R.id.wallpaper_live_ic)) as View?)

发现并无用,因为本质上是一致的,因为View是一个类型,View?并非一个类型,View?只是表示变量是View类型,但可空。
这时,注意到**(Void)helper.getView(-1001432)**,View被强制转为Void类型,之后为了调用displayWallpaper()方法,必须要将Void转化为View,从而有可能产生空指针问题。
因此改成

        val liveView = if (item.isHot()) null else helper.getView<View?>(R.id.wallpaper_live_ic)
        WallpaperUtil.displayWallpaper(pageLifecycle, item, helper.getView(R.id.wallpaper_image), liveView as View?)

其字节码为

    LINENUMBER 25 L15
    ALOAD 2
    INVOKEVIRTUAL com/ss/android/tuchong/wallpaper/model/WallpaperCardModel.isHot ()Z
    IFEQ L16
    ACONST_NULL
    GOTO L17
   L16
    ALOAD 1
    LDC -1001432
    INVOKEVIRTUAL com/chad/library/adapter/base/BaseViewHolder.getView (I)Landroid/view/View;
   L17
    ASTORE 4
   L18
    LINENUMBER 26 L18
    ALOAD 0
    GETFIELD com/ss/android/tuchong/feed/model/RecommendWallpaperAdapter.pageLifecycle : Lplatform/http/PageLifecycle;
    ALOAD 2
    ALOAD 1
    LDC -1001457
    INVOKEVIRTUAL com/chad/library/adapter/base/BaseViewHolder.getView (I)Landroid/view/View;
    DUP
    LDC "helper.getView(R.id.wallpaper_image)"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    CHECKCAST android/widget/ImageView
    ALOAD 4
    INVOKESTATIC com/ss/android/tuchong/common/util/WallpaperUtil.displayWallpaper (Lplatform/http/PageLifecycle;Lcom/ss/android/tuchong/wallpaper/model/WallpaperCardModel;Landroid/widget/ImageView;Landroid/view/View;)V
   L19

字节码反编译后为

            View liveView = item.isHot() ? null : helper.getView(-1001432);
            PageLifecycle var10000 = this.pageLifecycle;
            View var10002 = helper.getView(-1001457);
            Intrinsics.checkExpressionValueIsNotNull(var10002, "helper.getView(R.id.wallpaper_image)");
            WallpaperUtil.displayWallpaper(var10000, item, (ImageView)var10002, liveView);

可以看到,跟预期一致。

你可能感兴趣的:(android,kotlin)