Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/211.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android post方法到底做什么?_Android - Fatal编程技术网

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