前言
我们对 setContentView 应该都很熟悉,也都知道它是用来设置我们的布局的。之前只会用,闲来无事研究一下底层是怎么实现的。
使用方式
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
源码分析
继承Activity源码:
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
继承AppCompatActivity源码:
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
今天就先研究一下继承AppCompatActivity的源码。
1、 进入getDelegate()方法,可以看到AppCompatDelegate对象是通过内部的一个静态create创建的对象。
@NonNull
public AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, this);
}
return mDelegate;
}
2、 进入到create方法,可以了解到AppCompatDelegate是一个抽象类,AppCompatDelegateImpl则是AppCompatDelegate类的实例。
public abstract class AppCompatDelegate {
@NonNull
public static AppCompatDelegate create(@NonNull Activity activity,
@Nullable AppCompatCallback callback) {
return new AppCompatDelegateImpl(activity, callback);
}
}
3、 因为AppCompatDelegateImpl是抽象类AppCompatDelegate的实例,那么setContentView的实现最终在AppCompatDelegateImpl类中如下。
@Override
public void setContentView(int resId) {
ensureSubDecor();
//获取android.R.id.content的布局,也就是activity的根布局
ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
//将我们的布局添加到根布局上
LayoutInflater.from(mContext).inflate(resId, contentParent);
mAppCompatWindowCallback.getWrapped