• 我终于读懂了Handler(二)


    接上篇 我终于读懂了Handler(一)
    经过上一篇的阅读,相信你对handler已经有了一定的理解。本篇就开始进行实践

    1. 多个handler在多线程中的应用

    public class HandlerTestActivity extends AppCompatActivity {
        private static final String TAG = "HandlerTestActivity";
        private Handler mHandler;
        private Handler mHandler1;
        private MyThread mThread1;
        private Handler mHandler2;
        private MyThread mThread2;
    
        class MyThread extends Thread {
            private Looper mLooper;
    
            @Override
            public void run() {
                super.run();
                Looper.prepare();
                synchronized (this) {
                    mLooper = Looper.myLooper();
                    notifyAll();
                }
                Looper.loop();
            }
    
            public Looper getLooper() {
                if (!isAlive()) {
                    return null;
                }
    
                synchronized (this) {
                    while (isAlive() && mLooper == null) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                        }
                    }
                }
                return mLooper;
            }
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
           mThread1 = new MyThread();
           mThread1.start();
    
           mThread2 = new MyThread();
           mThread2.start();
    
           mHandler = new Handler() {
               @Override
               public void handleMessage(Message msg) {
                   super.handleMessage(msg);
                   Log.d(TAG,"get Message =="+msg.what);
               }
           };
           new Thread(() -> mHandler.sendEmptyMessage(10)).start();
           mHandler.sendEmptyMessage(0);
    
    
            mHandler1 = new Handler(mThread1.getLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d(TAG,"get Message =="+msg.what);
                }
            };
            mHandler1.sendEmptyMessage(1);
    
            mHandler2 = new Handler(mThread2.getLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d(TAG,"get Message =="+msg.what);
                }
            };
            mHandler2.sendEmptyMessage(2);
    
        }
    
    }
    

    输出结果:

    这里我们实验了多个线程之间发送消息的情况。

    • Handler默认实例化和Handler指定Looper对象实例化的比较
    • handler在主线程发送消息和在子线程发送消息的比较
    • 上一篇中我们也举过一下在子线程实例化Handler对象的例子。

    这样我们对Handler的理解应该更加清晰了吧!这里我们探究一下多线程中为何要像上面例子一样实现。

    1.1 指定Looper对象

    首先我们要明白一点,在上面的例子中可不可以不指定Looper对象(也就是说61行mThread1.getLooper()可不可以没有)。 答案是:可以。 即使我们加一行代码new Thread(() -> mHandler1.sendEmptyMessage(12)).start();handler1在子线程中发送消息它还是可以收到,既然这样我们是不是不需要指定Looper对象?

      如果我们没有指定Looper对象,那么我们就是用的主线程的Looper;现在我们指定了mThread1.getLooper(),mHandler1中用的就是Thread1中的Looper对象。在这里当然看不出会出什么问题,但是如果我们的Handler1是在子线程进行实例化的,那么我们就一定要指定Looper对象了,不然发送消息的时候程序怎么知道你要存到哪个线程的消息队列呢。

    1.2 getLooper()

    mThread1.getLooper()时MyThread的run方法执行了,Looper.prepare可能还没执行,所以在getLooper方法里面用wait等待,当Looper.prepare()执行了再notifyAll,这里加了把锁保证了线程安全。

    一般情况下我们使用默认的Handler实例化完全可以满足我们的日常开发需求。而上面MyThread类的创建完全是为了让我们在子线程中实例化handler进行的封装,而且是比较简陋的封装,Android系统为我们提供了更好的——HandlerThread。

    2. HandlerThread的引入

    HandlerThread比上面的MyThread考虑的更全面,而且它是核心类库自带的,我们直接用就行。

    public class HandlerThreadActivity extends AppCompatActivity {
        private static final String TAG = "HandlerThreadActivity";
        private HandlerThread mHandlerThread;
        private HandlerThread mHandlerThread1;
        private HandlerThread mHandlerThread2;
        private Handler mHandler;
        private Handler mHandler1;
        private Handler mHandler2;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mHandlerThread = new HandlerThread("handler-thread");
            mHandlerThread.start();
    
            mHandlerThread1 = new HandlerThread("handler-thread1");
            mHandlerThread1.start();
    
            mHandlerThread2 = new HandlerThread("handler-thread2");
            mHandlerThread2.start();
    
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.d(TAG,"get Message ==="+msg.what);
                }
            };
    
            new Thread(()-> {
                mHandler1 = new Handler(mHandlerThread1.getLooper()) {
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Log.d(TAG,"get Message ==="+msg.what);
                    }
                };
                mHandler.sendEmptyMessage(0);
                mHandler1.sendEmptyMessage(1);
            }).start();
    
    
            new Thread(()-> {
                mHandler2 = new Handler(mHandlerThread2.getLooper()) {
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        Log.d(TAG,"get Message ==="+msg.what);
                    }
                };
                mHandler2.sendEmptyMessage(10);
            }).start();
    
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            mHandler2.sendEmptyMessage(2);
        }
    }
    

    输出结果:

    这里简单的使用了一下,着重了多线程中实例化Handler的情况。

       第38行我们就使用了上篇中的例子,同时也是子线程做耗时操作,然后向主线程发送消息的例子,这里我们发了一个空消息,所以不需要构造消息对象。
      第30行我们创建了一个线程(这里命名为子线程1),第43行我们又创建了一个线程(这里命名为子线程2),本来想让举个这两个子线程间通信的例子。但是我如果从子线程2向子线程1发送消息的话mHandler2.sendEmptyMessage(1000),有可能子线程1还未创建,所以就没举子线程间通信的例子。但是我们应该明白handler在线程间通信的优越性和它的可行性。

  • 相关阅读:
    Asp.Net Core 轻松学-被低估的过滤器
    Asp.Net Core 轻松学-利用文件监视进行快速测试开发
    Asp.Net Core 轻松学-利用xUnit进行主机级别的网络集成测试
    Asp.Net Core 轻松学-HttpClient的演进和避坑
    Asp.Net Core 轻松学-基于微服务的后台任务调度管理器
    Asp.Net Core 轻松学-一行代码搞定文件上传
    .NET Core 2.2 新增部分功能使用尝鲜
    Asp.NetCore轻松学-业务重点-实现一个简单的手机号码验证
    Asp.Net Core 轻松学-实现跨平台的自定义Json数据包
    Asp.Net Core 轻松学-利用 Swagger 自动生成接口文档
  • 原文地址:https://www.cnblogs.com/dearnotes/p/15807365.html
Copyright © 2020-2023  润新知