Использование Handler Android - PullRequest
8 голосов
/ 08 марта 2011

Какой лучший способ использовать обработчик. Любые преимущества. Кажется, что все примеры, которые я встречал, дают встроенную версию.

Использование реализаций Handler.Callback в классе и реализация метода интерфейса.

или

Использование версии встроенного кода

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

Ответы [ 4 ]

5 голосов
/ 18 сентября 2011

Общий термин или эти определения встроенного класса - это Анонимные классы.

Подробнее об этом можно прочитать в Java / Android: анонимные локальные классы против именованных классов

По сути, основными различиями являются удобочитаемость, скорость кодирования, повторное использование и объем.

С точки зрения ресурса, создание анонимного класса может вызвать перегрузку в сборщике мусора, как обсуждалось в Избегать создания ненужных объектов . Я не уверен в точных деталях создания анонимного класса, однако логично, что реализация интерфейса в классе более эффективна.

@ WilliamTMallard предоставил пример того, что НЕ делать. В его примере длинный и синтаксически сложный обработчик должен быть реализован в классе, а не в анонимном обработчике, потому что его сложнее читать и редактировать, когда он определен в строке.

2 голосов
/ 06 ноября 2014

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

package : android.os
public class
Handler
extends Object

Обработчик позволяет отправлять и обрабатывать объекты Message и Runnable, связанные с MessageQueue потока. Каждый экземпляр обработчика связан с одним потоком и очередью сообщений этого потока. Когда вы создаете новый обработчик, он привязывается к потоку / очереди сообщений потока, который его создает - с этого момента он будет доставлять сообщения и исполняемые файлы в эту очередь сообщений и выполнять их по мере их выхода из сообщения очереди.

Существует два основных варианта использования обработчика:

  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

Используйте 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 голосов
/ 22 августа 2016

Существует опасность использования анонимных классов в 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
            }
        }
    }
}

Я написал в блоге об использовании обработчиков , поэтому может бытьстоит также проверить:)

0 голосов
/ 18 сентября 2011

Это действительно не ответ на поставленный выше вопрос, потому что я не знаю, каков «лучший способ», и это, вероятно, зависит от того, что вы делаете.Однако я объясню, что я делаю и почему.

Я пишу приложение, которое служит в качестве удаленного контроллера.Есть несколько действий, которые будут взаимодействовать с контролируемым устройством, и разные вещи должны происходить в зависимости от результата команды и действия, из которого оно получено.Две вещи, которые мне не нравятся в обработчиках: А), что они в конечном итоге являются своего рода конструкцией «кухонной раковины», реализующей функциональность из разных источников, и Б), что они отделили действие (отправка команды в моем случае)от обработки результата этого действия.Однако использование анонимного (правильный термин? Я такой нуб.) Обработчик в качестве параметра позволяет мне сохранять логику вместе.Вот псевдокод для моего подхода:

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

(Всегда помните, это, вероятно, стоит именно то, что вы заплатили за него;))

...