How to create a Looper thread, then send it a message immediately?

后端 未结 4 1724
离开以前
离开以前 2020-11-30 17:47

I have a worker thread that sits in the background, processing messages. Something like this:

class Worker extends Thread {

    public volatile Handler hand         


        
相关标签:
4条回答
  • 2020-11-30 17:52

    Eventual solution (minus error checking), thanks to CommonsWare:

    class Worker extends HandlerThread {
    
        // ...
    
        public synchronized void waitUntilReady() {
            d_handler = new Handler(getLooper(), d_messageHandler);
        }
    
    }
    

    And from the main thread:

    Worker worker = new Worker();
    worker.start();
    worker.waitUntilReady(); // <- ADDED
    worker.handler.sendMessage(...);
    

    This works thanks to the semantics of HandlerThread.getLooper() which blocks until the looper has been initialized.


    Incidentally, this is similar to my solution #1 above, since the HandlerThread is implemented roughly as follows (gotta love open source):

    public void run() {
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Looper.loop();
    }
    
    public Looper getLooper() {
        synchronized (this) {
            while (mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }
    

    The key difference is that it doesn't check whether the worker thread is running, but that it has actually created a looper; and the way to do so is to store the looper in a private field. Nice!

    0 讨论(0)
  • 2020-11-30 18:03

    take a look at the source code of HandlerThread

    @Override
         public void run() {
             mTid = Process.myTid();
             Looper.prepare();
             synchronized (this) {
                 mLooper = Looper.myLooper();
                 notifyAll();
             }
             Process.setThreadPriority(mPriority);
             onLooperPrepared();
             Looper.loop();
             mTid = -1;
         }
    

    Basically, if you are extending Thread in worker and implementing your own Looper, then your main thread class should extend worker and set your handler there.

    0 讨论(0)
  • 2020-11-30 18:04

    This is my solutions: MainActivity:

    //Other Code
    
     mCountDownLatch = new CountDownLatch(1);
            mainApp = this;
            WorkerThread workerThread = new WorkerThread(mCountDownLatch);
            workerThread.start();
            try {
                mCountDownLatch.await();
                Log.i("MsgToWorkerThread", "Worker Thread is up and running. We can send message to it now...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Toast.makeText(this, "Trial run...", Toast.LENGTH_LONG).show();
            Message msg = workerThread.workerThreadHandler.obtainMessage();
            workerThread.workerThreadHandler.sendMessage(msg);
    

    The WorkerThread Class:

    public class WorkerThread extends Thread{
    
        public Handler workerThreadHandler;
        CountDownLatch mLatch;
    
        public WorkerThread(CountDownLatch latch){
    
            mLatch = latch;
        }
    
    
        public void run() {
            Looper.prepare();
            workerThreadHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
    
                    Log.i("MsgToWorkerThread", "Message received from UI thread...");
                            MainActivity.getMainApp().runOnUiThread(new Runnable() {
    
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.getMainApp().getApplicationContext(), "Message received in worker thread from UI thread", Toast.LENGTH_LONG).show();
                                    //Log.i("MsgToWorkerThread", "Message received from UI thread...");
                                }
                            });
    
                }
    
            };
            Log.i("MsgToWorkerThread", "Worker thread ready...");
            mLatch.countDown();
            Looper.loop();
        }
    }
    
    0 讨论(0)
  • 2020-11-30 18:13
        class WorkerThread extends Thread {
                private Exchanger<Void> mStartExchanger = new Exchanger<Void>();
                private Handler mHandler;
                public Handler getHandler() {
                        return mHandler;
                }
                @Override
                public void run() {
                        Looper.prepare();
                        mHandler = new Handler();
                        try {
                                mStartExchanger.exchange(null);
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                        Looper.loop();
                }
    
                @Override
                public synchronized void start() {
                        super.start();
                        try {
                                mStartExchanger.exchange(null);
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                }
        }
    
    0 讨论(0)
提交回复
热议问题