定义

Handler是用来结合线程的消息队列来发送、处理"Message对象"和"Runnable对象"的工具。

每一个Handler实例之后会关联一个线程和该线程的消息队列。也就是说,当你创建一个Handler的时候,从此开始,他就会自动关联到所在的线程/消息队列,然后它就会陆续把Message/Runnable分发到消息队列,并在他们出队的时候处理掉。因为android只允许在主线程中更新UI,Handler的目的就是作为线程通信的桥梁,进而再通过主线程更新UI。使用Handler这种异步回调机制,使我们可以再完成一个很长的任务后再做出相应的通知。

Handler和Message、MessageQueue、Looper之间的关系

Message

Handler接收与处理的消息对象

MessageQueue

消息队列,以先进先出队列形式管理所有的Message,且在初始化Looper对象时会创建一个与之关联的MessageQueue。每个线程最多只有一个MessageQueue。MessageQueue通常都是由Looper来管理,而主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个MessageQueue。其他非主线程,不会自动创建Looper。

Looper

每个线程只能够一个Looper,管理MessageQueue,不断从中去除Message分发给对应的Handler处理。

通俗一点讲:当我们的子线程想修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送消息;而我们发送的消息会先到主线程的MessageQueue中进行等待,由Looper按先入先出顺序取出,再根据Message对象的what属性分发给对应的Handler进行处理。

hanlp_index 测试 测试handler是什么意思啊_消息队列

Handler的主要用途

1.推送未来某个时间点将要执行的Message或者Runnable到消息队列

 

通过Handler+Message的方式更新UI

 

public class MainActivity extends AppCompatActivity {

    private TextView text;

    private static final int UPDATE_TEXT = 1;  //整型常量用于表示更新TextView这个动作

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.id.activity_main);
        text = (TextView) findViewById(R.id.text); 
        Button chaneText = (Button) findViewById(R.id.change_text);
        change_text.setOnClickListener(this);
    }

    //新增Handler对象,并重写父类的handlerMessage()方法,在这里对具体的Message进行处理
    private Handler handler = new Handler(){  
        public void handleMessage(Message msg){  //收到消息,在HandleMessage()方法中对消息进行处理
            switch (msg.what){
                case UPDATE_TEXT:
                // 在这里进行UI操作,处于主线程中
                    text.setText("Nice to meet you");
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    public void onClick(View v){
        switch(v.getId()){
            case R.id.change_text:
                new Thread(new Runnable(){
                    @Override
                    public void run(){
                        Message message = new Message();
                        message.what = UPDATE_TEXT;    //将waht字段的值指定为UPDATE_TEXT
                        handler.sendMessage(message);    //调用Handler的sendMessage()方法发送消息
                    }
                }).start();
                break;
            default:
                break;
        }
    }
}

 

 

 

2.在子线程把需要在另一个线程执行的操作加入到消息队列中去

通过Handler + Message来实现子线程加载图片,在UI线程显示图片

public class ThreadActivity extends AppCompatActivity implements View.OnClickListener {
    private ActivityThreadBinding mBinding = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_thread);
        // 设置点击事件
        mBinding.clickBtn.setOnClickListener(this);
        mBinding.resetBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            // 响应load按钮
            case R.id.clickBtn:
                // 开启一个线程
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // 在Runnable中进行网络读取操作,返回bitmap
                        final Bitmap bitmap = loadPicFromInternet();
                        // 在子线程中实例化Handler同样是可以的,只要在构造函数的参数中传入主线程的Looper即可
                        Handler handler = new Handler(Looper.getMainLooper());
                        // 通过Handler的post Runnable到UI线程的MessageQueue中去即可
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                // 在MessageQueue出队该Runnable时进行的操作
                                mBinding.photo.setImageBitmap(bitmap);
                            }
                        });
                    }
                }).start();
                break;
            case R.id.resetBtn:
                mBinding.photo.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.default_pic));
                break;
        }
    }

    /***
     * HttpUrlConnection加载图片,不多说
     * @return
     */
    public Bitmap loadPicFromInternet() {
        Bitmap bitmap = null;
        int respondCode = 0;
        InputStream is = null;
        try {
            URL url = new URL("https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1421494343,3838991329&fm=23&gp=0.jpg");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(10 * 1000);
            connection.setReadTimeout(5 * 1000);
            connection.connect();
            respondCode = connection.getResponseCode();
            if (respondCode == 200) {
                is = connection.getInputStream();
                bitmap = BitmapFactory.decodeStream(is);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(), "访问失败", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bitmap;
    }
}

 

很想高飞,但我不能;不想天空,剩我一人。