Java项目转Kotlin后RecyclerView智能转换失败与mUploads未识别问题求助
问题1:可变属性智能转换失败报错
原因
Kotlin的空安全机制限制:postRecyclerView、shimmerFrameLayout这类属性是用var声明的可变可空属性,编译器无法保证你调用方法的瞬间,该属性没有被其他线程修改为null,因此禁止直接调用成员方法,抛出对应错误。
解决方案
有几种常用处理方式,可按需选择:
- 空安全调用:如果属性为空时不需要执行对应逻辑,用
?.调用,空值时会自动跳过执行不会崩溃postRecyclerView?.layoutManager = staggeredGridLayoutManager postRecyclerView?.addOnScrollListener(/* 滚动监听实例 */) shimmerFrameLayout?.startShimmer() - 非空断言:如果你能100%确认调用时属性一定不为空,用
!!强制认定非空,注意空值时会抛出空指针异常postRecyclerView!!.layoutManager = staggeredGridLayoutManager - 局部变量缓存:先把可变属性赋值给不可变局部变量,编译器确认值不会变更后就允许直接调用,适合需要连续调用多个方法的场景
val recyclerView = postRecyclerView if (recyclerView != null) { recyclerView.layoutManager = staggeredGridLayoutManager recyclerView.addOnScrollListener(/* 滚动监听实例 */) } - 根治方案:如果是视图属性,建议开启View Binding,自动生成的视图属性均为非空不可变类型,不会触发该报错;也可将确定会提前初始化的属性声明为
lateinit var,规避空安全检查。
问题2:Adapter中mUploads未找到报错
原因
你转换后的Kotlin代码中,companion object(对应Java的静态域)为空,没有定义mUploads属性,因此调用时会报未找到引用的错误。另外你当前的Kotlin代码构造函数也缺失了原Java代码的列表入参,和原有逻辑不匹配。
解决方案
这里不推荐保留静态声明的实现,静态变量生命周期和类绑定,容易引发内存泄漏,建议改为实例成员,修改后完整Adapter核心代码如下:
class PostAdapter( val mcontext: Context, private var mUploads: List<Upload> = emptyList() ) : RecyclerView.Adapter<PostAdapter.PostViewHolder>() { private var mListener: OnItemClickListener? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.post_item_container_profile, parent, false) return PostViewHolder(view) } override fun onBindViewHolder(holder: PostViewHolder, position: Int) { val uploadCurrent = mUploads[position] // 原有加载图片等逻辑保持不变 val shimmer = ColorHighlightBuilder() .setBaseColor(Color.parseColor("#F3F3F3")) .setBaseAlpha(1f) .setHighlightColor(Color.parseColor("#E7E7E7")) .setHighlightAlpha(1f) .setDropoff(50f) .build() val shimmerDrawable = ShimmerDrawable() shimmerDrawable.setShimmer(shimmer) Glide.with(mcontext) .load(uploadCurrent.getmImageUrl()) .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC) .placeholder(shimmerDrawable) .centerCrop() .fitCenter() .into(holder.imageView) } override fun getItemCount(): Int = mUploads.size fun setOnItemClickListener(listener: OnItemClickListener?) { mListener = listener } fun setUploads(uploads: List<Upload>) { mUploads = uploads notifyDataSetChanged() // 数据更新后刷新列表,原有Java代码缺失该逻辑 } interface OnItemClickListener { fun onClick(view: View?) fun onItemClick(position: Int) fun onDeleteClick(position: Int) } // 去掉inner关键字,对应原Java的静态内部类逻辑 class PostViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener, View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener { val imageView: ShapeableImageView = itemView.findViewById(R.id.imagePost) private var mListener: OnItemClickListener? = null override fun onClick(v: View) { val position = adapterPosition if (position != RecyclerView.NO_POSITION) { mListener?.onItemClick(position) } } override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) { val delete = menu.add(Menu.NONE, 2, 2, "Delete") delete.setOnMenuItemClickListener(this) } override fun onMenuItemClick(item: MenuItem): Boolean { val position = adapterPosition if (position != RecyclerView.NO_POSITION && item.itemId == 2) { mListener?.onDeleteClick(position) return true } return false } init { itemView.setOnClickListener(this) itemView.setOnCreateContextMenuListener(this) } } }
如果确实需要保留原有静态逻辑,只需要在空的companion object中添加mUploads声明即可:
companion object { var mUploads: List<Upload> = emptyList() }
内容的提问来源于stack exchange,提问作者Vasant Raval
相关产品推荐
相关产品推荐

