java - Android:如何从工作线程到服务进行通信

标签 java android multithreading android-service

我创建了一个服务类和一个在单独线程中执行的工作类。我想在它们之间建立通信,以便工作人员可以将一些状态发送回服务。

我尝试将我的工作线程 Thread 转换为 HandlerThread 并在服务端设置 Handler,但后来我没有知道如何实际从工作人员发送消息。看来我无法理解这个概念。

这是我的类(class)(没有通信逻辑):

服务类别

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

worker 类(Class)

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的情况下从线程发送消息?

最佳答案

看来我终于成功了!

为了将数据从线程传递回服务,您需要执行以下操作:

  1. 在服务内部创建 Handler 类的子类(例如,将其称为 LocalHandler)。您必须将其设为静态。重写handleMessage方法,它将从线程接收消息。

  2. 向您的 Thread 构造函数添加一个 Handler 参数。在服务中实例化您的 LocalHandler 类,并通过构造函数将其注入(inject)到您的线程中。

  3. 保存对线程内部 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");
    }
}

worker 类(线程)

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

我希望这是一个有效的实现。如果您现在有更好的方法 - 请告诉我。

关于java - Android:如何从工作线程到服务进行通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28915610/

相关文章:

java - 需要帮助调试我的 android-java 代码

java - 使用 Dropbox 进行分页

java - runOnUiThread : Cant touch the View,异常

java - 使用 Java IO 读取文件时返回 "impossible"null

java - 关闭预览模式时,动态壁纸引擎不会调用 onDestroy

java - Guava Optional 类型,当转换返回另一个 Optional

android - 使用 AMD 处理器启动 AVD 时出错

java - 如何将 FloatingActionButton 放到 Fragment 中?

java - 如何知道手机何时收到消息

python - 如何将 asyncio 与其他操作系统线程同步?