我们有这样一个需求,当一个activity启动后的第一帧,也就是肉眼可见的第一帧后做一个更新界面updateText的操作,这里的第一帧有没有一个合理的时机,让我们认为activity界面可见了?onResume是否可以认为是第一帧可见?
public class MainActivity extends AppCompatActivity {
private static final int DEALY_TIME = 300 ;
private ImageView imageView1;
private ImageView imageView2;
private ImageView imageView3;
private TextView textView1;
private TextView textView2;
private TextView textView3;
private Handler myHandler = new Handler();
private Runnable mLoadingRunnable = new Runnable() {
@Override
public void run() {
updateText();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.image1);
imageView2 = (ImageView) findViewById(R.id.image2);
imageView3 = (ImageView) findViewById(R.id.image3);
textView1 = (TextView) findViewById(R.id.text1);
textView2 = (TextView) findViewById(R.id.text2);
textView3 = (TextView) findViewById(R.id.text3);
// 第一种写法:直接Post
myHandler.post(mLoadingRunnable);
// 第二种写法:直接PostDelay 300ms.
myHandler.postDelayed(mLoadingRunnable, DEALY_TIME);
// 第三种写法:优化的DelayLoad
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
myHandler.post(mLoadingRunnable);
}
});
// Dump当前的MessageQueue信息.
getMainLooper().dump(new Printer() {
@Override
public void println(String x) {
Log.i("Gracker",x);
}
},"onCreate");
}
private void updateText() {
TraceCompat.beginSection("updateText");
textView1.setText("image1 : w=" + imageView1.getWidth() +
" h =" + imageView1.getHeight());
textView2.setText("image2 : w=" + imageView2.getWidth() +
" h =" + imageView2.getHeight());
textView3.setText("image3 : w=" + imageView3.getWidth() +
" h =" + imageView3.getHeight());
TraceCompat.endSection();
}
第三种写法我们认为是屏幕可见的第一帧回调,通过观察systrace图可见
Activity 的 onCreate/onStart/onResume三个回调中,并没有执行Measure和Layout操作,这个是在后面的performTraversals中才执行的。因为我们知道,,应用启动的时候,要等两次 performTraversals 都执行完成之后才会显示第一帧,
因此updateText 方法需要在第二个performTraversals 方法执行完成后(即APP第一帧在屏幕上显示),马上就去执行,那么即起到了 Delay Load的作用,又可以正确显示图片的宽高。updateText 在第二个 performTraversals 方法执行完成后马上执行,然后下一个 VSYNC 信号来了之后,,TextView就更新了。