Android_handler

背景:

  1.主线程(UI线程):主要负责UI更新,为了提高性能,Android的UI线程是不安全的,子线程无法直接更新UI

  2.消息循环机制:UI线程是个死循环

应用:1.定时任务

  2.线程与线程交互

handler方法使用:

简单使用:子线程通知UI更新

public class MainActivity extends AppCompatActivity {

    protected Handler handler;
    protected TextView textView;

    @SuppressLint("HandlerLeak")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        /*
        UI线程
        */
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //主线程接受到子线程发送的消息,更新数据
                if(msg.what == 1001011){
                    textView.setText("消息");
                }
            }
        };

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //又可能做大量耗时操作如下载文件
                new Thread(){
                    @Override
                    public void run() {
                        //子线程发送消息
                        handler.sendEmptyMessage(1001011);
                    }
                }.start();
            }
        });
    }
}

如果在子线程中直接更新UI:

  则会提示异常信息:只有在主线程中才能更新view

常用方法:

 //使用obtain实例化Message(建议),会做一个缓存
                        Message message = Message.obtain();
                        //标识,相当于密码箱的密码,int类型
                        message.what = 10010;
                        message.arg1 = 10011;
                        message.arg2 = 10012;
                        //对象,可以是上下文
                        message.obj = MainActivity.this;
                        //空消息
                        handler.sendEmptyMessage(1001013);
                        //约定一个时间发送,绝对时间 准时发送
                        handler.sendMessageAtTime(message,6000);
                        //相对时间  XX秒后发送
                        handler.sendMessageDelayed(message,2000);
                        //发送一个可执行程序,立即发出
                        Runnable runnable = new Runnable() {
                            @Override
                            public void run() {
                                int a = 1 + 3;
                            }
                        };
                        handler.post(runnable);
                        //执行程序时使用run方法
                        runnable.run();
                        //定时任务
                        handler.postAtTime(runnable,2000);

Demo:

1.下载文件并更新进度条 

public class DownActivity extends AppCompatActivity {

    public static final int INT = 1001011;
    protected ProgressBar progressBar;
    protected Handler handler;

    private static final String TAG = "DownActivity";
    protected int progress;

    @SuppressLint("HandlerLeak")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down);
        findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                downData();
            }
        });
        progressBar = findViewById(R.id.progressBar);
        /**
         * UI线程接收消息
         */
        handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == INT){
                    Log.e(TAG, "handleMessage: "+ "判断成功" );
                    progress = (Integer) msg.obj;
                    //设置进度条进度
                    progressBar.setProgress(progress);
                }
            }
        };
    }

    private void downData() {
        /**
         * 子线程,下载文件
         */
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL("https://clfile.imooc.com/class/assist/119/4289211/Handler%E6%BA%90%E7%A0%81(%E4%BB%A3%E7%A0%81%E7%BB%8F%E8%BF%87%E5%B0%81%E8%A3%85).rar");
                    HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                    InputStream inputStream = httpURLConnection.getInputStream();
                    //获取文件总长度
                    int filesize = httpURLConnection.getContentLength();
                    //下载文件夹名称
                    String downloadFolderName = Environment.getExternalStorageDirectory() + File.separator + "我的下载文件"  + File.separator;
                    File file = new File(downloadFolderName);
                    //如果文件夹不存在,则创建
                    if(!file.exists()){
                        file.mkdir();
                    }
                    //下载文件名
                    String filename = downloadFolderName + "源代码";
                    File file1 = new File(filename);
                    if(file1.exists()){
                        file1.delete();
                    }
                    //已下载文件长度
                    int downsize = 0;
                    int len = 0;
                    byte[] b = new byte[1024*10];
                    OutputStream outputStream= new FileOutputStream(filename);
                   while ((len = inputStream.read(b)) != -1){
                       outputStream.write(b,0,len);
                       downsize += len;
                       Message message = Message.obtain();
                       message.obj = downsize*100/filesize;
                       message.what = INT;
                        handler.sendMessage(message);
                    }


                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();
    }
}

下载网络图片,通过handle更新ImageView控件显示图片

public class PicActivity extends AppCompatActivity {
    MyHandler2 myHandler2 = new MyHandler2(this);
    protected ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_pic);
        imageView = findViewById(R.id.imageView);
        findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getPicture();

            }
        });
    }

    void getPicture(){
       new Thread(new Runnable() {
           @Override
           public void run() {
               try {
                   URL url = new URL("https://img2.mukewang.com/5adfee7f0001cbb906000338-240-135.jpg");
                   HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                   httpURLConnection.setRequestMethod("GET");
                   httpURLConnection.setConnectTimeout(5000);
                   if (httpURLConnection.getResponseCode() ==200){
                       InputStream inputStream = httpURLConnection.getInputStream();
                       //获取流
                       Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                       Message message = Message.obtain();
                       message.what = 10010;
                       message.obj = bitmap;
                       //发送消息
                       myHandler2.sendMessage(message);
                   }

               } catch (MalformedURLException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }

           }).start();
       }

    /**
     * 静态 弱引用 handle 避免发生内存泄漏
     * 当handle持有PicActivity的引用也能被回收
     */
    static class  MyHandler2 extends Handler{
        WeakReference<PicActivity> weakReference;

        private MyHandler2(PicActivity activity) {
            this.weakReference =new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //获取当前activity
            PicActivity picActivity = weakReference.get();
            switch (msg.what){
                case 10010:
                    Bitmap bitmap = (Bitmap) msg.obj;
                    picActivity.imageView.setImageBitmap(bitmap);
            }
        }
    }
}

通过handle更新显示内容,通过延迟发送sendMessageDelayed,实现倒计时功能

public class TimeActivity extends AppCompatActivity {

    public static final int MAX = 10;
    public static final int CODE = 10010;
    protected TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_time);
        textView = findViewById(R.id.textView2);
        MyHandler myHandler = new MyHandler(this);
        Message message = Message.obtain();
        message.what = 10010;
        message.arg1 = MAX;
        myHandler.sendMessageDelayed(message, 1000);

    }

  public static class MyHandler extends Handler {
        WeakReference<TimeActivity> weakReference;

        private MyHandler(TimeActivity activity) {
            this.weakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int value = 0;
            TimeActivity timeActivity = weakReference.get();
            if (msg.what == 10010) {
                value = msg.arg1;
                timeActivity.textView.setText(String.valueOf(value--));
            }
            //实现消息循环发送,直至不满足条件
            if (value > 0) {
                Message message = Message.obtain();
                message.what = 10010;
                message.arg1 = value;
                sendMessageDelayed(message, 1000);
            }
        }
    }
}
原文地址:https://www.cnblogs.com/conglingkaishi/p/9373972.html