哪一種更好的方式來使用處理程序。任何優點。我遇到的所有例子似乎都給出了內聯版本。使用處理程序Android
在類中使用執行器Handler.Callback
並實現接口方法。
或
使用內嵌代碼版本
private Handler mHandler = new Handler(){ ....};
哪一種更好的方式來使用處理程序。任何優點。我遇到的所有例子似乎都給出了內聯版本。使用處理程序Android
在類中使用執行器Handler.Callback
並實現接口方法。
或
使用內嵌代碼版本
private Handler mHandler = new Handler(){ ....};
常見的術語或這些內嵌類定義爲匿名類。
你可以閱讀更多關於這些的討論Java/Android: anonymous local classes vs named classes
本質上的主要區別是readbility,編碼的速度,再利用和範圍。
從資源的角度來看,匿名類的創建可能會導致垃圾回收器的開銷,如Avoid Creating Unnecessary Objects中所討論的。我不確定匿名類創建的確切細節,但是,在類上實現接口更高效是合乎邏輯的。
@WilliamTMallard提供了一個不是要做的例子。在他的例子中,應該在類上實現一個長而複雜的句法複雜的處理程序,而不是匿名處理程序,因爲在內聯定義時難以閱讀和編輯。
這個真沒有回答上述問題,因爲我不知道什麼是「最好的辦法」是,它可能取決於你在做什麼。但是,我會解釋我在做什麼以及爲什麼。
我正在寫一個作爲遙控器的應用程序。有幾種活動會與受控設備進行交互,並根據命令的結果和活動的結果發生不同的事情。我不喜歡關於處理程序的兩件事: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;
}
}
}
});
(一定要記住,這可能是值得你付出什麼吧;))
http://developer.android.com/reference/android/os/Handler.html
package : android.os
public class
Handler
extends Object
一個處理程序,您可以發送和處理信息,並與一個線程的MessageQueue關聯Runnable對象。每個Handler實例都與單個線程和該線程的消息隊列相關聯。當您創建一個新的處理程序時,它將綁定到正在創建它的線程的線程/消息隊列 - 此後,它將消息和可運行消息傳遞到該消息隊列,並在消息出來時執行它們隊列。
有一個處理程序兩種主要用途:作爲在將來的某一時刻 要執行
〔實施例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);
}
};
在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,所以可能需要檢查以及:)