2011-03-08 117 views
7

哪一種更好的方式來使用處理程序。任何優點。我遇到的所有例子似乎都給出了內聯版本。使用處理程序Android

在類中使用執行器Handler.Callback並實現接口方法。

使用內嵌代碼版本

private Handler mHandler = new Handler(){ ....}; 

回答

5

常見的術語或這些內嵌類定義爲匿名類。

你可以閱讀更多關於這些的討論Java/Android: anonymous local classes vs named classes

本質上的主要區別是readbility,編碼的速度,再利用和範圍。

從資源的角度來看,匿名類的創建可能會導致垃圾回收器的開銷,如Avoid Creating Unnecessary Objects中所討論的。我不確定匿名類創建的確切細節,但是,在類上實現接口更高效是合乎邏輯的。

@WilliamTMallard提供了一個不是要做的例子。在他的例子中,應該在類上實現一個長而複雜的句法複雜的處理程序,而不是匿名處理程序,因爲在內聯定義時難以閱讀和編輯。

0

這個真沒有回答上述問題,因爲我不知道什麼是「最好的辦法」是,它可能取決於你在做什麼。但是,我會解釋我在做什麼以及爲什麼。

我正在寫一個作爲遙控器的應用程序。有幾種活動會與受控設備進行交互,並根據命令的結果和活動的結果發生不同的事情。我不喜歡關於處理程序的兩件事:A)他們最終成爲一種「廚房水槽」構造,實現來自不同來源的功能,並且B)他們分離了一個動作(在我的情況下是發送命令)從處理該行爲的結果。然而,使用一個匿名(正確的術語?我是一個noob。)處理程序作爲參數允許我將邏輯保持在一起。下面是我的方法的僞代碼:

command = "Wake up!"; 

    mDeviceInterface.write(command, new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      switch(msg.what) { 
      case DeviceInterface.MESSAGE_TIMEOUT: // Process the timeout. 
       announce("Device not responding."); 
       break; 
      case DeviceInterface.MESSAGE_READ: // Process the response. 
       byte[] readBuf = (byte[]) msg.obj; 
       if (readBuf[0] == 0x05) { 
        // Success, update device status. 
       } else { 
        announce("Error!"); 
        break; 
       } 
      } 
     } 
    }); 

(一定要記住,這可能是值得你付出什麼吧;))

2

http://developer.android.com/reference/android/os/Handler.html

package : android.os 
public class 
Handler 
extends Object 

一個處理程序,您可以發送和處理信息,並與一個線程的MessageQueue關聯Runnable對象。每個Handler實例都與單個線程和該線程的消息隊列相關聯。當您創建一個新的處理程序時,它將綁定到正在創建它的線程的線程/消息隊列 - 此後,它將消息和可運行消息傳遞到該消息隊列,並在消息出來時執行它們隊列。

有一個處理程序兩種主要用途:作爲在將來的某一時刻 要執行

  1. 調度消息和可運行;和
  2. 排隊要在您自己的不同線程上執行的操作。

〔實施例1所

使用處理器在應用初始頁面。

if (!isFirstIn) { 
    mHandler.sendEmptyMessageDelayed(GO_HOME, SPLASH_DELAY_MILLIS); 
} else { 
    mHandler.sendEmptyMessageDelayed(GO_GUIDE, SPLASH_DELAY_MILLIS); 
} 


/************************************************************************************** 
*1. Handler 
*/ 
private Handler mHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     if(isAuto){ 
      switch (msg.what) { 
      case GO_HOME: 
       goHome(); 
       break; 
      case GO_GUIDE: 
       goGuide(); 
       break; 
      } 
     } 
     super.handleMessage(msg); 
    } 
}; 
private void goHome() { 
    Intent intent = new Intent(SplashActivity.this, MainAct.class); 
    SplashActivity.this.startActivity(intent); 
    SplashActivity.this.finish(); 
} 

private void goGuide() { 
    Intent intent = new Intent(SplashActivity.this, GuideActivity.class); 
    SplashActivity.this.startActivity(intent); 
    SplashActivity.this.finish(); 
} 

實施例2

在子線程使用處理程序請求網絡,如果請求的工作可能需要時間。

new Thread(new Runnable(){ 
    @Override 
    public void run() { 
     String versionPath = Parameters.getCheckVersionPath(); 
     String result = RequestHelper.doGet(versionPath, null); 
     Message msg = new Message(); 
     Bundle data = new Bundle(); 
     data.putString("result",result); 
     msg.setData(data); 
     handler1.sendMessage(msg); 
    } 
}).start(); 

handler1 = new Handler(){ 
    @Override 
    public void handleMessage(Message msg) { 
     String result = msg.getData().getString("result"); 
     JSONObject obj; 
     try { 
      obj = new JSONObject(result); 
      Map<String, String> versionInfo = Helper.getSoftwareVersion(obj); 
      if (versionInfo != null) { 
       newVersion = versionInfo.get("version"); 
       updateUrl = versionInfo.get("url"); 
      } 
     } catch (JSONException e) { 
      Log.w("net work error!", e); 
     } 
    } 

}; 

實施例3

使用處理程序和定時器更新進度條。

logobar = (ImageView) findViewById(R.id.splash_bar);//progress bar. 
logobarClipe = (ClipDrawable) logobar.getBackground(); 

timer = new Timer(); 
timer.schedule(new TimerTask() { 
    public void run() { 
     updateLogoBarHandler.sendEmptyMessage(0); 
}}, 0, rate); 


/************************************************************************************** 
*2. Handler 
*/ 
//update progress bar. 
private Handler updateLogoBarHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     if(logobarClipe.getLevel() < 10000){ 
      //1.update image. 
      logobarClipe.setLevel(logobarClipe.getLevel() + rate*2); 

      //2.update text. 
      float percent = logobarClipe.getLevel() /100; 
      String percentTxtVerbose = String.valueOf(percent); 
      String percentTxt = percentTxtVerbose.substring(0, percentTxtVerbose.indexOf('.')) + "%"; 
      bartxt.setText(percentTxt); 

     }else{ 
      timer.cancel(); 
     } 
     super.handleMessage(msg); 
    } 
}; 
0

在Android中使用匿名類存在危險。如在this blog post描述 -

在Java中,非靜態內部和匿名類保持一個隱含 參考它們的外部類。

這裏有一個泄漏的機會。

所以,簡短的答案是:實現接口方法或使用靜態內部類(不包含外部類引用)。

例如,泄漏的安全處理程序可能看起來像這樣:

private static class ChangeTextHandler extends Handler { 
    private final WeakReference activity; 

    public ChangeTextHandler(MainActivity activity) { 
     this.activity = new WeakReference<>(activity); 
    } 

    @Override 
    public void handleMessage(Message msg) { 
     MainActivity activity = this.activity.get(); 
     if (activity == null) { 
      Log.e(TAG, "Activity is null ChangeTextHandler.handleMessage()!"); 
      return; 
     } 

     final String text = (String) msg.getData().get(BUNDLE_KEY); 
     if (!TextUtils.isEmpty(text)) { 
      switch (msg.what) { 
       // do something 
      } 
     } 
    } 
} 

我做了一個blog post around usage of Handlers,所以可能需要檢查以及:)