浅谈Android中的Handler
16lz
2021-01-23
Android中的Handler, Looper, MessageQueue和Thread的相互关系
面试常问的一个问题,也是Android里面非常重要、非常基础的一个问题。这篇blog就来简单总结下这个知识点。
Handler类说明
Handler类用来发送和处理消息(Message)以及和线程的消息队列(MessageQueue)关联的Runnable对象。
Handler是属于主线程的一个工具类。
当你创建一个新的Handler对象,它会和创建它的这个线程/线程的消息队列绑定,从那个时刻开始,它将向这个消息队列传递消息和runnable对象,并且当它们从队列中出来时执行它们。
Handler主要有两种用途:
1.合理调度安排消息和runnable对象,使它们在将来的某个点被执行。
2.将一个动作入队安排在非当前线程执行。
使用Handler我通常使用sendMessage()和HandlerMessage()两方法。sendMessage方法允许你入队一个消息对象(Message),包含一个bundle数据,之后将会被Handler的handleMessage(Message)方法所处理。
Handler,Looper和MessageQueue就是简单的三角关系。Looper和MessageQueue一一对应,创建一个Looper的同时,会创建一个MessageQueue。而Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper和MessageQueue。
Handler传递runnable的例子
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView textView; private Button startBtn; private Button endBtn; //使用handler首先要创建一个handler private Handler mHandler=new Handler(); //要用handler来处理多线程可以使用实现Runnable接口,这里先定义该接口 //线程中运行该接口的run函数 Runnable updateRunnable=new Runnable() { @Override public void run() { //线程每次执行时输出"UpdateThread..."文字,且自动换行 textView.append("\nUpdateThread..."); //延时1s后又将线程加入到线程队列中 mHandler.postDelayed(updateRunnable,1000); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView= (TextView) findViewById(R.id.tv_handler); startBtn= (Button) findViewById(R.id.btn_start); endBtn= (Button) findViewById(R.id.btn_end); startBtn.setOnClickListener(this); endBtn.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_start: //将线程接口立即加入线程队列中 mHandler.post(updateRunnable); break; case R.id.btn_end: //将接口从线程队列中移除 mHandler.removeCallbacks(updateRunnable); break; } }}
Handler通过handleMessage()和sendMessage()方法来实现进度条展示的例子
public class ProgressHandlerAct extends AppCompatActivity{ private ProgressBar progressBar; private Button startBtn; //创建handler,并且执行 private Handler mHandler=new Handler(){ @Override public void handleMessage(Message msg) { //显示进度条 progressBar.setProgress(msg.arg1); //将线程加入到handler的线程队列中 mHandler.post(updateThread); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_progress_handler); progressBar= (ProgressBar) findViewById(R.id.pb); startBtn= (Button) findViewById(R.id.btn_start); startBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //设置progressBar可见 progressBar.setVisibility(View.VISIBLE); //通过上面定义的handler将线程加入handler中 mHandler.post(updateThread); } }); } //handler中添加的runnable线程 Runnable updateThread=new Runnable() { int i=0; @Override public void run() { i+=10; //获取上面handler中的message Message msg=mHandler.obtainMessage(); //将进度条显示的值赋值给消息的arg1参数 msg.arg1=i; //延时1s try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //关键点1,将消息通过handler发送到消息队列中 mHandler.sendMessage(msg); if(i==100){ mHandler.removeCallbacks(updateThread); } } };}
上面2个例子表面上看handler使用了post方法启动了runnbale,其实启动的线程和activity主线程是同一个线程,因为它只是 运行了线程的run方法,而不是start方法。
今天就简单总结到这里,有时间会继续进行完善。
更多相关文章
- android中的多线程基础问题
- 从源码分析RxJava在Android里线程切换的实现
- Android UI 的更新及其线程模型
- Android多线程编程和线程池
- Android中的线程状态之AsyncTask详解
- 个人对Android消息机制的一点归纳
- Android任务、进程、线程的关系