Android布局优化ViewStub源码分析
Posted lxn_李小牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android布局优化ViewStub源码分析相关的知识,希望对你有一定的参考价值。
前言
关于布局优化的内容之前总结过一篇,可以移步Android布局优化总结,今天我们从源码的角度来分析一下ViewStub是如何实现的。
源码分析
@RemoteView
public final class ViewStub extends View
private int mInflatedId; // 被填充View的id
private int mLayoutResource; // layout布局资源id
// 弱引用,引用填充的View,以便在inflate之后可以通过setVisibility方法设置可见性
private WeakReference<View> mInflatedViewRef;
private LayoutInflater mInflater;
private OnInflateListener mInflateListener; // inflate监听
public ViewStub(Context context)
this(context, 0);
/**
* Creates a new ViewStub with the specified layout resource.
*
* @param context The application's environment.
* @param layoutResource The reference to a layout resource that will be inflated.
*/
public ViewStub(Context context, @LayoutRes int layoutResource)
this(context, null);
mLayoutResource = layoutResource;
public ViewStub(Context context, AttributeSet attrs)
this(context, attrs, 0);
public ViewStub(Context context, AttributeSet attrs, int defStyleAttr)
this(context, attrs, defStyleAttr, 0);
public ViewStub(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
super(context);
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ViewStub, defStyleAttr, defStyleRes);
mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID);
mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);
mID = a.getResourceId(R.styleable.ViewStub_id, NO_ID);
a.recycle();
setVisibility(GONE); // 默认不可见
setWillNotDraw(true); // 如果View不绘制任何内容,设置这个标记可以优化性能,默认View没有设置这个标记,如果重写onDraw,就不要设置这个标记
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
setMeasuredDimension(0, 0); // 测量时尺寸为0
@Override
public void draw(Canvas canvas) // 不绘制内容
@Override
protected void dispatchDraw(Canvas canvas)
..... 省去部分代码
private View inflateViewNoAdd(ViewGroup parent)
final LayoutInflater factory;
if (mInflater != null)
factory = mInflater;
else
factory = LayoutInflater.from(mContext);
// 通过inflate填充布局
final View view = factory.inflate(mLayoutResource, parent, false);
if (mInflatedId != NO_ID)
view.setId(mInflatedId);
return view;
private void replaceSelfWithView(View view, ViewGroup parent)
final int index = parent.indexOfChild(this);
parent.removeViewInLayout(this); // 移除ViewStub,后面不能在inflate
final ViewGroup.LayoutParams layoutParams = getLayoutParams(); // 获得ViewStub的布局参数
if (layoutParams != null)
parent.addView(view, index, layoutParams); // 把ViewStub指定的布局添加到parent中
else
parent.addView(view, index);
/**
* Inflates the layout resource identified by @link #getLayoutResource()
* and replaces this StubbedView in its parent by the inflated layout resource.
*
* @return The inflated layout resource.
*
*/
public View inflate()
final ViewParent viewParent = getParent(); // 获取ViewStub的parent
if (viewParent != null && viewParent instanceof ViewGroup)
if (mLayoutResource != 0)
final ViewGroup parent = (ViewGroup) viewParent;
final View view = inflateViewNoAdd(parent);
replaceSelfWithView(view, parent);
mInflatedViewRef = new WeakReference<>(view);
if (mInflateListener != null)
mInflateListener.onInflate(this, view);
return view;
else
throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
else
throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
/**
* Specifies the inflate listener to be notified after this ViewStub successfully
* inflated its layout resource.
*
* @param inflateListener The OnInflateListener to notify of successful inflation.
*
* @see android.view.ViewStub.OnInflateListener
*/
public void setOnInflateListener(OnInflateListener inflateListener)
mInflateListener = inflateListener;
/**
* Listener used to receive a notification after a ViewStub has successfully
* inflated its layout resource.
*
* @see android.view.ViewStub#setOnInflateListener(android.view.ViewStub.OnInflateListener)
*/
public static interface OnInflateListener
/**
* Invoked after a ViewStub successfully inflated its layout resource.
* This method is invoked after the inflated view was added to the
* hierarchy but before the layout pass.
*
* @param stub The ViewStub that initiated the inflation.
* @param inflated The inflated View.
*/
void onInflate(ViewStub stub, View inflated); // ViewStub填充完毕的回调
/** @hide **/
public class ViewReplaceRunnable implements Runnable
public final View view;
ViewReplaceRunnable(View view)
this.view = view;
@Override
public void run()
replaceSelfWithView(view, (ViewGroup) getParent());
以上是关于Android布局优化ViewStub源码分析的主要内容,如果未能解决你的问题,请参考以下文章