我终于读懂了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在线程间通信的优越性和它的可行性。

posted @ 2022-01-16 19:25  我的小鱼干嘞  阅读(47)  评论(0编辑  收藏  举报