Android基础知识:在UI线程中运行代码

Luk*_*uky 434 android android-ui android-asynctask android-view

从在UI线程中运行代码的角度来看,之间有什么区别:

MainActivity.this.runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});
Run Code Online (Sandbox Code Playgroud)

要么

MainActivity.this.myView.post(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});
Run Code Online (Sandbox Code Playgroud)

private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
    protected void onPostExecute(Bitmap result) {
        Log.d("UI thread", "I am the UI thread");
    }
}
Run Code Online (Sandbox Code Playgroud)

Com*_*are 281

这些都不是完全一样的,尽管它们都具有相同的净效应.

第一和第二之间的区别是,如果你恰巧是执行代码时,主应用程序线程,则第一个(runOnUiThread())将执行Runnable立即.第二个(post())总是将Runnable事件放在事件队列的末尾,即使您已经在主应用程序线程上.

第三个,假设您创建并执行一个实例BackgroundTask,将浪费大量时间从线程池中获取一个线程,执行默认的无操作doInBackground(),然后最终执行相当于a的操作post().这是三者中效率最低的.使用AsyncTask如果你确实有工作在后台线程做,不只是为使用onPostExecute().

  • 另请注意,`AsyncTask.execute()`要求您始终从UI线程调用,这使得此选项对于在后台线程中仅在UI线程上运行代码的用例无效,除非您将所有后台工作都移到`doInBackground()`并正确使用`AsyncTask`. (27认同)

pom*_*ber 242

我喜欢HPP评论中的那个,它可以在没有任何参数的任何地方使用:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 这有多有效?与其他选项一样吗? (2认同)

vas*_*art 58

有第四种方式使用 Handler

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 在主UI线程上执行`new Handler(Looper.getMainLooper()).post(r)`,这是首选方式,因为`Looper.getMainLooper()`对main进行静态调用,而`postOnUiThread() `必须在范围内有一个'MainActivity`实例. (105认同)
  • 你应该小心这一点.因为如果在非UI线程中创建处理程序,则会将消息发布到非UI线程.默认情况下,处理程序将消息发送到创建它的线程. (54认同)
  • `postOnUiThread()`使用`Handler`来做到这一点:) (2认同)

小智 18

Pomber的答案是可以接受的,但我并不是反复创建新对象的忠实粉丝.最好的解决方案总是那些试图减轻记忆力的解决方案.是的,有自动垃圾收集,但移动设备中的内存保护属于最佳实践范围.下面的代码更新了服务中的TextView.

TextViewUpdater textViewUpdater = new TextViewUpdater();
Handler textViewUpdaterHandler = new Handler(Looper.getMainLooper());
private class TextViewUpdater implements Runnable{
    private String txt;
    @Override
    public void run() {
        searchResultTextView.setText(txt);
    }
    public void setText(String txt){
        this.txt = txt;
    }

}
Run Code Online (Sandbox Code Playgroud)

它可以在任何地方使用:

textViewUpdater.setText("Hello");
        textViewUpdaterHandler.post(textViewUpdater);
Run Code Online (Sandbox Code Playgroud)

  • 提及GC和对象创建的+1.但是,我不一定同意"最好的解决方案始终是那些试图减轻记忆力的方法"."最佳"还有许多其他标准,这有一种"过早优化"的轻微气味.也就是说,除非你知道你正在调用它,否则创建的对象数量是一个问题(与你的应用程序可能创造垃圾的其他万种方式相比.),最好的就是编写最简单的(最容易理解的代码,并继续执行其他任务. (7认同)
  • 顺便说一句,`textViewUpdaterHandler`可以更好地命名为`uiHandler`或`mainHandler`,因为它通常对主UI空间的任何帖子都有用; 它完全没有绑定到TextViewUpdater类.我会把它从其他代码中移开,并明确表示它可以在其他地方使用......其余的代码是可疑的,因为为了避免动态创建一个对象,你可以打破一个单一的调用两个步骤`setText`和`post`,依赖于你用作临时的长寿命对象.不必要的复杂性,而不是线程安全.不容易维护. (2认同)

小智 8

使用处理程序

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});
Run Code Online (Sandbox Code Playgroud)


Dic*_*cas 7

从Android P开始,您可以使用getMainExecutor()

getMainExecutor().execute(new Runnable() {
  @Override public void run() {
    // Code will run on the main thread
  }
});
Run Code Online (Sandbox Code Playgroud)

来自Android开发人员文档

返回一个执行程序,该执行程序将在与此上下文关联的主线程上运行排队的任务。这是用于将调用分派到应用程序组件(活动,服务等)的线程。

CommonsBlog

您可以在Context上调用getMainExecutor()以获取将在主应用程序线程上执行其作业的Executor。还有其他方法可以使用Looper和自定义的Executor实现来实现,但这很简单。


Bey*_*yaz 7

如果需要在Fragment中使用,则应使用

private Context context;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context;
    }


    ((MainActivity)context).runOnUiThread(new Runnable() {
        public void run() {
            Log.d("UI thread", "I am the UI thread");
        }
    });
Run Code Online (Sandbox Code Playgroud)

代替

getActivity().runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});
Run Code Online (Sandbox Code Playgroud)

因为在某些情况下会出现空指针异常,例如寻呼机片段