我创建了一个服务类和一个在单独的线程中执行的工作类。我想在它们之间建立通信,因此工作人员可以将某些状态发送回服务。
我已尝试将我的工作人员Thread
转换为HandlerThread
并在服务端设置Handler
,但后来我不知道如何实际发送来自工人的消息。看起来我无法理解这个概念。
这是我的课程(没有沟通逻辑):
package com.example.app;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class ConnectionService extends Service {
protected ConnectionWorker thread;
@Override
public void onCreate() {
super.onCreate();
// Creating a connection worker thread instance.
// Not starting it yet.
this.thread = new ConnectionWorker();
Log.d(this.getClass().getName(), "Service created");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(this.getClass().getName(), "Service started");
// Checking if worker thread is already running.
if (!this.thread.isAlive()) {
Log.d(this.getClass().getName(), "Starting working thread");
// Starting the worker thread.
this.thread.start();
}
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Log.d(this.getClass().getName(), "Stopping thread");
// Stopping the thread.
this.thread.interrupt();
Log.d(this.getClass().getName(), "Stopping service");
super.onDestroy();
Log.d(this.getClass().getName(), "Service destroyed");
}
}
package com.example.app;
import android.os.SystemClock;
import android.util.Log;
public class ConnectionWorker extends Thread {
public ConnectionWorker() {
super(ConnectionWorker.class.getName());
}
@Override
public void run() {
super.run();
Log.d(this.getClass().getName(), "Thread started");
// Doing the work indefinitely.
while (true) {
if (this.isInterrupted()) {
// Terminating this method when thread is interrupted.
return;
}
// @todo: send a message to the service
Log.d(this.getClass().getName(), "Doing some work for 3 seconds...");
SystemClock.sleep(3 * 1000);
}
}
}
如何实现HandlerThread
,从工作线程发送消息并在我的服务中接收消息?
我将非常感谢代码示例。
实际上,看起来我无法在我的线程中使用Looper
因为它会阻止线程执行而我不想这样做。是否可以在不使用Looper
的情况下从线程发送消息?
答案 0 :(得分:2)
看起来我终于把它钉了!
为了将数据从线程传递回服务,您需要执行以下操作:
在您的服务中对Handler
类进行子类化(称之为LocalHandler
)。你必须使它静止。覆盖handleMessage
方法,它将从线程接收消息。
向Handler
构造函数添加Thread
参数。在服务中实例化您的LocalHandler
类,并通过构造函数将其注入您的线程。
保存对线程内Handler
的引用,并在适当的时候使用它来发送消息。
以下是完整的示例:
package com.example.app;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
public class ConnectionService extends Service {
protected ConnectionWorker thread;
static class LocalHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Log.d(this.getClass().getName(), "Message received: " + (String) msg.obj);
}
}
protected Handler handler;
@Override
public void onCreate() {
super.onCreate();
// Instantiating overloaded handler.
this.handler = new LocalHandler();
// Creating a connection worker thread instance.
// Not starting it yet.
// Injecting our handler.
this.thread = new ConnectionWorker(this.handler);
Log.d(this.getClass().getName(), "Service created");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(this.getClass().getName(), "Trying to start the service");
// Checking if worker thread is already running.
if (!this.thread.isAlive()) {
Log.d(this.getClass().getName(), "Starting working thread");
// Starting the worker thread.
this.thread.start();
Log.d(this.getClass().getName(), "Service started");
}
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Log.d(this.getClass().getName(), "Stopping thread");
// Stopping the thread.
this.thread.interrupt();
Log.d(this.getClass().getName(), "Stopping service");
super.onDestroy();
Log.d(this.getClass().getName(), "Service destroyed");
}
}
package com.example.app;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
public class ConnectionWorker extends Thread {
// Reference to service's handler.
protected Handler handler;
public ConnectionWorker(Handler handler) {
super(ConnectionWorker.class.getName());
// Saving injected reference.
this.handler = handler;
}
@Override
public void run() {
super.run();
Log.d(this.getClass().getName(), "Thread started");
// Doing the work indefinitely.
while (true) {
if (this.isInterrupted()) {
// Terminating this method when thread is interrupted.
return;
}
Log.d(this.getClass().getName(), "Doing some work for 3 seconds...");
// Sending a message back to the service via handler.
Message message = this.handler.obtainMessage();
message.obj = "Waiting for 3 seconds";
this.handler.sendMessage(message);
SystemClock.sleep(3 * 1000);
}
}
}
我希望这是一个有效的实现。如果你现在有更好的方法 - 请告诉我。
答案 1 :(得分:0)
为什么Android在Thread存在时会有HandlerThread?
这是因为正如documentation所说,HandleThread是
用于启动具有looper的新线程的方便类。弯针 然后可以用于创建处理程序类。请注意start()必须 仍被称为。
Looper如何用于创建处理程序?
应该在Handler的构造函数中传递一个Looper来告诉Handler它正在使用哪个Looper。
因此每个HandlerThread都有一个Looper,并且可以有许多处理程序处理Looper循环的消息。
当您使用默认构造函数在Service类中创建新的Handler时,Handler会与当前的Looper关联,如其文档中所述。
处理程序()
默认构造函数将此处理程序与Looper相关联 当前线程。如果这个线程没有looper,那么这个处理程序 无法接收消息,因此会抛出异常。
您可以通过打印此
来确认问题仍然存在Thread.currentThread().getId()
在适当的位置 - 在服务器的onCreate()
内,在处理程序的handleMessage()
内和ConnectionWorker的run()
内。那么如何解决你的问题?
即使在服务中,您也可以创建一个HandlerThread,当它的Looper准备就绪时,使用该Looper创建Handler。
new HandlerThread("ConnectionWorker") {
@Override
protected void onLooperPrepared() {
new Handler(getLooper()).post(new Runnable() {
@Override
public void run() {
// do your stuff
getLooper().quitSafely();
}
});
}
}.start();
希望答案为时已晚:P