Post 方法到底是做什么的?

我遇到了一个非常奇怪的现象。

当我试图在主线程上运行动画时,它不会启动。 当我使用

getView().post(new Runnable() {
@Override
public void run() {
getView().startAnimation(a);
}
});

确实开始了。

在开始动画之前,我已经打印了 CurrentThread,并且都打印了 main

显然,我在这里遗漏了一些东西,因为两者都应该在主线程上启动动画..。 我的猜测是,当 post 将任务添加到队列中时,它会在一个更“正确的时间”开始,但我想知道在更深入的层次上会发生什么。

编辑: 让我澄清一些事情-我的问题是,为什么启动动画在后导致它启动,而启动动画在主线程不。

78380 次浏览

看一下 给你寻找一个好的答案。Post ()与 handler.post ()基本相同。它进入主线程队列,并在其他挂起的任务完成后执行。如果您调用 activity.runOnUiThread () ,它将立即在 UI 线程上被调用。

Post : post 导致将 Runnable 添加到消息队列,

表示可以执行的命令。通常用于在不同的线程中运行代码。

Run () : 开始执行类代码的活动部分。当使用实现 Runnable 的类创建的线程启动时调用此方法。

getView().post(new Runnable() {


@Override
public void run() {
getView().startAnimation(a);
}
});

代码 : getView().startAnimation(a);

在你的代码里,

Post 使 Runnable (密码将在不同的线程中运行)添加消息队列。

因此,当 startAnimation 从 信息队列获取时,它将在一个新线程中被激发

[编辑1]

为什么我们使用一个新的线程而不是 UI 线程(主线程) ?

用户界面:

  • 启动应用程序时,会自动创建 Ui 线程

  • 它负责将事件发送到适当的小部件 这包括绘画事件

  • 它也是与 Android 小部件交互的线程

例如,如果你触摸屏幕上的一个按钮,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 提供了几种从其他线程访问 UI 线程的方法

  • RunOnUiThread (Runnable)
  • View.post (Runnable)
  • PostDelayed (Runnable,long)
  • 管理员

比如下面,

View.post (Runnable)

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

enter image description here

了解更多信息

Http://android-developers.blogspot.com/2009/05/painless-threading.html

Http://www.aviyehuda.com/blog/2010/12/20/android-multithreading-in-a-ui-environment/

这是在 onCreate 还是在 onCreateView 上完成的?如果是这样,应用程序可能不会处于视图附加到窗口的状态。许多基于视图度量的算法可能无法工作,因为诸如视图的度量值和位置之类的东西可能还没有被计算出来。Android 动画通常要求它们运行 UI 数学

Post 实际上在 View 的消息循环中将动画排队,因此一旦视图附加到窗口,它就会执行动画,而不是手动执行。

您实际上是在 UI 线程上运行,但是在不同的时间

我认为问题可能是调用 post ()方法的生命周期方法。你是在 onCreate ()中做的吗?如果是这样,看看我在活动的 onResume ()文档中发现了什么:

OnResume ()

在 API 级别1中添加了 void onResume () 对于您的 活动开始与用户交互 开始动画 ,打开独占访问设备(如 摄影机)等。

Https://developer.android.com/reference/android/app/activity.html#onresume

因此,正如 Joe Plante 所说,可能在您调用 post ()的时候视图还没有准备好启动动画,所以尝试将其移动到 onResume ()。

PD: 实际上,如果您将代码移动到 onResume () ,那么我认为您可以删除 post ()调用,因为您已经在 ui-thread 中,并且视图应该已经准备好启动动画了。