发表于: 2018-10-05 23:12:13
0 811
一、今天完成的事情
1. 解决了昨天下拉刷新数据不能正常加载到RecyclerView的问题
原因:适配器中的数据虽然更新了,但RecyclerView并不知道,需要调用Adapter的notifyDataSetChanged() 方法来更新RecyclerView,当适配器的内容改变时会强制调用getView()来刷新每个Item的内容。
然后我又在添加了adapter.notifyDataSetChanged()
@Override
public void onRefresh() {
@Override
public void run () {
Toast.makeText(getActivity(), "正在刷新", Toast.LENGTH_SHORT).show();
Log.d("通知", "开始查询");
queryData(0, STATE_REFRESH);
adapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
}
结果还是不行,后来又查了半天才发现原因,使用notifyDataSetChanged()有一些要注意的地方:
(1)adapter适配的数据必须是同一个对象
比如myAdapter = new MyAdapter(data)中的data必须是同一个对象。
(2)数据刷新时要通知主线程刷新UI(我的问题就出在这里)
Android实现View更新有两组方法,分别是invaliDate和postInvaliDate,前者在UI线程中使用,后者在
非 UI线程即子线程中使用,在子线程调用invaliDate 方法会导致线程不安全,invaliDate 方法会通知 view
立 即重绘,刷新界面,假如子线程在用 invaliDate刷新界面的同时UI线程也在用 invaliDate 刷新界面,这
样会不导致界面的刷新不能同步。
解决方法是子线程发送消息通知UI线程更新UI
UI线程接受消息并执行adapter.notifyDataSetChanged(),UI得到更新:
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == CHANGE_UI) {
Log.d("通知:", "接受成功");
workerAdapter.notifyDataSetChanged();
Log.d("通知:", "UI更新");
}
}
};
子线程发送更新UI的消息:
Log.d("", "数据查询已完成,通知主线程更新UI");
mHandler.sendEmptyMessage(CHANGE_UI);
安卓的消息机制
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例 如更新UI等。 MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际 意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
参考Android子线程更新UI的方法总结,这篇博文讲得很详细。
二、明天计划的事情
实现上拉加载和条件筛选菜单。
三、遇到的问题
如何设定子线程中 方法的执行顺序?
四、收获
学会了如何在子线程中更新UI,其实并不是把更新UI的逻辑写在子线程中,子线程只是发送消息通知UI线程更新UI,具体的更新UI的逻辑要写在UI线程里。
评论