android - 工作线程与主线程通信

标签 android multithreading handler

我正在开发 Android 应用程序。

此应用程序将有一个服务器来启动一个 DatagramSocket 作为服务器。它将等待传入的消息。当套接字收到消息时,我将处理它。

要启动 UDP 服务器套接字,我将使用本地服务。此服务将有一个工作线程,我将在其中收听传入的消息。

这是我的未完成本地服务实现:

public class UDPSocketBackgroundService extends Service
{
    private static final String TAG = "UDPSocketBackgroundService";
    private ThreadGroup myThreads = new ThreadGroup("UDPSocketServiceWorker");
    private Handler mServiceHandler;

    @Override
    public void onCreate()
    {
        super.onCreate();
        Log.v(TAG, "in onCreate()");
    }

    @Override
    public IBinder onBind(Intent arg0)
    {
        try
        {
            new Thread(myThreads, new UDPServerThread("X", 8888)).start();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

这也是我未完成的工作线程实现:

public class UDPServerThread extends Thread
{
    private static final int MESSAGE_SIZE = 256;

    protected DatagramSocket socket = null;
    protected boolean end = false;

    public UDPServerThread(String serverName, int port) throws IOException
    {
        super(serverName);
        socket = new DatagramSocket(port);
    }

    public void run()
    {
        while (!end)
        {
            try
            {
                byte[] buf = new byte[MESSAGE_SIZE];

                // Wait an incoming message.
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
                // TODO: Notify Service with packet received
            }
            catch (IOException e)
            {
                // TODO Mensaje de error.
                e.printStackTrace();
            }
        }
    }
}

这些类有自己的文件(它们在不同的文件中)。

这里:

socket.receive(packet);
//TODO: Notify Service with packet received

如何通知服务我们已经收到数据包?我也想将该数据包发送给服务。

Here有一个关于如何从主线程到工作线程进行通信的示例。但是,我不需要那个,我正在寻找一个关于如何从工作线程到服务进行通信的示例。

我找到了这个 example ,但我不是很理解,因为在那个例子中,两个类都在同一个文件中声明了它。

如您所见,我是 Android 开发的新手。

如果你知道更好的方法,请告诉我。

最佳答案

当您创建 UDPServerThread 时,您可以传入对 UDPSocketBackgroundService 的引用,然后在收到数据包时调用它的方法(例如 processPacket())。此 processPacket() 方法将需要使用某种同步。

下面是相关函数的一小段代码摘录:

public class UDPSocketBackgroundService extends Service
{
    ....
    @Override
    public IBinder onBind(Intent arg0)
    {
        try
        {
            new Thread(myThreads, new UDPServerThread(this, "X", 8888)).start();
            // Notice we're passing in a ref to this  ^^^
        }
        ...
    }
    public void processPacket(DatagramPacket packet)
    {
        // Do what you need to do here, with proper synchronization
    }
}

public class UDPServerThread extends Thread
{
    private static final int MESSAGE_SIZE = 256;

    protected DatagramSocket socket = null;
    protected boolean end = false;
    protected UDPSocketBackgroundService = null;

    public UDPServerThread(UDPSocketBackgroundService service, String serverName, int port) throws IOException
    {
        super(serverName);
        this.service = service;
        socket = new DatagramSocket(port);
    }

    ...

    public void run()
    {
        while (!end)
        {
            try
            {
                byte[] buf = new byte[MESSAGE_SIZE];

                // Wait an incoming message.
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
                service.processPacket(packet);
            }
            ...
        }
        ...
    }
}

请注意,采用这种方法时,UDPSocketBackgroundService 现在与 UDPServerThread“紧密耦合”。一旦你开始工作,你可以考虑用更优雅的设计重构它,耦合更少,但现在这应该让你继续:)

关于android - 工作线程与主线程通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10977729/

相关文章:

将 void* 转换为 long*

android - 如何使用 Crosswalk 长按获取 URL?

android - 将字体添加到首选项屏幕标题

android - 安装在 system/priv-app 中的应用程序在没有重启的情况下无法启动(root)

java - 更改项目 libgdx 中的版本控制并使用 Application Loader 加载

java - 多线程类加载可能吗?

c# - 缓存是否需要同步?

exception - exceptionCaught错误处理回写响应导致异常和infiniteLoop调用exceptionCaught

c# - 事件处理程序与方法

android - 有没有办法从 firebaseauth 获取名字和姓氏?