Зачем использовать обработчики, а runOnUiThread делает то же самое?
Я сталкивался как с обработчиками, так и с понятиями runOnUiThread. Но мне все еще кажется сомнением, по каким фактам они точно отличаются.
Они оба предназначены для выполнения действий пользовательского интерфейса из фонового потока. Но каковы факторы, которые следует учитывать, пока мы выбираем один из двух методов.
Например, рассмотрим Runnable
Thread
который выполняет веб-сервис в фоновом режиме, и теперь я хочу обновить пользовательский интерфейс.
Как лучше всего обновить мой пользовательский интерфейс? Должен ли я пойти на Handler
или же runOnUiThread
?
Я до сих пор знаю, что мог бы использовать AsyncTask
и использовать onPostExecute
, Но я просто хочу знать разницу.
5 ответов
Activity.runOnUiThread() является частным случаем более универсальных обработчиков. С Handler
Вы можете создать свой собственный запрос события в вашей собственной теме. С помощью Handlers
создание экземпляра с конструктором по умолчанию не означает, что "код будет выполняться в потоке пользовательского интерфейса" в целом. По умолчанию обработчики привязаны к Thread
из которого они были созданы.
Создавать Handler
это гарантированно привязать к пользовательскому (основному) потоку, который вы должны создать Handler
Объект привязан к Main Looper следующим образом:
Handler mHandler = new Handler(Looper.getMainLooper());
Более того, если вы проверите реализацию runOnuiThread()
метод, он использует Handler
делать вещи:
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
Как вы можете видеть из фрагмента кода выше, Runnable action
будет выполнен немедленно, если runOnUiThread()
вызывается из потока пользовательского интерфейса. В противном случае он отправит его на Handler
, который будет выполнен в какой-то момент позже.
Обработчики были старым способом (уровень API 1) делать вещи, а затем AsycTask
(API уровня 3), наряду с уделением большего внимания использованию runOnUIThread
(Уровень API 1). Вам следует избегать максимально возможного использования обработчиков и предпочитать другие два в зависимости от ваших потребностей.
После ответа HitOdessit.
Вы можете создать такой класс.
public class Global{
private static Handler mHandler = new Handler(Looper.getMainLooper());
public static void runOnUiThread(Runnable action){
mHandler.post(action);
}
}
А потом назови это так.
Global.runOnUiThread(new Runnable(){
//Your code
});
И это может быть запущено из любого места (где у вас есть доступ к вашему классу Global).
Как лучше всего обновить мой пользовательский интерфейс? Должен ли я пойти на Handler или runOnUiThread?
Если твой Runnable
необходимо обновить интерфейс, опубликовать его на runOnUiThread
,
Но это не всегда возможно опубликовать Runnable
на тему пользовательского интерфейса.
Подумайте о сценарии, где вам нужно выполнить операцию Network/IO или вызвать веб-сервис. В этом случае вы не можете оставлять сообщения Runnable
в UI Thread. Это бросит android.os.NetworkOnMainThreadException
Эти типа Runnable
должен работать в другом потоке, как HandlerThread. После завершения операции вы можете опубликовать результат обратно в поток пользовательского интерфейса, используя Handler
, который был связан с UI Thread.
public void onClick(View view) {
// onClick on some UI control, perform Network or IO operation
/* Create HandlerThread to run Network or IO operations */
HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
/* Create a Handler for HandlerThread to post Runnable object */
Handler requestHandler = new Handler(handlerThread.getLooper());
/* Create one Handler on UI Thread to process message posted by different thread */
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Runnable on HandlerThread is completed and got result:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
NetworkRunnable r1 = new NetworkRunnable("http://www.google.com/",responseHandler);
NetworkRunnable r2 = new NetworkRunnable("http://in.rediff.com/",responseHandler);
requestHandler.post(r1);
requestHandler.post(r2);
}
class NetworkRunnable implements Runnable{
String url;
Handler uiHandler;
public NetworkRunnable(String url,Handler uiHandler){
this.url = url;
this.uiHandler=uiHandler;
}
public void run(){
try {
Log.d("Runnable", "Before IO call");
URL page = new URL(url);
StringBuffer text = new StringBuffer();
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
BufferedReader buff = new BufferedReader(in);
String line;
while ((line = buff.readLine()) != null) {
text.append(line + "\n");
}
Log.d("Runnable", "After IO call:"+ text.toString());
Message msg = new Message();
msg.obj = text.toString();
/* Send result back to UI Thread Handler */
uiHandler.sendMessage(msg);
} catch (Exception err) {
err.printStackTrace();
}
}
}
У обработчика много работы, такой как передача сообщений и частое обновление пользовательского интерфейса, если вы запускаете поток для любого запускающего задачу. Обработчик позволяет отправлять и обрабатывать объекты Message и Runnable, связанные с MessageQueue потока, что очень полезно во многих приложениях, таких как Bluetooth chat, wifi chat... и у обработчика есть методы PostDelay и PostAtTime, с помощью которых вы можете поиграть с любым видом, чтобы оживить и изменить видимость и так далее.
Вы должны посмотреть в этом
http://developer.android.com/guide/components/processes-and-threads.html
http://developer.android.com/tools/testing/activity_testing.html