Android post方法到底做什么?
我遇到了一个非常奇怪的特征 当我试图在主线程上运行动画时,它不会启动。 当我运行说的动画使用Android post方法到底做什么?,android,Android,我遇到了一个非常奇怪的特征 当我试图在主线程上运行动画时,它不会启动。 当我运行说的动画使用 getView().post(new Runnable() { @Override public void run() { getView().startAnimation(a); } }); 它确实开始了 在开始动画之前,我已经打印了CurrentThread,并且都打印了main
getView().post(new Runnable() {
@Override
public void run() {
getView().startAnimation(a);
}
});
它确实开始了
在开始动画之前,我已经打印了CurrentThread
,并且都打印了main
显然,我在这里遗漏了一些东西,因为两者都应该在主线程上启动动画。。。
我的猜测是,当post将任务添加到队列中时,它会在一个更“正确”的时间开始,但我想更深入地了解这里发生了什么
编辑:
让我澄清一下-我的问题是,为什么在post上启动动画会导致它启动,而在主线程上启动动画却不会。寻找一个好的答案。view.post()与handler.post()基本相同。它进入主线程队列,并在其他挂起任务完成后执行。如果调用activity.runOnUiThread(),它将立即在UI线程上被调用。post:post会将Runnable添加到消息队列中 Runnable:表示可以执行的命令。通常用于在不同线程中运行代码 run():开始执行类代码的活动部分。当使用实现Runnable的类创建的线程启动时,将调用此方法
getView().post(new Runnable() {
@Override
public void run() {
getView().startAnimation(a);
}
});
code:getView().startAnimation(a)代码>
在代码中
post导致Runnable(代码将在不同的线程中运行)添加消息队列
因此,从messageQueue获取startAnimation时,它将在新线程中激发
[编辑1]
为什么我们要使用新线程而不是UI线程(主线程)?
UI线程:
- 当应用程序启动时,Ui线程将自动创建
- 它负责将事件分派到适当的小部件
这包括绘图事件
- 它也是您与Android小部件交互的线程
例如,如果您触摸屏幕上的a按钮,UI线程
将触摸事件发送到小部件,小部件依次设置其
按下状态并向事件队列发出无效请求。这个
UI线程对请求进行排队,并通知小部件重新绘制
本身
如果用户按下一个按钮将执行长时间操作,会发生什么情况
((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();
}
它打破了android的规则,从不直接从工作线程更新UI
Android提供了几种从其他线程访问UI线程的方法。
- Activity.runOnUiThread(可运行)
- View.post(可运行)
- View.postDelayed(可运行,长)
- 处理者
如下图所示
查看.post(可运行)
处理程序
final Handler myHandler = new Handler(Looper.getMainLooper());
(new Thread(new Runnable() {
@Override
public void run() {
final Bitmap b = loadImageFromNetwork();
myHandler.post(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(b);
}
});
}
})).start();
}
更多信息
这是在onCreate还是onCreateView上完成的?如果是这样,应用程序可能不会处于视图附加到窗口的状态。许多基于视图度量的算法可能不起作用,因为视图的度量和位置之类的东西可能还没有计算出来。Android动画通常要求它们运行UI数学
View.post实际上将动画在视图的消息循环中排队,因此一旦视图连接到窗口,它就会执行动画,而不是手动执行
实际上,您正在UI线程上运行一些东西,但在另一个时间,我认为问题可能是生命周期方法,您正在调用post()方法。您是在onCreate()中执行此操作的吗?如果是,请查看我在活动的onResume()文档中找到的内容:
onResume()
在API级别1中添加了void onResume(),之后调用
用于您的应用程序的onRestoreInstanceState(Bundle)、onRestart()或onPause()
开始与用户交互的活动这是一个好去处
开始动画,打开专用访问设备(如
(照相机)等
因此,正如Joe Plante所说,在调用post()时,视图可能还没有准备好启动动画,所以请尝试将其移动到onResume()
PD:事实上,如果你将代码移动到onResume(),那么我认为你可以删除post()调用,因为你已经在ui线程中,视图应该可以开始动画了。我发现一个巨大的(非常有用的)区别是视图中的runnable。当视图第一次显示时,将调用post()。也就是说,您可以将其设置为在视图膨胀时启动动画,然后在将来的某个时间点,最后将其添加到视图层次中。在这一点上,动画将执行,您不必担心它。实际上,handler.post()并不总是在主线程上发布消息/runnable。这取决于处理程序的创建方式(它可以与不同线程上的循环器相关联)。另一方面,view.post()总是在主线程上运行,那么为什么在post上启动动画与在主线程上运行动画不同呢,当它们最终都在同一个线程上运行时?因为这种单线程模型在Android应用程序中会产生较差的性能。较差的性能与不显示动画有什么关系?我认为这并不能回答问题,这更像是对初学者的一般回答,他们对ui线程和多线程一无所知。这并不能解释为什么在队列中向前抛出动画会使动画工作;动画应该是直接在ui线程中执行的,而不使用任何post()或RUNNUITHREAD()技巧。所有ui工作都应该在主线程(ui线程)上进行。使用post()而不是立即在主线程中调用使动画工作的技巧是时间:如果您立即在主线程中调用
final Handler myHandler = new Handler(Looper.getMainLooper());
(new Thread(new Runnable() {
@Override
public void run() {
final Bitmap b = loadImageFromNetwork();
myHandler.post(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(b);
}
});
}
})).start();
}