2014-06-14 260 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將被凍結以啓動)。