1、前言
有时候需要使用网络请求数据,一般的做法都是将网络请求放在一个子线程中,防止出现主线程堵塞的情况。但是这时候出现了一个问题,如何将所请求的数据,设置到所需要的UI上呢。
android只允许在主线程中更新UI
2、方法一:Handler
Handler就是用来结合线程队列,发送,处理线程数据的工具。
具体的作用就是,主线程和通信线程之间的桥梁。主线程–>通信线程(Runnable)–>Handler -->主线程。算是一种异步的机制。
2.1 Looper Message MessageQueue 作用和关系
Massage:是传递信息的载体。也是Handler处理和发送的主体。
MessageQueue: 消息队列:
- 调度规则:先进先出(FIFO)
- 数量:每个线程最多只有一个MessageQueue
- 管理:由Looper管理,在主线程创建的时候会默认创建一个Looper。
Looper
- 作用:用来管理MassageQueue。不断的移除MessageQueue中的Message,之后交给Handler处理。
- 创建者:主线程
- 在Looper被创建的时候,会自动创建一个MessageQueue。
2.2 步骤
- 创建 Handler
- 开一个子线程
- 在子线程中创建 Message。
- Handler 发送消息给MessageQueue
- Handler处理消息。
- 更新UI
2.3 例子
message :
what= 表示消息码。
obj= 承载大量的数据
arg1和arg2:少量的int类型数据。
public class FragmentAnalysisEmailAccept extends Fragment {
private View view;
private SmartTable<Email> table;
private TextView tv;
private SPUtil sp;
private HashMap<String,String> stringHashMap;
/**
* 利用Handler 将请求到的信息取出。
* 利用JsonUtil进行数据的解析。
* 将解析后的数据 设置到表格中。
*/
@SuppressLint("HandlerLeak")
private Handler handler =new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
if (msg.what==1){
//。。。具体的处理操作。
}
}
};
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if(view==null){
view = inflater.inflate(R.layout.fragment_table,container,false);
}
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.obj = res;
message.what = 1;
handler.sendMessage(message);
}
}).start(); //请求数据
return view;
}
}
3、方法二:
Runnable对像就能在ui程序中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程。
利用runOnUiThread()方法。
在fragment中使用需要加上 getActivity().
new Thread(new Runnable() {
@Override
public void run() {
// ...
网络请求
//...
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
//...
更新UI内的数据。
//...
});
}
}).start();
总结
- 只可以在主线程中更新数据,操作UI控件
- 比较复杂的操作 Handler+Message+Thread
- 简单的操作,runOnUIThread()