Loopers,Handlers和Threads

问题描述 投票:0回答:1

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

java android multithreading
1个回答
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 handler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        // Process message within main UI thread
    }
};

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.