将处理程序从后台处理程序线程传递到后台线程

时间:2013-07-17 14:18:11

标签: android multithreading handler looper

有人能指出我在正确的方向吗?

我有一个活动产生两个线程,一个用于处理消息的线程,使用一个Looper

    public static class MiddleThread extends Handler{
    static public Handler handler;

    public void run() {
        Looper.prepare();
        Log.d("MiddleThread", "Looper is prepared !");
        handler = new Handler() {

            public void handleMessage(Message msg)
            {
                Bundle bundle = msg.getData();
                String exitString = bundle.getString("endmessage");
                if(exitString.equals(("ExitOK")))
                {
                    boolean searchFinished = true;
                    Looper looper = Looper.myLooper();
                    looper.quit();
                } else
                {
                    int fileCount = bundle.getInt("filecount");
                    String fileName = bundle.getString("filename");
                    Log.d("MiddleThread", "File Number " + fileCount + " is " + fileName);
                }
            }
        };
        Log.d("MiddleThread", "nandler should be initialised");
        Looper.loop();
    }

...然后它产生主要的工作线程,它从UI线程传递一个处理程序,并从上面的线程传递处理程序。

public class BasicSearch {
public Handler handlerUi, handlerMiddleThread;
public Message messageUi, messageMiddleThread;
public int fileCount = 0;
public BasicSearch(Handler ui, Handler mt) {
    handlerUi = ui;
    handlerMiddleThread = mt;
}

public void listFiles()
{
    File searchPath = Environment.getExternalStorageDirectory();
    messageUi = handlerUi.obtainMessage();
    messageMiddleThread = handlerMiddleThread.obtainMessage();
    walk(searchPath);
    Bundle b = new Bundle();
    b.putString("endmessage", "ExitOK");
    messageMiddleThread.setData(b);
    handlerMiddleThread.dispatchMessage(messageMiddleThread);
}

private void walk(File path) {
    File[] list = path.listFiles();
    for(File f : list)
    {
        if(f.isDirectory())
        {               
            walk(new File(f.getAbsolutePath()));
        } else {
            processFile(f);
        }
    }
}

private void processFile(File f) {
    Bundle b = new Bundle();
    fileCount++;
    b.putString("filename", f.getName());
    b.putInt("filecount", fileCount);
    messageMiddleThread.setData(b);
    Log.d("BasicSearch", "Data is set, to send to MiddleThread");
    handlerMiddleThread.dispatchMessage(messageMiddleThread);
    Log.d("BasicSearch", "Message sent");

}

    }

无论发生什么,当它尝试dispatchMessage时,handlerMiddleThread都会恢复为null。我甚至在我的活动中有以下代码,尝试确保它不是null,但是当我发送消息时它仍然是null。

      startMiddleThread();
    while(true)
    {
        if(MiddleThread.handler != null)
            break;
    }   
    startSearchThread();

这是一个测试项目,因为我希望能够在继续我的项目之前正确理解Handler / Looper概念。

我之前已成功设法在我的UI线程中使用Handler,但我当前的项目在UI中进行了太多的处理,我希望有一个辅助线程处理来自searchThread的输出,并且只是接收到线程完成时,UI线程中的消息。

1 个答案:

答案 0 :(得分:2)

所以我想我知道你要做什么,让我建议一个稍微简单的方法:

启动后台线程并获取处理程序:

HandlerThread bgThread = new HandlerThread();
bgThread.start();
Handler bgHandler = new Handler(bgThread.getLooper());

然后您可以将您想要的任何消息发送给您的bgHandler。请注意,在创建bgThread之前需要在HandlerThread上调用start(否则getLooper()将返回null)。

话虽如此,我想我知道你发布它时你的代码有什么问题。首先,MiddleThread扩展了Handler(它没有run()方法!)而不是Thread。其次,从不调用MiddleThread上的run()方法,因此从不实例化Handler。即使您在上面的代码中只是错误输入Handler并且实际上正在扩展Thread,您仍然需要在MiddleThread上调用start以便执行run()中的任何操作。实际上,你正在做的事情是它需要的更复杂,你几乎肯定想要做我上面提到的。