58

我遇到过HandlersrunOnUiThread概念。但对我来说,他们在哪些事实上完全不同似乎仍然是一个疑问。

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

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

更新我的 UI 的最佳方式是什么?我应该去Handler还是runOnUiThread

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

4

5 回答 5

84

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

要创建一个Handler保证绑定到 UI(主)线程的对象,您应该创建一个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();
        }
    }

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

于 2012-09-27T09:25:08.270 回答
1

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

于 2012-09-27T09:23:15.917 回答
1

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

你必须看看这个

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

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

于 2012-09-27T09:30:10.250 回答
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 类)。

于 2017-01-03T15:18:19.593 回答
1

更新我的 UI 的最佳方式是什么?我应该选择 Handler 还是 runOnUiThread?

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

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

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

这些类型的Runnable应该在不同的线程上运行,比如HandlerThread。完成操作后,您可以使用Handler已与 UI Thread 关联的 将结果发送回 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();
        }
    }
}
于 2017-09-05T13:47:25.093 回答