最近对代码进行优化,想到了面试时常问的ViewStub,可以实现延迟加载.虽然知道大概工作过程是初始化时不加载,使用的时候再加载.但是具体如何使用却还一直没有动手尝试.
https://developer.android.com/training/improving-layouts/loading-ondemand.html
https://developer.android.com/reference/android/view/ViewStub.html
看了下官方文档,ViewStub使用起来也很简单,教程就几句话.
首先是在布局文件里,将需要延迟加载的布局用ViewStub标签替换.
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
同时将需要延迟加载的布局移出,单独写在新的布局文件中(本例中的progress_overlay),需要注意的是ViewStub不支持与<merge>
标签一起使用,即单独移除的布局,不能用<merge>
标签作为父布局.
ViewStub标签中新增了inflatedId属性,ViewStub使用id属性,当ViewStub被新布局替换之后,就使用inflatedId来表示新布局,ViewStub不再存在于布局中.
布局文件配置好,在代码中使用时也很简单,有两种方式来加载.
findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
// or
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
通过findViewById找到ViewStub之后,调用setVisibility(View.VISIBLE)和inflate()方法都可以加载新布局.
其中ViewStub中setVisibility方法经过了重写,当ViewStub使用setVisibility方法设置为VISIBLE或INVISIBLE时,都会调用inflate()方法,实现加载.
这两种方法区别在于,setVisibility使用方便,当代码比较简单,即只需要显示出布局,不需要做其他操作(显示无网络信息等时),可以不影响之前代码的逻辑.
但由于setVisibility方法返回值为空,所以如果需要对新加载布局进行修改或输入时,使用inflate()方法可以直接返回所需的View,不在需要findViewById了.
需要注意一点,即ViewStub加载成功后,ViewStub即为空不再可用了.