Handler 相关知识(一)使用

根据Handler创建时所在的线程不同使用方式也有些不同

一、在主线程中

示例代码如下:

public class MainActivity extends AppCompatActivity {
    private static final int MSG_1 = 1;
    private static final int MSG_2 = 2;
    Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            //在主线程中处理所要进行的操作
            switch (msg.what) {
                case MSG_1:
                    //TODO 处理相关问题
                    Log.i("handler", "MSG_1,当前线程名称:" + Thread.currentThread().getName());
                    break;
                case MSG_2:
                    //TODO 处理相关问题
                    Log.i("handler", "MSG_2,当前线程名称:" + Thread.currentThread().getName());
                    break;
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sendMessage();
        postTask();
    }
    private void sendMessage() {
        //从主线程中发送消息
        handler.sendEmptyMessage(MSG_1);

        new Thread(new Runnable() {
            @Override
            public void run() {
                //从工作线程中发送消息
                handler.sendEmptyMessage(MSG_2);
            }
        }).start();
    }
    private void postTask() {
        //主线程中发送延时任务
        handler.postDelayed(() -> {
            Log.i("handler", "主线程中的postTask,当前线程名称:" + Thread.currentThread().getName());
        }, 1000);

        new Thread(() -> {
            //工作线程中发送延时任务
            handler.postDelayed(() -> {
                Log.i("handler", "工作线程中的postTask,当前线程名称:" + Thread.currentThread().getName());
            }, 1000);
        }).start();
    }
}

打印日志:

2021-01-07 11:50:25.433 5693-5693/com.example.behaviorapplication I/handler: MSG_1,当前线程名称:main
2021-01-07 11:50:25.433 5693-5693/com.example.behaviorapplication I/handler: MSG_2,当前线程名称:main
2021-01-07 11:50:26.400 5693-5693/com.example.behaviorapplication I/handler: 主线程中的postTask,当前线程名称:main
2021-01-07 11:50:26.400 5693-5693/com.example.behaviorapplication I/handler: 工作线程中的postTask,当前线程名称:main

在主线程中创建的Handler对象,不管是否从工作线程中发送消息或任务,所要处理的操作都是在主线程。

二、在工作线程中

示例代码如下:

public class MainActivity2 extends AppCompatActivity {
    private static final int MSG_1 = 1;
    private static final int MSG_2 = 2;
    Handler threadHandler;
    Handler mainHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (threadHandler == null) {
                mainHandler.sendEmptyMessageDelayed(1, 1000);
            } else {
                sendMsg();
                postTask();
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        initThreadHandler();
        mainHandler.sendEmptyMessageDelayed(1, 1000);
    }

    /**
     * 在工作线程中创建handler
     */
    private void initThreadHandler() {
        new Thread(() -> {
            //创建当前线程的looper,必须在handler创建之前,否则报错
            Looper.prepare();
            Log.i("handler", "创建threadHandler,当前线程名称:" + Thread.currentThread().getName());
            threadHandler = new Handler() {
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    //在工作线程中处理所要进行的操作
                    switch (msg.what) {
                        case MSG_1:
                            //TODO 处理相关问题
                            Log.i("handler", "处理消息MSG_1,当前线程名称:" + Thread.currentThread().getName());
                            break;
                        case MSG_2:
                            //TODO 处理相关问题
                            Log.i("handler", "处理消息MSG_2,当前线程名称:" + Thread.currentThread().getName());
                            break;
                    }
                }
            };
            //启动消息队列处理工作
            Looper.loop();
        }).start();
    }

    /**
     * 发送消息
     */
    private void sendMsg() {
        //从主线程中发送消息
        Log.i("handler", "发送MSG_1,当前线程名称:" + Thread.currentThread().getName());
        threadHandler.sendEmptyMessage(MSG_1);

        new Thread(new Runnable() {
            @Override
            public void run() {
                //从工作线程中发送消息
                Log.i("handler", "发送MSG_2,当前线程名称:" + Thread.currentThread().getName());
                threadHandler.sendEmptyMessage(MSG_2);
            }
        }).start();
    }

    /**
     * 开启延迟任务
     */
    private void postTask() {
        //主线程中发送延时任务
        threadHandler.postDelayed(() -> {
            Log.i("handler", "主线程中的postTask,当前线程名称:" + Thread.currentThread().getName());
        }, 1000);

        new Thread(() -> {
            //工作线程中发送延时任务
            threadHandler.postDelayed(() -> {
                Log.i("handler", "工作线程中的postTask,当前线程名称:" + Thread.currentThread().getName());
            }, 1000);
        }).start();
    }
}

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (threadHandler != null) {
            //手动停止looper,否则会引发内存泄漏
            threadHandler.getLooper().quit();
        }
    }

注意Looper.loop();是一个双层嵌套的死循环,需要手动的将Looper关闭(或者关闭对应的线程),否则很容易引发内存泄漏:

        if (threadHandler != null) {
            threadHandler.getLooper().quit();
        }

打印日志:

2021-01-07 12:27:28.903 8206-8373/com.example.behaviorapplication I/handler: 创建threadHandler,当前线程名称:Thread-6
2021-01-07 12:27:29.904 8206-8206/com.example.behaviorapplication I/handler: 发送MSG_1,当前线程名称:main
2021-01-07 12:27:29.906 8206-8373/com.example.behaviorapplication I/handler: 处理消息MSG_1,当前线程名称:Thread-6
2021-01-07 12:27:29.907 8206-8379/com.example.behaviorapplication I/handler: 发送MSG_2,当前线程名称:Thread-8
2021-01-07 12:27:29.907 8206-8373/com.example.behaviorapplication I/handler: 处理消息MSG_2,当前线程名称:Thread-6
2021-01-07 12:27:30.909 8206-8373/com.example.behaviorapplication I/handler: 主线程中的postTask,当前线程名称:Thread-6
2021-01-07 12:27:30.909 8206-8373/com.example.behaviorapplication I/handler: 工作线程中的postTask,当前线程名称:Thread-6

在工作线程中创建的handler,不管从哪个线程中发送的消息或任务,所要处理的操作都是在创建handler的线程中。

我们在主线程中创建Handler时,没有处理Looper相关的代码,是因为在app启动主线程创建的过程中已经处理过了,可以在ActivityThreadpublic static void main(String[] args)中查看相关代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容