我对这个感到非常困惑。我正在接受this Coursera course,并致力于Assignment 5。我能够以最小的困难完成任务,然后继续尝试使代码完成我自己的目的。我也对它进行了一些调整,但我遇到了一个重大问题,我无法理解这一点。处理程序似乎根本不接受消息......任何想法我做错了什么?
这是我的一些代码。如果还有其他您想看的东西,请告诉我。
处理程序:
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
它创建了两个DownloadHandler,因为另一个是我的单元测试中的另一个单元测试。
答案 0 :(得分:4)
引用the documentation for Handler
:
Handler允许您发送和处理与线程的MessageQueue关联的Message和Runnable对象。每个Handler实例都与一个线程和该线程的消息队列相关联。当您创建一个新的Handler时,它被绑定到正在创建它的线程的线程/消息队列 - 从那时起,它将消息和runnables传递给该消息队列并在消息出来时执行它们队列。
引用您正在使用的the documentation for the zero-argument Handler
constructor:
默认构造函数将此处理程序与当前线程的Looper相关联。如果此线程没有looper,则此处理程序无法接收消息,因此会抛出异常。
如果你没有崩溃,并且你没有创建自己的HandlerThread
(或等效的),那么你的DownloadHandler
可能会将自己绑定到主应用程序线程。发送给DownloadHandler
的邮件只有在主应用程序线程处理完邮件队列中的所有其他邮件后才会传递给handleMessage()
方法。而且,只要您使用主应用程序线程(例如,执行onCreate()
的{{1}}),该消息就不会出现(并且您的UI将被冻结以启动)。
答案 1 :(得分: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池集,以便在服务完成后对数据进行后处理。
答案 2 :(得分:1)
尝试在活动的onCreate()上测试你的处理程序。
如下所示:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DownloadHandler dh = new DownloadHandler(getMainLooper());
dh.sendEmptyMessage(0);
}