2012-10-16 75 views
1

下面的消息處理工作從我的細膩的服務接收消息...消息處理和WeakReference的問題

private Handler handler = new Handler() 
{ 

    public void handleMessage(Message message) 
    { 
     Object path = message.obj; 

     if (message.arg1 == 5 && path != null) //5 means its a single mapleg to plot on the map 
     { 
      String myString = (String) message.obj; 
      Gson gson = new Gson(); 
      MapPlot mapleg = gson.fromJson(myString, MapPlot.class); 
      myMapView.getOverlays().add(new DirectionPathOverlay(mapleg.fromPoint, mapleg.toPoint)); 
      mc.animateTo(mapleg.toPoint); 

     } 
     else 
     { 
      if (message.arg1 == RESULT_OK && path != null) 
      { 
       Toast.makeText(PSActivity.this, "Service Started" + path.toString(), Toast.LENGTH_LONG).show(); 
      } 
      else 
      { 
       Toast.makeText(PSActivity.this,"Service error" + String.valueOf(message.arg1), Toast.LENGTH_LONG).show();   


      } 

     } 
    }; 
}; 

然而,即使它正常的測試出來的AVD(我餵養它大的KML通過DDMS文件)「對象路徑= message.obj;」行有警告說「這個Handler類應該是靜態的,否則可能會發生泄漏」。

但是,如果我說「靜態處理程序處理程序=新處理程序()」它不會編譯抱怨我「不能靜態引用非靜態字段myMapView。如果我不能這樣的引用,我

這導致我在這個問題上搜索了幾個小時,並且學習了更多關於weakReferences的知識,我發現我經常發現的建議是我應該替換...

private Handler handler = new Handler() 

static class handler extends Handler 
{ 
    private final WeakReference<PSActivity> mTarget; 
    handler(PSActivity target) 
    { 
     mTarget = new WeakReference<PSActivity>(target); 
    } 

但是這不會編譯仍然抱怨我不能靜態引用非dtatic字段。所以,我的問題一週或前一天是「我怎麼才能爲android編寫一個消息處理程序,以便我的服務可以將數據發送到我的活動中。即使我有工作代碼,問題仍然以」沒有內存泄漏「爲後綴。 謝謝,加里

回答

3

我得到了相同的警告信息時,我想在一個服務使用的處理程序,最後由來自this thread採取的建議解決它,看到的代碼片段從我的項目。

public class MyService extends Service { 
    ... 
    private MyHandler mHandler; 

    public static class MyHandler extends Handler { 
     private final WeakReference<MyService> mService; 

     MyHandler(MyService service) { 
      mService = new WeakReference<MyService>(service); 
     } 

     @Override 
     public void handleMessage(Message msg) { 
      super.handleMessage(msg); 
      MyService service = mService.get(); 
      if (service!=null) { 
       if (msg.what==MSG_RESUME_CHECKING) { 
        service.pause(); 
       } else if (msg.what==MSG_PAUSE_CHECKING) { 
        service.resume(); 
       } 
      } 
     } 
    } 
    ... 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     ... 
     mHandler = new MyHandler(this); 
     ... 
    } 
} 
+0

它看起來並不像你引用任何非靜態對象,所以你會沒事的。我正在提供這樣的參考。現在我已經使myMapview和控制器成爲靜態的,但我可能並不總是能夠做到這一點。嘗試做出這樣的參考,看看你得到什麼。 –

+0

正如我看到的message.obj是一個字符串,如果它不是太長,那麼你可以忽略警告(一個路徑的長度通常在256內,所以它消耗至多半千字節,假設你有100消息隊列中的處理程序保持50kB,可忽略)。如果您有充分的理由擔心潛在的內存泄漏,那麼當您收到消息時,您可以在第一個地方爲「obj」指定一個弱引用「msg.obj = new WeakReference (path);」,並在handleMessage在使用之前檢查它「WeakReference ref = message.obj; String str = ref.get(); if(str!= null)...」 –

0

我知道我對晚會有點遲,但希望這有助於進一步回答未來詢問者的問題。

正如你通過你的谷歌搜索(我已經做了很多自己解決類似問題的事情),你需要把你的Handler實例變成一個靜態內部類(嵌套類),它在構造函數中接受目標Activity。然後,它將此活動引用轉換爲WeakReference,這就是可以用來與目標活動中的事物進行交互的內容。你的情況:

Toast.makeText(mTarget.get().this, "Service Started" + path.toString(), Toast.LENGTH_LONG).show(); 

既然你要改變一個嵌套類,你還需要創建一個類你的線程的實例在其run()方法訪問。有關此方面的更多幫助(以及如何確保您的應用程序即使在配置更改後也能正常工作),請參閱this question

希望這會有所幫助!