2014-06-14 237 views
2

我对此感到困惑。我正在使用this Coursera course,并且在Assignment 5上工作。我能够以最小的困难完成任务,然后尝试使代码达到我自己的目的。我对它做了一些调整,但是我遇到了一个重大问题,我不能在我的生活中弄清楚。处理程序似乎没有消息......任何想法我做错了什么?Android Handler不处理消息

这是我的一些代码。让我知道是否有其他你想看的东西。

处理程序:

public class DownloadHandler extends Handler { 
private WeakReference<Context> mContext; 
public DownloadHandler(Context context) { 
    super(); 
    mContext = new WeakReference<Context>(context); 
    Log.v(TAG,"Created! "+this); 
} 
    // Handle any messages that get sent to this Handler 
    @Override 
    public void handleMessage(Message msg) { 
     Log.v(TAG, "" + msg); //Never reached 
       ... 
     } 
} 

我往前走了,我已经通过发送一个简单的消息(handler.sendEmptyMessage(0);,没有成功测试了处理任何想法

Log.v(TAG,"handler="+handler); 
Log.v(TAG,"Sending test "+handler.sendEmptyMessage(0)); 

而且logcat的? :

06-14 22:47:34.700: V/DownloadAddOnProducts(7406): handler=Handler (com.kd7uiy.hamfinder.DownloadHandler) {527724dc} 
06-14 22:47:34.700: V/DownloadAddOnProducts(7406): Sending test true 

为了进一步减少这个,我有一个单元测试:

public class DownloadTester extends InstrumentationTestCase { 
    public void setUp() { 
     targetContext=getInstrumentation().getTargetContext(); 
    } 

    public void testDownloadHandler() { 
     Looper.myLooper().setMessageLogging(new LogPrinter(Log.VERBOSE,"DownloadLooper")); 
     DownloadHandler handler=new DownloadHandler(targetContext,Looper.myLooper()); 
     Log.v(TAG,"handler="+handler); 
     handler.sendEmptyMessage(0); 
     Log.v(TAG,"Send empty message"); 
    } 

而且logcat中显示:

06-14 23:03:46.068: V/DownloadHandler(8337): Created! Handler (com.kd7uiy.hamfinder.DownloadHandler) {52770be8} 
06-14 23:03:46.068: V/DownloadHandler(8337): Created! Handler (com.kd7uiy.hamfinder.DownloadHandler) {52770f60} 
06-14 23:03:46.068: V/DownloadTester(8337): handler=Handler (com.kd7uiy.hamfinder.DownloadHandler) {52770f60} 
06-14 23:03:46.068: V/DownloadTester(8337): Send empty message 

它创造了两个DownloadHandlers因为另一种是在我的单元测试集的另一个单元测试。

+0

其中是处理程序正在申报? – Ryan

+0

你是什么意思“没有成功”?你的意思是你从来没有看到'handleMessage()'的日志吗? –

+0

你在哪里,何时以及如何实例化Handler? – CommonsWare

回答

2

问题是我在非UI线程上使用了Handler。这可以完成,但需要一些工作。开展这项工作的诀窍是确保您在有问题的线索上致电Looper.loop(),因为this question也提供参考。所以这个单元测试代码的工作:

public void testDownloadHandler() { 
    Looper.myLooper().setMessageLogging(new LogPrinter(Log.VERBOSE,"DownloadLooper")); 
    DownloadHandler handler=new DownloadHandler(targetContext,Looper.myLooper()); 
    Log.v(TAG,"handler="+handler); 
    handler.sendEmptyMessage(0); 
    Log.v(TAG,"Send empty message"); 
    Log.v(TAG,"Looper="+handler.getLooper()); 
    Log.v(TAG,""+Looper.myQueue()); 
    Looper.loop(); 
} 

事实上,在我来说,我想做的事情后,我收到了文件的一些相当显著的处理,所以我不希望它在UI线程中运行。但我不想混淆Looper.loop(),并可能阻塞我的帮助程序线程(它是ThreadPoolExecutioner线程池的一部分,我不希望它挂起)。所以我决定使用Main Looper消息池来管理Handler,然后让Handler管理一个ThreadPoolExecutioner集合集合,在服务完成后对其进行后处理。

1

尝试在活动的onCreate()上测试您的处理程序。

类似以下内容:

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    DownloadHandler dh = new DownloadHandler(getMainLooper()); 
    dh.sendEmptyMessage(0); 
} 
+0

是的,这是正确的,你不必传递onCreate()mainLooper()至少因为onCreate()保证在主UI线程上运行 – Ryan

4

报价the documentation for Handler

一个处理程序允许您发送和处理消息并Runnable对象与线程的MessageQueue关联。每个Handler实例都与单个线程和该线程的消息队列相关联。当您创建一个新的处理程序时,它将绑定到正在创建它的线程的线程/消息队列 - 此后,它将消息和可运行消息传递到该消息队列,并在消息出来时执行它们队列。

默认的构造同伙这个处理器与乐句当前线程:

您正在使用引用the documentation for the zero-argument Handler constructor。如果此线程没有活套,则此处理程序将无法接收消息,因此引发异常。

如果不崩溃,你还没有创建自己的HandlerThread(或同等学历),那么你的DownloadHandler据推测自己绑在主应用程序线程。当主应用程序线程处理完其消息队列中的所有其他消息后,您发送到该DownloadHandler的消息将只传递给handleMessage()方法。而且,只要您使用主应用程序线程(例如,执行ServiceonCreate()),该消息就不会出现(并且您的UI将被冻结以启动)。