Android:如何从工作线程与服务进行通信 [英] Android: how to communicate from worker thread to a service

查看:94
本文介绍了Android:如何从工作线程与服务进行通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've created a service class and a worker class that is executed in a separate thread. I would like to setup a communication between them, so the worker could send some status back to the service.

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

I've tried to convert my worker Thread to HandlerThread and setup a Handler on the service side, but then I don't know how to actually send a message from the worker. It looks like I can't grasp the concept.

这是我的课程(没有通讯逻辑):

Here's my classes (without communication logic):

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,从工作线程发送消息并在我的服务中接收消息?

How do I implement a HandlerThread, send messages from the worker thread and receive them in my service?

我将非常感谢一个代码示例.

I will highly appreciate a code example.

实际上,看来我不能在线程内部使用Looper,因为它会阻塞线程执行,而我不希望那样.是否可以在不使用Looper的情况下从线程发送消息?

Actually, it looks like I can't use Looper inside of my thread cause it will block the thread execution and I don't want that. Is it possible to send messages from the thread without using Looper?

推荐答案

看来我终于确定了目标!

It looks like I've finally nailed it!

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

In order to pass data from thread back to a service you will need to do this:

  1. 在服务内部将Handler类子类化(例如,将其称为LocalHandler).您将不得不使其静态.覆盖handleMessage方法,它将接收来自线程的消息.

  1. Subclass a Handler class inside of your service (call it e.g. a LocalHandler). You will have to make it static. Override a handleMessage method, it will receive messages from the thread.

Thread构造函数添加Handler参数.在服务中实例化LocalHandler类,然后通过构造函数将其注入到线程中.

Add a Handler argument to your Thread constructor. Instantiate your LocalHandler class in a service and inject it to your thread via constructor.

将对Handler的引用保存在线程内部,并在适当的时候使用它来发送消息.

Save reference to the Handler inside of your thread and use it to send messages whenever appropriate.

这是完整的示例:

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

我希望这是一个有效的实现.如果您现在采用的是更好的方法-请让我知道.

I hope it's a valid implementation. If you now a better approach - please let me know.

这篇关于Android:如何从工作线程与服务进行通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆