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