Android Handler的使用

问题描述 投票:0回答:4

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

在类中使用implements

Handler.Callback
并实现接口方法。

使用内联代码版本

private Handler mHandler = new Handler(){ ....};
android handler
4个回答
6
投票

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

您可以在Java/Android:匿名本地类与命名类

中阅读有关这些内容的更多讨论

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

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

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


5
投票

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

package : android.os
public class
Handler
extends Object

Handler 允许您发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象。每个 Handler 实例都与一个线程和该线程的消息队列相关联。当您创建一个新的处理程序时,它会绑定到创建它的线程的线程/消息队列 - 从那时起,它将向该消息队列传递消息和可运行对象,并在它们从消息中出来时执行它们排队。

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

0
投票

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

我正在编写一个用作遥控器的应用程序。 有多种活动将与受控设备交互,并且根据命令的结果及其来自的活动,需要发生不同的事情。 我不喜欢处理程序的两件事是: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;  
                }
            }
        }
    });

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


0
投票

在 Android 中使用匿名类存在危险。如此博文 -

中所述

在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
            }
        }
    }
}

我发表了一篇关于处理程序的使用的博客文章,所以可能也值得检查:)

© www.soinside.com 2019 - 2024. All rights reserved.