• Android Handler使用


    1. 介绍

    Handler允许向关联线程的消息队列(MessageQueue)发送消息(Message)和可执行对象(Runnable).
    每个Handler实例都与某个线程(即创建该Handler的线程)及该线程的消息队列所关联

    Handler主要有两种用途

    - 调度消息和可执行对象在未来某个时间点的处理
    - 在其他线程中执行动作

    2. 实例

    2.1 基本实例

    注意: 实例中myRunnable方法是被UI线程执行

    File: activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.lineto.testhandler.MainActivity">
    
        <Button
            android:id="@+id/start"
            android:text="start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
        <Button
            android:id="@+id/stop"
            android:text="stop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
    </LinearLayout>

    File: MainActivity.java

    public class MainActivity extends AppCompatActivity {
        private Button start;
        private Button stop;
        private Handler handler;
        private Runnable myRunnable;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            start = (Button)findViewById(R.id.start);
            stop  = (Button)findViewById(R.id.stop);
    
            View.OnClickListener listener = new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Button button = (Button)v;
                    if (button == start) {
                        handler.post(myRunnable);
                    } else if (v == stop) {
                        handler.removeCallbacks(myRunnable);
                    }
                }
            };
            start.setOnClickListener(listener);
            stop.setOnClickListener(listener);
    
            handler = new Handler();
            myRunnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("Run method");
                    handler.postDelayed(myRunnable, 3000);
                }
            };
        }
    }

    2.2 进度条实例

    在该实例中, 分别采用两种方式来实现
    一种是runnable方法由UI线程来执行, 另一种是runnable方法由新线程来执行
    可以发现第一种会导致界面卡顿, 后面一种才是Handler的正确使用方法

    File: activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.lineto.handlerprogressbar.MainActivity">
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="ProgressBar With Handler"
            />
        <ProgressBar
            android:id="@+id/progressbar"
            style="@android:style/Widget.ProgressBar.Horizontal"
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:visibility="gone"
            />
        <Button
            android:id="@+id/start"
            android:text="Start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <Button
            android:id="@+id/stop"
            android:text="Stop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </LinearLayout>

    File: MainActivity.java

    public class MainActivity extends AppCompatActivity {
        private ProgressBar progressBar;
        private Button start;
        private Button stop;
        private Handler handler;
        private boolean use_new_thread = true;
        private boolean thread_running = false;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            progressBar = (ProgressBar)findViewById(R.id.progressbar);
            start       = (Button)findViewById(R.id.start);
            stop        = (Button)findViewById(R.id.stop);
    
            final Runnable myRunnable = new Runnable() {
                int i = 0;
                @Override
                public void run() {
                    do {
                        try {
                            Thread.sleep(1000);
                        } catch (Exception e) {
                            System.out.println(e);
                        }
                        if (i < 100) {
                            i += 10;
                        } else {
                            i = 0;
                        }
                        Message msg = handler.obtainMessage();
                        msg.arg1 = i;
                        handler.sendMessage(msg);
                    } while(thread_running);
                }
            };
    
            View.OnClickListener listener = new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (v == start) {
                        Toast toast = Toast.makeText(MainActivity.this, "Start", Toast.LENGTH_SHORT);
                        toast.show();
                        progressBar.setVisibility(View.VISIBLE);
                        if (use_new_thread) {
                            thread_running = true;
                            Thread thread = new Thread(myRunnable);
                            thread.start();
                        } else {
                            thread_running = false;
                            handler.post(myRunnable);
                        }
                    }
                    else if(v == stop) {
                        Toast toast = Toast.makeText(MainActivity.this, "Stop", Toast.LENGTH_SHORT);
                        toast.show();
                        progressBar.setVisibility(View.GONE);
                        if (use_new_thread) {
                            thread_running = false;
                        } else {
                            handler.removeCallbacks(myRunnable);
                        }
                    }
                }
            };
    
            start.setOnClickListener(listener);
            stop.setOnClickListener(listener);
    
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    progressBar.setProgress(msg.arg1);
                    if (!use_new_thread) {
                        handler.post(myRunnable);
                    }
                }
            };
    
        }
    }

    3. Looper

    Looper是用于给线程添加一个消息队列(MessageQueue), 并且循环等待; 当有消息时会唤起线程来处理消息的类.
    UI线程默认包含一个Looper, 所以通常不需要为新线程创建Looper;当为新线程创建Looper后, 通常使用Handler来进行消息交互

    下面是一个典型的Looper使用方法

    class LooperThread extends Thread {
          public Handler mHandler;
    
          public void run() {
              Looper.prepare();
    
              mHandler = new Handler() {
                  public void handleMessage(Message msg) {
                      // process incoming messages here
                  }
              };
    
              Looper.loop();
          }
      }

    详细的实例参考<Android实战技巧:消息循环与Looper>

    4. HandlerThread

    HandlerThread是一个拥有Looper的Thread, 然后可以使用该Looper得到一个Handler(一定要在start()方法之后)
    需要注意的是程序结束的时候需要退出Looper(quit()/quitSafely())

    相关实例参考<Android HandlerThread 完全解析>

    5. Message

    Message用于在消息循环中通信, 用来发消息给某个Handler, 可以通过Handler的obtainMessage()从消息池中获取一个Message引用;Message常用的方法是赋值, 相关操作查询API即可

    参考:
    <Android 异步消息处理机制>
    <Android中的Handler的机制与用法详解>

  • 相关阅读:
    haproxy 看到的是https,后台是http的原因
    frontend http 前端名字定义问题
    frontend http 前端名字定义问题
    Git学习总结(3)——代码托管平台简介
    Git学习总结(3)——代码托管平台简介
    Git学习总结(3)——代码托管平台简介
    [置顶] 开源史上最成功的8个开源产品
    [置顶] 开源史上最成功的8个开源产品
    [置顶] 开源史上最成功的8个开源产品
    Maven学习总结(十一)——Maven项目对象模型pom.xml文件详解
  • 原文地址:https://www.cnblogs.com/hzl6255/p/6705048.html
Copyright © 2020-2023  润新知