一、ViewStub概述
ViewStub是Android中一個比較好用的工具類,可以讓我們在布局中預先設置一些不常用的View,當需要使用時才加載進來,可以優化布局加載時間和內存開銷。使用ViewStub可以將布局層次扁平化,以提高布局性能。
ViewStub的優點:
- 方便:可以增加應用程序的負載效率。
- 簡單:加入的布局很簡單,在XML文件使用。
- 高效:由於布局的添加是動態的進行,內存佔用量更小。
- 快速:提高布局加載速度。
二、ViewStub的使用
1.在布局文件中添加ViewStub
可以在布局文件中添加ViewStub標籤,通過設置android:layout布局參數設置ViewStub的位置,code示例如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_container" android:layout_width="match_parent" android:layout_height="match_parent"> <!--其他View省略--> <ViewStub android:id="@+id/view_stub" android:layout="@layout/custom_layout" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
2.在Java文件中進行ViewStub的替換
在Java代碼中可以使用ViewStub的inflate()方法將StubView替換為真正的View,並添加到布局中。在這個例子中,被inflate的布局叫做custom_layout.xml
ViewStub viewStub = findViewById(R.id.view_stub); View inflatedView = viewStub.inflate();
3.使用ViewStub的setVisibility()
也可以使用setVisibility()方法,將ViewStub替換為相應的真正View。
ViewStub viewStub = findViewById(R.id.view_stub); viewStub.setVisibility(View.VISIBLE);
4.使用ViewStub的getInflatedId()
可以使用getInflatedId()方法獲取被inflate的View的ID。
ViewStub viewStub = findViewById(R.id.view_stub); int layoutId = viewStub.getInflatedId();
三、ViewStub原理
ViewStub本質上是一個代理View,當ViewStub替換為真正的View之後,ViewStub就不再存在,成為了普通的View。
可以通過以下方式查看ViewStub的監聽事件:
ViewStub viewStub = findViewById(R.id.view_stub); viewStub.setOnInflateListener(new ViewStub.OnInflateListener() { @Override public void onInflate(ViewStub stub, View inflated) { Log.d("ViewStubDemo", "inflate()"); } });
四、ViewStub的擴展
基於ViewStub的原理,可以通過擴展ViewStub做一些有意思的功能。
1.自定義ViewStub
可以擴展ViewStub實現自定義的StubView,提供創建的接口。
public class MyViewStub extends ViewStub { private View mInflated = null; private int mLayoutId; public interface OnInflateListener { void onInflated(MyViewStub stub, View inflated); } private OnInflateListener mListener; public MyViewStub(Context context, AttributeSet attrs) { super(context, attrs); } public void setLayoutResource(int layoutId) { mLayoutId = layoutId; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mInflated == null) { setVisibility(View.GONE); LayoutInflater inflater = LayoutInflater.from(getContext()); View view = inflater.inflate(mLayoutId, this, true); if (mListener != null) { mListener.onInflated(this, view); } mInflated = view; } else { setMeasuredDimension(mInflated.getMeasuredWidth(), mInflated.getMeasuredHeight()); } } public void setOnInflateListener(OnInflateListener listener) { mListener = listener; } }
自定義的ViewStub可以在布局文件中使用。
<com.example.myviewstub.MyViewStub android:id="@+id/my_view_stub" android:layout="@layout/custom_layout" android:layout_width="match_parent" android:layout_height="wrap_content" />
在Java文件中可以使用如下代碼進行ViewStub的替換(和ViewStub使用類似):
MyViewStub myViewStub = findViewById(R.id.my_view_stub); myViewStub.setLayoutResource(R.layout.custom_layout); View inflatedView = myViewStub.inflate();
2.ViewStub的懶加載
可以擴展ViewStub實現懶加載的StubView,可以控制是否需要加載。
public class LazyViewStub extends ViewStub { private boolean mIsVisibleToUser; private boolean mHasLoadOnce = false; public LazyViewStub(Context context, AttributeSet attrs) { super(context, attrs); } public void setVisibleToUser(boolean isVisibleToUser) { mIsVisibleToUser = isVisibleToUser; if (isVisibleToUser && !mHasLoadOnce) { inflate(); mHasLoadOnce = true; } } }
使用懶加載的ViewStub時,需要在Java代碼中控制是否需要加載。
LazyViewStub lazyViewStub = findViewById(R.id.lazy_view_stub); lazyViewStub.setLayoutResource(R.layout.custom_layout); lazyViewStub.setVisibleToUser(isVisibleToUser);
五、總結
ViewStub是Android中一個方便、簡單、高效和快速的工具類,可以優化布局加載時間和內存開銷。除此之外,還可以擴展ViewStub實現一些有意思的功能,例如自定義StubView和懶加載。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/249898.html