handler消息处理机制原理

时间:2020-12-01 17:49:08
01_消息处理机制的原理(重点)

使用handler的步骤:

    1.在主线程中创建handler成员变量;

    2.在子线程中得到handler,调用sendMessage方法,给主线程发送一个消息,说我要修改UI界面;

    3.handler经过主线程的授权后,修改UI界面;

handler的工作原理(handler/message/looper三者之间的关系):
    
    补充前提知识:所有使用UI界面的操作系统,后台都运行着一个死循环(Looper),它在不停的监听和接收用户发出的指令,一旦接收到指令就会立即执行;

    在应用程序已启动的时候,系统就给它提供了死循环(Looper);当子线程需要发送消息(修改UI界面),就会调用handler的sendMessage方法给主线程发送一个消息(Message),handler会把消息放到looper中的消息队列(MessageQueue)中;在Looper中还有一个死循环,这个死循环在不停的从消息队列中读取消息,取到消息后分发给handler,handler在调用handleMessage方法修改UI界面;

代码:

    package com.itheima.picview;

    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.text.TextUtils;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        private EditText et_path;
        private ImageView iv_image;
        
        //1.在主线程中创建handler成员变量;
        private Handler handler = new Handler(){
            
            /**
             * 接收和处理消息
             */
            public void handleMessage(Message msg) {
                // 接收消息
                Bitmap bitmap = (Bitmap) msg.obj;
                
                //  处理消息:修改UI界面
                iv_image.setImageBitmap(bitmap);
                
            
            };
        };
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            // 1.找到控件对象
            et_path = (EditText) findViewById(R.id.et_path);
            iv_image = (ImageView) findViewById(R.id.iv_image);
        }
    
        /**
         * 查看网络上的一张图片
         * @param view
         */
       public void viewPic(View view){
           // 2.从输入框中得到用户输入的图片网络路径
           final String path = et_path.getText().toString().trim();
           if(TextUtils.isEmpty(path)){
               Toast.makeText(this, "请输入图片的网络路径", 0).show();
               return;
           }else{
             // 把访问网络的代码写在子线程中;
               new Thread(){
                   public void run() {
                       try {
                            // 3.访问网络,从网络上获得图片的数据,显示在imageview上
    
    //                3.1.创建URL对象,打开一个http类型的连接;
                            URL url = new URL(path);
                            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    //                3.2.给连接设置请求参数:请求方式(GET,POST),连接的超时时间,请求方式必须大小;
                            conn.setRequestMethod("GET");  // ,默认使用GET方式
                            conn.setConnectTimeout(3000); //超时时间为3000毫秒
                            // 设置其他参数
    //                        conn.setRequestProperty("Accept-Language", "zh-CN");
    //                3.3.服务器给客户端返回数据:响应码为200 客户端正常发送请求,服务器端返回数据成功,404 找不到数据资源,503 服务器内部错误;
    //                首先判断服务器返回的响应码是不是200.服务器端是以二进制流的形式返回数据的;然后接收二进制流的数据.
                            // 得到服务器端返回的响应码
                            int code = conn.getResponseCode();
                            if(code == 200){ // 服务器端返回数据成功
                                // 接受服务器端返回的二进制输入流
                                InputStream is = conn.getInputStream();
                                
                                Bitmap bitmap = BitmapFactory.decodeStream(is);
                                // 2.在子线程中得到handler,调用sendMessage方法,给主线程发送一个消息,说我要修改UI界面;
                                // 创建一个消息对象:消息盒子
                                Message msg =new Message();
                                msg.obj = bitmap;
                                handler.sendMessage(msg);
                            }
    //                3.4.添加访问互联网的权限;
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                   };
               }.start();
           }
       }

    }


02_消息处理常用另一个API
    
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
            tv_result.setText(result);
        }
    });