写了一段代码,造成了空指针
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);
可以看到,跟预期一致。