Loopers,Handlers和Threads

时间:2018-05-05 19:40:05

标签: java android multithreading

我希望将一个字节数组从应用程序的主线程(MainActivity)传递给“工作线程”,这样我就可以在工作线程中做任何我想做的事情,而不会阻塞UI(主线程)。 所以我读到了关于Looper和Handler但我没理解它,因为我读到我在处理程序中编写的所有内容都是在主线程中完成的,但我只想将参数/数据从主线程传递给另一个线程。 有人可以举个例子吗?

1 个答案:

答案 0 :(得分:0)

处理程序处理从Looper调度的消息和Runnable对象。默认情况下,新创建的线程没有Looper,因为它们通常是为执行特定任务而创建的。如果你想要一个线程来处理来自其他线程的消息,那么你可以为该线程创建一个Looper以及一个使用looper的处理程序

这是一个非常简单的例子,可能还有其他方法:

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();
    }

}

以下是活动:

<?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>

您还可以创建使用主线程的Looper的处理程序。这样做是为了让你的线程可以将消息发送回主线程。在这种情况下,您可以像这样创建处理程序:

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

总结一下,处理程序在运行特定Looper的线程内执行。因此,如果您向使用主UI线程的Looper的处理程序发送消息,则代码将在主UI线程中执行。如果您将消息发送给具有在不同线程中运行的自己的Looper的Handler,那么它将在该特定线程内运行。

[编辑]嗯。回过头来看,我的答案仍然不完全清楚所以让我解释一下示例中发生了什么:这里,onCreate()方法在UI线程中运行并创建另一个线程(我们称之为Thread2)。然后它启动Thread2,它创建一个Looper和Handler,然后处于一个无限循环中,通过调用Looper.loop()来处理它收到的消息

单击“测试”按钮时,会向Thread2处理程序发送一条消息。 Thread2,除了坐在那里等待消息之外什么都不做,注意到新消息并将其传递给Handler,后者调用覆盖的handleMessage()方法,该方法写入日志。然后Thread2恢复它等待消息的任务