post方法究竟做了什么?

时间:2012-12-12 12:39:44

标签: android

我遇到了一个非常奇怪的功能。

当我尝试在主线程上运行动画时,它无法启动。 当我使用

运行所述动画时
getView().post(new Runnable() {
            @Override
            public void run() {
                getView().startAnimation(a);
            }
        });

确实开始了。

我在开始动画之前打印了CurrentThread并打印main

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

编辑: 让我清楚一点 - 我的问题是,为什么在帖子上启动动画会导致它开始,当在主线程上启动动画时不会。

4 个答案:

答案 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线程的方法。

  • Activity.runOnUiThread(可运行)
  • View.post(可运行)
  • View.postDelayed(Runnable,long)
  • 处理程序

如下所示,

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

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/

答案 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中了,视图应该可以开始制作动画。