Android 为什么在 runOnUiThread 做同样的事情时使用处理程序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12618038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:13:30  来源:igfitidea点击:

Why to use Handlers while runOnUiThread does the same?

androidmultithreadingandroid-asynctaskhandler

提问by Andro Selva

I have come across both Handlersand runOnUiThreadconcepts. But to me it still seems to be a doubt as on which facts do they differ exactly.

我遇到过处理程序runOnUiThread概念。但对我来说,它们究竟在哪些事实上存在差异似乎仍然存在疑问。

They both are intended to do UI actions from a background thread. But what are the factors that are to be considered while we choose among the two methods.

它们都旨在从后台线程执行 UI 操作。但是,我们在这两种方法中进行选择时需要考虑哪些因素。

For example consider a RunnableThreadwhich performs a web service in the background and now I want to update the UI.

例如,考虑RunnableThread在后台执行 Web 服务,现在我想更新 UI。

What would be the best way to update my UI? Should I go for Handleror runOnUiThread?

更新我的用户界面的最佳方式是什么?我应该去Handler还是去runOnUiThread

I still know I could use a AsyncTaskand make use of onPostExecute. But I just want to know the difference.

我仍然知道我可以使用 aAsyncTask并使用onPostExecute. 但我只想知道区别。

回答by HitOdessit

Activity.runOnUiThread()is a special case of more generic Handlers. With Handleryou can create your own event query within your own thread. Using Handlersinstantiated with the default constructordoesn'tmean "code will run on UI thread" in general. By default, handlers are bound to the Threadfrom which they were instantiated from.

Activity.runOnUiThread()是更通用的Handlers 的一个特例。随着Handler你可以创建自己的线程中自己的事件查询。通常,使用默认构造函数Handlers实例化并不意味着“代码将在 UI 线程上运行”。默认情况下,处理程序绑定到它们被实例化的来源。Thread

To create a Handlerthat is guaranteed to bind to the UI (main) thread, you should create a Handlerobject bound to Main Looperlike this:

要创建一个Handler保证绑定到 UI(主)线程的Handler对象,您应该创建一个绑定到Main Looper的对象,如下所示:

Handler mHandler = new Handler(Looper.getMainLooper());

Moreover, if you check the implementation of the runOnUiThread()method, it is using Handlerto do the things:

此外,如果您检查该runOnUiThread()方法的实现,它正在Handler用于执行以下操作:

  public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

As you can see from code snippet above, Runnable actionwill be executed immediately if runOnUiThread()is called from the UI thread. Otherwise, it will post it to the Handler, which will be executed at some point later.

从上面的代码片段可以看出,Runnable action如果runOnUiThread()从 UI 线程调用,将立即执行。否则,它会将其发布到Handler,稍后将执行该 。

回答by Vipin Sahu

Handler have many work like message passingand frequent UI update if you start A Thread for any running a task .A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue ,, which is very useful in many application like bluetooth chat ,, wifi chat ... and handler has as Method PostDelay and PostAtTime by which you can play around any view to animate and change visibility and so on

如果您为任何正在运行的任务启动一个线程,处理程序有许多工作,例如消息传递和频繁的 UI 更新。处理程序允许您发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象,这在许多应用程序(如蓝牙)中非常有用chat ,, wifi chat ... 和 handler 有方法 PostDelay 和 PostAtTime,通过它你可以播放任何视图来设置动画和改变可见性等等

You must look in this

你必须看看这个

http://developer.android.com/guide/components/processes-and-threads.html

http://developer.android.com/guide/components/processes-and-threads.html

http://developer.android.com/tools/testing/activity_testing.html

http://developer.android.com/tools/testing/activity_testing.html

回答by Vipin Sahu

Following HitOdessit's answer.

按照 HitOdessit 的回答。

You can create a class like this.

您可以创建这样的类。

public class Global{
    private static Handler mHandler = new Handler(Looper.getMainLooper());
    public static void runOnUiThread(Runnable action){
        mHandler.post(action);
    }
}

And then call it like this.

然后这样称呼它。

Global.runOnUiThread(new Runnable(){
    //Your code
});

And this can be run from anywhere (where you have access to your Global class).

这可以从任何地方运行(您可以访问 Global 类)。

回答by Ravindra babu

What would be the best way to update my UI? Should I go for Handler or runOnUiThread?

更新我的用户界面的最佳方式是什么?我应该选择 Handler 还是 runOnUiThread?

If your Runnableneeds to update UI, post it on runOnUiThread.

如果您Runnable需要更新 UI,请将其发布到runOnUiThread.

But it's not always possible to post Runnableon UI Thread.

但是并不总是可以Runnable在 UI Thread 上发帖。

Think of scenario, where you want need to execute Network/IO operationOr invoke a web service. In this case, you can't post Runnableto UI Thread. It will throw android.os.NetworkOnMainThreadException

想一想您需要执行网络/IO 操作或调用Web 服务的场景。在这种情况下,您不能发布Runnable到 UI 线程。它会抛出android.os.NetworkOnMainThreadException

These type of Runnableshould run on different thread like HandlerThread. After completing your operation, you can post result back to UI Thread by using Handler, which has been associated with UI Thread.

这些类型Runnable应该在不同的线程上运行,比如HandlerThread。完成操作后,您可以使用Handler已与 UI 线程关联的将结果发布回UI 线程。

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

回答by Animesh

Handlers were the old way (API Level 1) of doing stuff, and then AsycTask(API Level 3) were introduced, along with a stronger focus on using runOnUIThread(API Level 1). You should avoid using handlers as much as possible, and prefer the other two depending on your need.

处理程序是旧的做事方式(API 级别 1),然后AsycTask(API 级别 3)被引入,同时更加注重使用runOnUIThread(API 级别 1)。您应该尽可能避免使用处理程序,并根据需要选择其他两个。