【问题标题】:Use of Handler Android安卓处理器的使用
【发布时间】:2016-08-22 22:15:49
【问题描述】:

使用处理程序的更好方法是什么。任何优点。我遇到的所有示例似乎都给出了内联版本。

在类中使用实现Handler.Callback并实现接口方法。

使用内联代码版本

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

【问题讨论】:

    标签: android handler


    【解决方案1】:

    常用术语或这些内联类定义是匿名类。

    你可以在Java/Android: anonymous local classes vs named classes阅读更多关于这些的讨论

    本质上,主要区别在于可读性、编码速度、重用和范围。

    从资源的角度来看,匿名类的创建可能会导致垃圾收集器的开销,如Avoid Creating Unnecessary Objects 中所述。我不确定匿名类创建的确切细节,但是,在类上实现接口更有效是合乎逻辑的。

    @WilliamTMallard 提供了一个应该做的例子。在他的示例中,应该在类上实现一个长且语法复杂的处理程序,而不是匿名处理程序,因为内联定义时更难阅读和编辑。

    【讨论】:

      【解决方案2】:

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

      package : android.os
      public class
      Handler
      extends Object
      

      处理程序允许您发送和处理与线程的 MessageQueue 关联的 Message 和 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

      如果请求工作可能需要时间,请在子线程中使用 Handler 请求网络。

      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

      使用 Handler 和 Timer 来更新进度条。

      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);
          }
      }; 
      

      【讨论】:

        【解决方案3】:

        这确实不是上述问题的答案,因为我不知道“最佳方式”是什么,这可能取决于您在做什么。不过,我会解释我在做什么以及为什么。

        我正在编写一个用作遥控器的应用程序。有几个活动将与受控设备交互,根据命令的结果和它来自的活动,需要发生不同的事情。我不喜欢处理程序的两件事是 A)它们最终成为一种“厨房水槽”结构,实现来自不同来源的功能,以及 B)它们分离了一个动作(在我的例子中是命令的发送)从处理该动作的结果。但是,使用匿名(正确的术语?我是个菜鸟。)处理程序作为参数允许我将逻辑保持在一起。这是我的方法的伪代码:

            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;  
                        }
                    }
                }
            });
        

        (永远记住,这可能完全值得您为此付出的代价。;))

        【讨论】:

          【解决方案4】:

          在 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,所以可能也值得检查一下:)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-02-02
            • 2011-10-27
            • 1970-01-01
            • 1970-01-01
            • 2011-08-02
            • 1970-01-01
            相关资源
            最近更新 更多