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");
}
}
320283 次浏览

这些都不是完全相同的,尽管它们的净效果都是相同的。

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

第三个,假设你创建并执行BackgroundTask的实例,将浪费大量时间从线程池中抓取一个线程,执行默认的无操作doInBackground(),然后最终执行post()。到目前为止,这是三种方法中效率最低的。如果你在后台线程中确实有工作要做,那么使用AsyncTask,而不仅仅是为了使用onPostExecute()

有第四种方法使用Handler

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

我喜欢进行评论中的那个,它可以在任何地方使用,不需要任何参数:

new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
Pomber的答案是可以接受的,但是我不太喜欢重复创建新对象。最好的解决方案总是那些试图减少内存占用的解决方案。是的,存在自动垃圾收集,但移动设备中的内存保护属于最佳实践的范围。 下面的代码更新服务中的TextView。< / p >
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);

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

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

Android开发者文档:

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

CommonsBlog:

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

如果你需要在碎片中使用,你应该使用

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

因为在某些情况下会有空指针异常,如分页片段

使用处理程序

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

芬兰湾的科特林版:

Handler(Looper.getMainLooper()).post {
Toast.makeText(context, "Running on UI(Main) thread.", Toast.LENGTH_LONG).show()
}
如果你正在使用Kotlin协程: 在协程作用域内添加这个:

withContext(Dispatchers.Main) {
Toast.makeText(context, "Running on UI(Main) thread.", Toast.LENGTH_LONG).show()
}