一、起因
今天在写程序的时候,有个需求是从服务器获取数据,然后显示在页面的RecyclerView上。
由于之前也写过几个RecyclerView,于是就把之前的代码拿来抄了。
但是在运行的时候竟然闪退了,提示object not locked by thread before notify()
赶紧对着自己以前的代码排查原因,再结合错误提示,找了大概一个小时,总算是连蒙带猜找到了。
二、原因
我在初始化这个RecyclerView.Adapter的时候,使用了一个全局变量
recyclerViewAdapter = new MyCenterMenuAdapter(mList, mContext);
其中的mList就是我用的全局变量(是不是全局这不重要,见下文)
初始化结束之后,我在使用该recyclerView的时候,是从数据库中读出来的
也就是说,初始化的时候,适配器得到的地址,与实际使用的地址不同,适配器误以为有多个不同的线程在操作它,所以要求我们在使用的时候对它加锁。
知道了原因,就很好解决了。
三、解决办法
解决办法就是让初始化的地址与实际使用的地址相同,仅我自己写出的代码中,就出现了2种解决途径
第一种解决途径
以上文的代码为例,可以使用mlist = myCenterMenuService.getMyCenterMenuLocal();
然后再通知适配器刷新数据即可。
由于JAVA中传递对象的时候全部是地址传递,所以可以直接notify,因为适配器在初始化的时候就已经在监听这个地址了。
第二种解决途径
在适配器中增加一个方法
public void setmDatas(List<MyCenterMenu> datas) {
if (mDatas != null) {
mDatas.clear();
this.notifyDataSetChanged();
}
mDatas.addAll(datas);
this.notifyDataSetChanged();
}
先将初始化的时候存储的数据清除,然后将传来的从数据库中读取的数据追加到这个已经清空的列表中
这样适配器实际使用的列表和初始化中的列表都是一样的了,也解决了问题