简体   繁体   English

弯针,处理程序和线程

[英]Loopers, Handlers and Threads

I'm wishing to pass a byte array from the main thread of a application (MainActivity) to a "working thread" so that I can do whatever I wanna do in the working thread without blocking the UI (Main Thread). 我希望将字节数组从应用程序的主线程(MainActivity)传递到“工作线程”,以便我可以在工作线程中做我想做的任何事情而不会阻塞UI(主线程)。 So I read about Looper and Handler but I didn't understood it because I read that everything Im writing in the handler is done in the main thread, but I only want to pass arguments/data from the Main thread to the other thread. 所以我读了关于Looper和Handler的文章,但我不明白,因为我读到Im在处理器中编写的所有事情都是在主线程中完成的,但是我只想将参数/数据从Main线程传递给另一个线程。 Can someone please give me an example? 有人可以给我一个例子吗?

Handlers process messages and Runnable objects that are dispatched from a Looper. 处理程序处理从Looper调度的消息和Runnable对象。 Newly created threads do not have a Looper by default as they are usually created to perform a specific task. 默认情况下,新创建的线程通常没有Looper,因为它们通常是创建来执行特定任务的。 If you want a thread to sit and process messages from other threads then you can create a Looper for that thread plus a handler that uses the looper 如果您希望某个线程坐下来处理其他线程的消息,则可以为该线程创建一个Looper以及使用该Looper的处理程序

This is a very simple example and there are probably other ways of doing it: 这是一个非常简单的示例,可能还有其他方法可以执行此操作:

public class TestActivity extends AppCompatActivity {

TestThread thread;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);

    thread = new TestThread();
    thread.start();
}



public void testClick(View view) {
    // Check that handler object is assigned, as handler is initialised by the thread
    // itself after it has started running
    if(thread.handler != null) thread.handler.sendMessage(thread.handler.obtainMessage(123, new byte[12]));
}



private class TestThread extends Thread {

    Handler handler;


    @Override
    @SuppressLint("HandlerLeak")
    public void run() {
        // Creates the Looper object for this thread
        Looper.prepare();

        // Default Handler constructor uses the Looper of the current thread (the Looper we just created)
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // Handle message here, running within the thread
                if((msg.what == 123) && (msg.obj != null) && (msg.obj instanceof byte[]))
                    Log.d("Test", Integer.toString(((byte[])msg.obj).length) + " byte(s) received");
            }
        };

        // Does the work of actually looping and processing messages. This will
        // not return until the thread is being terminated
        Looper.loop();
    }

}

Here is the activity: 这是活动:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TestActivity">
<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:onClick="testClick"
    android:text="Test"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

You can also create Handlers that uses the main thread's Looper. 您还可以创建使用主线程的Looper的处理程序。 This is done so that to your thread can send messages back to the main thread. 这样做是为了使您的线程可以将消息发送回主线程。 In that instance you create your handler like this: 在这种情况下,您可以这样创建处理程序:

Handler handler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // Process message within main UI thread
    }
};

To sum it up, Handlers execute within the thread that is running a particular Looper. 总结起来,处理程序在运行特定Looper的线程中执行。 So if you send a message to a handler that is using the main UI thread's Looper then the code will execute in the main UI thread. 因此,如果将消息发送到使用主UI线程的Looper的处理程序,则代码将在主UI线程中执行。 If you send the message to a Handler that has it's own Looper that runs within a different thread, then it will run within that particular thread. 如果将消息发送到具有自己的Looper的Handler,该Handler在不同的线程中运行,则它将在该特定线程中运行。

[Edit] Hmmm. [编辑]嗯。 Reading back, my answer's still not totally clear so let me explain what's happening in the example: Here, the onCreate() method runs within the UI thread and creates another thread (we'll call it Thread2). 回读一遍,我的答案还不是很清楚,所以让我解释一下示例中发生的情况:在这里,onCreate()方法在UI线程中运行并创建另一个线程(我们将其称为Thread2)。 It then starts Thread2 which creates a Looper and Handler and then sits in an infinite loop, processing messages it receives by calling Looper.loop() 然后,它启动Thread2,后者创建一个Looper和Handler,然后处于无限循环中,通过调用Looper.loop()处理接收到的消息。

When the Test button is clicked a message is sent to the Thread2 Handler. 单击“测试”按钮时,消息将发送到Thread2处理程序。 Thread2, which is doing nothing but sitting there waiting for messages, notices the new message and passes it on to the Handler which calls the overridden handleMessage() method, which writes to the log. 线程2除了坐在那里等待消息外什么都不做,它注意到新消息并将其传递给处理程序,该处理程序调用重写的handleMessage()方法,该方法将其写入日志。 Thread2 then resumes it's task of waiting for messages 然后,Thread2恢复其等待消息的任务

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM