Java 循环器、处理程序和线程
我希望将一个字节数组从应用程序的主线程(MainActivity)传递到“工作线程”,这样我就可以在工作线程中做任何我想做的事情,而不会阻塞UI(主线程)。 所以我读了关于Looper和Handler的文章,但我不理解,因为我读到我在处理程序中编写的所有内容都是在主线程中完成的,但我只想将参数/数据从主线程传递到另一个线程。Java 循环器、处理程序和线程,java,android,multithreading,Java,Android,Multithreading,我希望将一个字节数组从应用程序的主线程(MainActivity)传递到“工作线程”,这样我就可以在工作线程中做任何我想做的事情,而不会阻塞UI(主线程)。 所以我读了关于Looper和Handler的文章,但我不理解,因为我读到我在处理程序中编写的所有内容都是在主线程中完成的,但我只想将参数/数据从主线程传递到另一个线程。 有人能给我举个例子吗?处理程序处理从循环器发送的消息和可运行对象。默认情况下,新创建的线程没有活套,因为它们通常是为了执行特定任务而创建的。如果希望一个线程驻留并处理来自其
有人能给我举个例子吗?处理程序处理从循环器发送的消息和可运行对象。默认情况下,新创建的线程没有活套,因为它们通常是为了执行特定任务而创建的。如果希望一个线程驻留并处理来自其他线程的消息,那么可以为该线程创建一个循环器,并创建一个使用该循环器的处理程序 这是一个非常简单的示例,可能还有其他方法:
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>
总之,处理程序在运行特定循环器的线程内执行。因此,如果您向使用主UI线程的循环器的处理程序发送消息,那么代码将在主UI线程中执行。如果您将消息发送给一个处理程序,该处理程序有自己的在不同线程中运行的循环器,那么它将在该特定线程中运行
[编辑]嗯。回过头来看,我的答案还不完全清楚,所以让我解释一下示例中发生了什么:这里,onCreate()方法在UI线程中运行,并创建另一个线程(我们称之为Thread2)。然后它启动Thread2,Thread2创建一个Looper和处理程序,然后位于一个无限循环中,通过调用Looper.loop()处理它接收到的消息
单击测试按钮时,会向Thread2处理程序发送一条消息。Thread2什么也不做,只是坐在那里等待消息,它注意到新消息并将其传递给处理程序,该处理程序调用重写的handleMessage()方法,该方法写入日志。然后,Thread2使用
Looper
恢复等待消息的任务,而Handler
的级别非常低。大多数开发人员使用更高级别的解决方案会得到更好的服务:AsyncTask
、RxJava、LiveData
、JobIntentService
,等等@commonware它们是低级的,但也是您列出的最简单的解决方案。有时候,在进入复杂的框架之前,最好先掌握简单而有效的东西,这些框架是建立在这些简单的东西之上的;thread.start();应该像线一样;线程=新线程(newtestthread());thread.start();但是,我无法访问新线程的处理程序……对不起,我不明白你在这里想说什么。示例代码清楚地创建了一个新线程,new关键字和它扩展了thread类的事实表明了这一点。如果您无法访问处理程序,那么可能意味着您的特定线程类不是内部类,在这种情况下,您可以将public关键字添加到处理程序字段declarationOK,我现在明白您的意思了。建议的代码创建两个对象,将TestThread作为可运行对象传递给另一个Thread对象。您不需要这样做,因为您可以直接扩展线程并保存额外的对象。无法访问处理程序字段,因为它属于TestThread类,而不是Thread类。按照我写的方式使用代码。我向你保证它是有效的,我在发布之前测试过它
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// Process message within main UI thread
}
};