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

时间:2012-10-11 23:28:55

标签: android android-asynctask android-view android-ui

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

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

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

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

7 个答案:

答案 0 :(得分:273)

这些都不完全相同,尽管它们都具有相同的净效应。

第一个和第二个之间的区别在于,如果您在执行代码时碰巧 on 主应用程序线程,那么第一个(runOnUiThread())将执行{{ 1}}立即。第二个(Runnable)总是将post()放在事件队列的末尾,即使您已经在主应用程序线程上。

第三个,假设您创建并执行Runnable的实例,将浪费大量时间从线程池中获取线程,以执行默认的无操作BackgroundTask,之前最终做了相当于doInBackground()的事情。这是三者中效率最低的。如果您确实在后台线程中有工作要做,请使用post(),而不只是使用AsyncTask

答案 1 :(得分:226)

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

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

答案 2 :(得分:55)

使用Handler

的第四种方法
new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

答案 3 :(得分: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;
    }

}

它可以在任何地方使用:

textViewUpdater.setText("Hello");
        textViewUpdaterHandler.post(textViewUpdater);

答案 4 :(得分:5)

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

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

来自Android developer docs

  

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

来自CommonsBlog

  

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

答案 5 :(得分:5)

如果您需要在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");
        }
    });

而不是

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

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

答案 6 :(得分:2)

大家好,这个是我告诉的基本问题

使用处理程序

<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.0.12/howler.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="pad" id="kick"></div>