本文介绍了Android将数据从主UI线程发送到另一个线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将一些数据从主线程发送到另一个线程。我已经阅读了很多关于线程,asynctasks和处理程序的资料,但也许他们给我带来了一些困惑。我读到我需要为我的'第二个线程创建一个Handler,以便我可以从主线程向它发送消息(现在我不担心将任何内容发送回主线程)。

I need to send some data from the main thread to another thread. I've already read a lot of materials on threads, asynctasks and handlers but maybe they created some confusion to me. I read that I need to create a Handler to my 'second thread' so that I can send messages from the main thread to it (for now I'm not worrying about send back anything to the main thread).

我需要第二个线程连接到服务器(通过套接字)并在某些用户事件上发送一些日期。我试图以有效的方式(不要打开/关闭不必要的套接字连接)。所以我想知道我应该在哪里打开socket命令?另外,在我的处理程序的handleMessage()方法中,我需要一个对套接字输出流的引用,以便将数据发送到服务器。

I need the second thread to connect to a server (via socket) and send some date on some user events. I'm trying to do it in an efficiently manner (do not open/close unnecessary socket connections). So I'm wondering where should I put my open socket command? Also, in my handler's handleMessage() method I need a reference to the socket output stream in order to send data to server.

我目前有以下代码:

protected void initThread(){
    this.thread = new HandlerThread(WorkerHandler.class.getCanonicalName()){

        @Override
        public void run() {
            super.run();
            try{
                handler = new WorkerHandler(getLooper());
            }catch(Exception e){
                e.printStackTrace();
            }
        }

    };
    this.thread.start();
}

在我的活动的onCreate()方法中调用initThread()方法。

The method initThread() is called in the onCreate() method of my activity.

以下是我的自定义处理程序类的代码:

Here follows the code of my custom handler class:

public class WorkerHandler extends Handler {

protected Socket socket;
protected BufferedWriter writer;

public WorkerHandler(Looper looper) throws Exception{
    super(looper);
    this.socket = new Socket("192.168.1.7", 5069);
    this.writer = new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream(), "utf-8"));

}

public BufferedWriter getWriter(){
    return this.writer;
}

public Socket getSocket(){
    return this.socket;
}

@Override
public void handleMessage(Message msg) {
    Draw draw = (Draw) msg.obj;
    if (draw != null){
        if (getWriter() != null){
            try{
                getWriter().write(DrawUtil.toJson(draw)+"\n");
                getWriter().flush();
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

}

再次,在我的活动中,我触发sendDataToServer()方法

And again, in my activity, I trigger the sendDataToServer() method

protected void sendDataToServer(){
    Draw draw = new Draw(getFlowType(), getID(), getSeq(), Calendar.getInstance(), startX, startY, endX, endY);
    if (getWorkerHandler() != null){
        Message msg = getWorkerHandler().obtainMessage();
        msg.obj = draw;
        getWorkerHandler().sendMessage(msg);
    }
}

但我对WorkerHandler对象的引用始终为null。我很确定我误解了一些概念......你能不能给我一些提示?

But my reference to the WorkerHandler object is always null. I'm pretty sure I misunderstood some concept... Could you please give me some hints?

非常感谢!

推荐答案

你不能这样做。您已使用 HandlerThread 创建了第二个Thread。 HandlerThread 线程,其 Looper 。这就是 HandlerThread run()方法中发生的情况。它正在运行looper循环。这意味着 HandlerThread 中的 run()方法仅在 Looper 退出。

You can't do it this way. You've created your second Thread by using HandlerThread. A HandlerThread is a Thread that has a Looper. So that is what is going on in the run() method of HandlerThread. It is running the looper loop. That means that the run() method in the HandlerThread will only complete when the Looper exits.

在您写的 initThread()方法中:

    @Override
    public void run() {
        super.run(); // <-- This call runs the Looper loop and doesn't complete!!
        try{
            handler = new WorkerHandler(getLooper());
        }catch(Exception e){
            e.printStackTrace();
        }
    }

你可以看到被覆盖的 run()方法首先调用 super.run()。这将运行looper循环并且不会完成。因此, initThread()中的其余代码永远不会执行。

You can see that your overridden run() method first calls super.run(). This runs the looper loop and doesn't complete. So the rest of your code in initThread() never executes.

如果你想使用 HandlerThread()然后你不能搞乱它的 run()方法。如果你想让它为你做的东西,你需要发布消息(或 Runnable s),并在那里做你的工作。这是一个例子:

If you want to use a HandlerThread() then you can't mess with its run() method. If you want it to do stuff for you then you'll need to post messages (or Runnables) to it, and do your work there. Here's an example:

    HandlerThread handlerThread = new HandlerThread("myHandlerThread");
    handlerThread.start();
    // Now get the Looper from the HandlerThread so that we can create a Handler that is attached to
    // the HandlerThread
    // NOTE: This call will block until the HandlerThread gets control and initializes its Looper
    Looper looper = handlerThread.getLooper();
    // Create a handler attached to the background message processing thread
    handler = new Handler(looper, this);

现在你可以发帖子和 Runnable s到处理程序。在此示例中,消息将由创建类的重写 handleMessage()方法处理。

Now you can post messages and Runnables to the "handler". In this example, the messages will be processed by an overridden handleMessage() method of the creating class.

编辑:提供Handler回调的代码示例

您可以使用 WorkerHandler 类来如果你这样修改它就处理回调(我已将名称更改为 Worker ,因为它实际上不是 Handler ,它只是实现 Handler.Callback 接口):

You can use your WorkerHandler class to handle the callbacks if you modify it like this (I've changed the name to Worker because it isn't really a Handler, it just implements the Handler.Callback interface):

public class Worker implements Handler.Callback {

    protected Socket socket;
    protected BufferedWriter writer;

    public Worker() throws Exception{
        this.socket = new Socket("192.168.1.7", 5069);
        this.writer = new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream(), "utf-8"));
    }

    public BufferedWriter getWriter(){
        return this.writer;
    }

    public Socket getSocket(){
        return this.socket;
    }

    @Override
    public void handleMessage(Message msg) {
        Draw draw = (Draw) msg.obj;
        if (draw != null){
            if (getWriter() != null){
                try{
                    getWriter().write(DrawUtil.toJson(draw)+"\n");
                    getWriter().flush();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}

现在您需要创建此 Worker 类的实例,并在创建 Handler 。在你的活动中:

Now you need to create an instance of this Worker class and pass it as the callback argument when you create the Handler. In your activity do:

    HandlerThread handlerThread = new HandlerThread("myHandlerThread");
    handlerThread.start();
    Looper looper = handlerThread.getLooper();
    // Create an instance of the class that will handle the messages that are posted
    //  to the Handler
    Worker worker = new Worker();
    // Create a Handler and give it the worker instance to handle the messages
    handler = new Handler(looper, worker);

这篇关于Android将数据从主UI线程发送到另一个线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 18:45