Android中Handler异步线程

来源:互联网 发布:怎么注册淘宝外卖 编辑:程序博客网 时间:2024/05/18 03:54
  在讲Handler之前,我想在这里给各位说说为什么要用Handler。Android中只有2种线程,主线程也叫UI线程和工作线程。除了主线程之外的都叫工作线程,我们知道Android种只有主线程能够修改UI,工作线程是不能修改UI的,这是Android的机制,具体是因为什么各位同学可以自己去查询为什么这样设定,这里我简单的说是为了线程安全。那么当工作线程想要修改UI怎么办呢?这个时候我们就需要工作线程在完成他的工作后把需要修改UI这个请求告诉UI线程,所以这个告诉的动作就可以通过我们的Handler实现:看下面的之前,我画一个简易的流程,并不是完整的流程:      通过Looper.prepar()开启MessageQueueLooper.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显示图片,类似拖拉网络视频时,视频图片在跳的功能。



0 0
原创粉丝点击