学会以事件为中心思考是关键。你能够做到 :)
第一条规则是:永远不要阻塞UI线程。UI线程负责保持应用程序的响应性,任何在此处执行的工作都不应该阻塞;尽快完成需要做的事情并返回。绝对避免在UI线程上进行I/O操作。(由于生命周期要求,有些地方你可能无法避免,例如在onPause中保存应用程序状态)。如果您在UI线程上调用Thread.sleep,就是错误的。
Android通过“应用程序无响应”(或“ANR”)错误来强制执行这一点,用户会看到这个错误。每当您在Android应用程序中看到这个错误时,它意味着开发人员做了某些导致UI线程停顿太久的事情。如果设备因某种原因而非常拥挤,这个错误可能实际上不是应用程序开发人员的错,但通常情况下,它意味着应用程序做错了什么。
您可以利用此模型来发布您自己的事件。这为您提供了一种简单的方法来告诉您的应用程序,“稍后处理”。在Android中,发布您自己的事件的关键在于
Handler
类。方法
postDelayed
允许您安排一个在某些毫秒后执行的
Runnable
。
如果您有一个看起来像这样的Activity:
public class MyActivity extends Activity {
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler.postDelayed(new Runnable() {
public void run() {
doStuff();
}
}, 5000);
}
private void doStuff() {
Toast.makeText(this, "Delayed Toast!", Toast.LENGTH_SHORT).show();
}
}
在创建活动后的5秒钟内,您将在doStuff
中看到创建的toast。
如果您正在编写自定义View
,那么更容易实现。View有其自己的postDelayed
方法,会将所有内容发布到正确的Handler
中,您无需创建自己的对象。
第二条规则是:视图应仅在UI线程上进行修改。您收到并忽略的那些异常意味着出了问题,如果您忽略它们,则应用程序可能会以有趣的方式开始表现不良。如果您的应用程序在其他线程中完成大部分工作,可以直接向要修改的视图post
事件,以便修改将正确运行。
如果您从代码的那部分拥有对Activity
的引用,也可以使用Activity#runOnUIThread
,该方法恰好执行其名称所示的操作。如果在上下文中发布到单个视图没有太多意义,则可能更喜欢此方法。
至于视图更新不会出现直到您按下按钮,这是什么类型的视图?这些是绘制这些更新的自定义视图吗?如果是这样,请记得在数据更改后调用invalidate
以触发重绘。只有在视图被无效后才会重新绘制。