2012-08-06 142 views
8

鑑於此代碼非靜態方法:安卓:調用從靜態的Handler類

public class MainActivity extends FragmentActivity implements ActionBar.TabListener { 

public static final int MESSAGE_NOT_CONNECTED = 1; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main_layout); 
} 

// ------------------------------------------------- 
public final void setStatus(int Rid) { 
    final ActionBar actionBar = getActionBar(); 
    actionBar.setSubtitle(Rid); 
} 

// ------------------------------------------------- 
static Handler mHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
     case MESSAGE_NOT_CONNECTED: 
      setStatus(R.string.title_not_connected); 
      break; 
     } 
    } 
} 
} 

我收到編譯錯誤:無法使靜態參考非靜態方法setStatus(INT)..

這是有道理的,因爲setStatus()中的getActionBar()是一個非靜態方法。

由於警告,我使Handler類成爲靜態的:這個Handler類應該是靜態的或者可能發生泄漏。

問題:如何從靜態處理程序中正確訪問setStatus()方法?

編輯:新的處理程序代碼是答案。

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

    @Override 
    public void handleMessage(Message msg) { 
     MainActivity target = mTarget.get(); 
     If(target == null) { 
      return; 
     } 
     switch (msg.what) { 
     case MESSAGE_NOT_CONNECTED: 
      target.setStatus(R.string.title_not_connected); 
      break; 
     } 
    } 
} 
+1

http://stackoverflow.com/q/11407943/844882 – 2012-08-06 12:32:05

+0

@Alex Lockwood提供的鏈接導致另一個鏈接Romain Guy幫助我理解WeakReferences:靜態與非靜態內部類[鏈接](https://groups.google.com/forum/?fromgroups#!msg/android-developers/1aPZXZG6kWk/lIYDavGYn5UJ)。 我可以回答我自己的問題,但我無法發佈它。 – vedavis 2012-08-06 14:18:18

+0

我回答了問題(因爲您顯然無法發佈它...):P – 2012-08-06 16:38:47

回答

9

嘗試使用WeakReference,如在本article說明。

+0

這就是答案。我修改了原來的帖子。感謝張貼,亞歷克斯。 – vedavis 2012-08-06 17:11:21

+0

@Alex Lockwood這篇文章很好,但它沒有解釋如何從靜態處理程序獲取上下文。我使用Toast.makeText(getApplicationContext(),dataString,Toast.LENGTH_SHORT).show();現在Handler是靜態的,getApplicationContext()沒有意義。如果有問題,我的處理程序在服務中。 – 2013-10-02 12:33:09

+0

@DavidDoria爲'Handler'提供一個構造函數,該構造函數將'Context'作爲參數,然後持有對該「Context」的弱引用。 – 2013-10-02 13:40:04

1

由於您現在正在使用WeakReference,mTarget.get()可能會返回null。在您編輯的代碼中,在執行target.setStatus(R.string.title_not_connected)之前,您沒有檢查target是否爲null。所以如果弱引用對象已經被GC化了,這可能會拋出NullPointerException

+0

謝謝。我會記住這一點。弗農。 – vedavis 2012-10-04 15:23:53

0

在我的活動的的onDestroy方法我稱之爲:

this.myHandler.removeCallbacksAndMessages(null); 

這不擺脫的「此處理程序類應該是靜態的或泄漏可能發生」的警告,但我相信它會破壞,因此該消息停止泄漏。我的處理程序類是我的活動的內部非靜態類。我的活動有一個MyHandler myHandler的實例。

當我這樣做時,處理程序的handleMessage方法沒有被調用,我假設這意味着包含處理程序的消息包含對活動的引用被銷燬。我打開了評論,因爲我沒有使用任何泄漏測試工具對其進行測試。我在這裏複製了這個想法:http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html回答者:Cyril 2013年1月15日上午7:50