我遇到了一个非常奇怪的功能。
当我尝试在主线程上运行动画时,它无法启动。 当我使用
运行所述动画时getView().post(new Runnable() {
@Override
public void run() {
getView().startAnimation(a);
}
});
确实开始了。
我在开始动画之前打印了CurrentThread
并打印main
。
显然,我在这里遗漏了一些东西,因为两者都应该在主线程上启动动画...... 我的猜测是,当post将任务添加到队列中时,它会在更“正确的时间”开始,但我想更深入地了解这里发生的事情。
编辑: 让我清楚一点 - 我的问题是,为什么在帖子上启动动画会导致它开始,当在主线程上启动动画时不会。
答案 0 :(得分:146)
发布:post会导致Runnable被添加到邮件队列中,
Runnable:表示可以执行的命令。通常用于在不同的线程中运行代码。
run():开始执行类代码的活动部分。当启动一个使用实现Runnable的类创建的线程时,将调用此方法。
getView().post(new Runnable() {
@Override
public void run() {
getView().startAnimation(a);
}
});
代码:getView().startAnimation(a);
在你的代码中,
post导致Runnable(代码将在不同的线程中运行)添加消息队列。
因此,当从 messageQueue
获取startAnimation时,将在新线程中触发startAnimation[编辑1]
为什么我们使用新线程而不是UI线程(主线程)?
UI线程:
启动应用程序时,会自动创建Ui线程
它负责将事件分派给适当的小部件 这包括绘图活动。
它也是您与Android小部件交互的线程
例如,如果您触摸屏幕上的a按钮,则会显示UI线程 将触摸事件调度到窗口小部件,窗口小部件又设置它 按下状态并向事件队列发布无效请求。该 UI线程将请求出列并通知窗口小部件重绘 本身。
如果用户按下将执行longOperation的按钮会怎样?
((Button)findViewById(R.id.Button1)).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
final Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
});
用户界面冻结。该计划甚至可能会崩溃。
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
}).start();
}
它破坏了永远不会直接从工作线程
更新UI的android规则Android提供了几种从其他线程访问UI线程的方法。
如下所示,
<强> View.post(可运行)强>
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(b);
}
});
}
}).start();
}
<强>处理程序强>
final Handler myHandler = new Handler();
(new Thread(new Runnable() {
@Override
public void run() {
final Bitmap b = loadImageFromNetwork();
myHandler.post(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(b);
}
});
}
})).start();
}
了解更多信息
http://android-developers.blogspot.com/2009/05/painless-threading.html
http://www.aviyehuda.com/blog/2010/12/20/android-multithreading-in-a-ui-environment/
答案 1 :(得分:22)
这是在onCreate还是onCreateView上完成的?如果是这样,应用程序可能不处于视图附加到窗口的状态。许多基于View指标的算法可能无效,因为可能尚未计算View的测量和位置等内容。 Android动画通常要求它们通过UI数学运行
View.post实际上是在View的消息循环中对动画进行排队,因此一旦视图附加到窗口,它就会执行动画而不是手动执行。
您实际上是在UI线程上运行,但是在不同的时间运行
答案 2 :(得分:17)
看看here以获得一个好的答案。 view.post()与handler.post()非常相似。它进入主线程队列并在其他待处理任务完成后执行。如果你调用activity.runOnUiThread(),它将立即在UI线程上调用。
答案 3 :(得分:3)
我认为问题可能是你调用post()方法的生命周期方法。你是在onCreate()吗?如果是这样,请查看我在活动的onResume()文档中找到的内容:
的onResume()
在API级别1中添加void onResume()之后调用 onRestoreInstanceState(Bundle),onRestart()或onPause(),用于你的 活动开始与用户交互。 这是个好地方 开始动画,打开独占访问设备(如 相机)等。
https://developer.android.com/reference/android/app/Activity.html#onResume()
因此,正如Joe Plante所说,也许视图还没有准备好在你调用post()时启动动画,所以尝试将它移动到onResume()。
PD:实际上,如果你确实将代码移动到onResume(),那么我认为你可以删除post()调用,因为你已经在ui-thread中了,视图应该可以开始制作动画。