Android中Handler异步线程
16lz
2021-12-04
在讲Handler之前,我想在这里给各位说说为什么要用Handler。Android中只有2种线程,主线程也叫UI线程和工作线程。除了主线程之外的都叫工作线程,我们知道Android种只有主线程能够修改UI,工作线程是不能修改UI的,这是Android的机制,具体是因为什么各位同学可以自己去查询为什么这样设定,这里我简单的说是为了线程安全。那么当工作线程想要修改UI怎么办呢?这个时候我们就需要工作线程在完成他的工作后把需要修改UI这个请求告诉UI线程,所以这个告诉的动作就可以通过我们的Handler实现:看下面的之前,我画一个简易的流程,并不是完整的流程: 通过Looper.prepar()开启MessageQueue Looper.loop 处理发送过来的信息Handler----------------------------------》MessageQueue---------------------》handleMessage 通过Handler对象的sendMessage发送信息 开始循环MessageQueue先说几个概念:Handler的工作原理: 先说说流程:首先某个WorkThread想要修改UI界面,那么WorkThread必须开启一个Looper和MessageQueue(除了主线程外,其他new 的线程都没有Looper和MeeageQueue),然后通过主线程的Handler对象去sendMessage,再让Looper去工作去循环Queue里边的消息,当MessageQueue中没有消息对象的时候,消息队列就变成阻塞。总之一句话理解,那个线程的Handler对象调用的sendMessage,那么这个Message对象就会被那个线程的handleMessage接受到。(希望各位能理解这句话,实在不能理解,就记住用就行啦!) Handler对象,用于发送消息,那个线程的Handler对象发送的消息就会被自己的线handleMessage(Message msg)收到 Looper对象,是子线成用于把Message送入到Message队列中去的(相当一个工作者,负责让MessageQueue的消息循环发送出去),子线程要的handler要创建之前必须要先调用Looper.prepare();并且在完成handleMessage(Message msg)方法后使用Looper.loop();去循环工作线程中的消息队列(通俗的讲就是让looper开始工作)。Android中除了主线程外要使用Handler必须开启消息循环。一个线程绑定一个消息队列和Looper对象(消息循环) Message对象:就是用户消息发送时保存数据用的,讲几个常用:message.arg2;message.arg1:这2个是用于保存int类型的值,可以直接通过sendMessage(Message message)发送的。还有一个是message.what主要是用户用来自定义的消息代码,这样便于接受者来了解这个消息,避免和其他自定义的handlers产生冲突。Message对象推荐使用Message.obtain()去从消息池里边去获取,不推荐使用new Message()的方式。 MessageQueue:消息队列,一个队列结构,在没有消息需要处理的MessageQueue处于阻塞状态,当message里边有消息的时候,Looper.loop()会让MessageQueue开始工作。
package com.example.administrator.test_handler;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.os.SystemClock;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.ProgressBar;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button button; private ProgressBar progressBar; private TextView textView; //主线程的Handler对象和子线程的Handler兑现 Handler mHandler; Handler sHandler; //一些记录常量 private static final int DOWNLOANSTATIC=0; private static final int DOWNLOADING=1; private static final int DOWNLOADFINISH=2; private static int OpenDown=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main1); initView(); initmHandler(); button.setOnClickListener(this); initsThread(); } private void initsThread() { new Thread(){ public void run(){ //创建looper对象以及创建工作线程的MessageQueue Looper.prepare(); sHandler=new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what==DOWNLOANSTATIC){ for(int i=1;i<=100;i++){ SystemClock.sleep(200); Message message=Message.obtain(); message.what=DOWNLOADING; message.arg1=i; message.arg2=1;//注意这里是使用主线程的Handler对象发送信息,所以主线程的handleMessage去处理发出去的信息 mHandler.sendMessage(message); } Message message=Message.obtain(); message.what=DOWNLOADFINISH; mHandler.sendMessage(message); OpenDown=0; } } }; Looper.loop();//循环工作线程中的消息队列 } }.start(); } private void initmHandler() { mHandler=new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what) { case DOWNLOADING: progressBar.setProgress(msg.arg1);//主线程在这里修改 textView.setText(msg.arg1 + "%"); break; case DOWNLOADFINISH: Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show(); break; case DOWNLOANSTATIC: break; } } }; } private void initView() { button= (Button) findViewById(R.id.button); progressBar= (ProgressBar) findViewById(R.id.progressBar); textView= (TextView) findViewById(R.id.textView); } @Override public void onClick(View view) { //将消息发送到工作线程的消息队列 if(OpenDown==0) { sHandler.sendEmptyMessage(DOWNLOANSTATIC); OpenDown=1; }else{ Toast.makeText(MainActivity.this,"点那么快干嘛!",Toast.LENGTH_SHORT).show(); } } @Override protected void onDestro() { }}还不明白的同学,可以在下面评论,建议把源码下载到自己设备上跑一跑。
预告:下次更新使用进度条去控制imageSwitcher显示图片,类似拖拉网络视频时,视频图片在跳的功能。
更多相关文章
- Android[中级教程] 深入剖析Android消息机制
- 菜鸟初学者学习Android心得
- 单线程模型中Message、Handler、Message Queue、Looper之间的关
- Android应用程序资源管理器(Asset Manager)的创建过程分析
- [置顶] android Asynctask的优缺点?能否同时并发100+asynctask呢?
- android面试1
- Android(安卓)进程和线程模型
- Android中各种组件的生命周期
- 进程和线程模型(android)