2011-03-08 133 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,所以可能需要检查以及:)