zoukankan      html  css  js  c++  java
  • 什么是Handler

    定义

    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进行处理。

    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;
        }
    }
    很想高飞,但我不能;不想天空,剩我一人。
  • 相关阅读:
    选择学习Web前端开发的理由
    在Nginx下部署SSL证书并重定向至HTTPS
    使用pm2快速将项目部署到远程服务器
    DNS域名解析过程
    HTML5新特性总结
    基于 HTML5 Canvas 的智能安防 SCADA 巡逻模块
    react中使用css的7种方式
    原生JS实现滑动轮播图
    H5与企业微信jssdk集成
    img图片不存在显示默认图
  • 原文地址:https://www.cnblogs.com/lixiansheng/p/11192281.html
Copyright © 2011-2022 走看看