AppcompaActivity相对于Activity的主要变化;
0、兼容低版本的一些问题。兼容性重点要关注的版本有11,14,23,这三个版本是分界线。11,14可以忽略,但23要重视
1、主界面带有toolbar的标题栏;
//去掉AppcompaActivity的标题栏方法:
if (getSupportActionBar()!=null){
getSupportActionBar().hide();
}
2、theme主题只能用android:theme=”@style/AppTheme (appTheme主题或者其子类),而不能用android:style。 否则会提示错误: Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
第1和2点请看文章 :https://blog.csdn.net/today_work/article/details/79300181
注意:当活动继承AppCompatActivity时再设置取消标题则程序会直接挂掉
即以下程序无法正常运行
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
}
}
----------------------------------------------------- 关于 兼容性 文章开始---
在开发过程中,我们有时候会让子类继承Activity,有时候会继承AppCompatActivity,其实这两者会有一些不同的,那么接下来我们就让MainActivity分别继承Activity和AppCompatActivity,然后打印下activity_main中的ImageView,观察打印结果到底有有什么不同。
继承Activity,打印结果如下:
Log.e("TAG", "" + mImageIv); // ImageView
继承AppCompatActivity,打印结果如下:
Log.e("TAG", "" + mImageIv); // AppCompatImageView
AppCompatActivity:
1>:主要是为了兼容低版本的一些问题;
比如说在activity_main布局中写一个ImageView控件,然后分别让MainActivity继承Activity和AppCompatActivity,然后打印 image_view这个对象:
会发现:
继承Activity,打印结果如下:
Log.e("TAG", "" + mImageIv); // ImageView
继承AppCompatActivity,打印结果如下:
Log.e("TAG", "" + mImageIv); // AppCompatImageView
也就是说AppCompatActivity兼容了很多低版本的一些东西,比如说ImageView、TextView、Button、MD5.0的一些新控件它都做了一些兼容的:如下图所示:
图片.png
至于二者为什么会有区别,可以参考我的这篇文章
----------------------------------------------文章2 开始--------
上篇文章我们分析了Activity的setContentView的源码,如果对Activity的setContentView的源码不是很清楚的,可以先去看下我之前的文章:
Activity的setContentView的加载流程分析
1>:点击AppCompatActivity源码中搜索 setContentView,代码如下
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
2>:发现setContentView()方法还是抽象方法:
public abstract void setContentView(@LayoutRes int resId);
3>:点击getDelegate(),代码如下:
public static AppCompatDelegate create(Activity activity, AppCompatCallback callback) {
return create(activity, activity.getWindow(), callback);
}
4>:点击create()如下:
private static AppCompatDelegate create(Context context, Window window,
AppCompatCallback callback) {
final int sdk = Build.VERSION.SDK_INT;
if (sdk >= 23) {
return new AppCompatDelegateImplV23(context, window, callback);
} else if (sdk >= 14) {
return new AppCompatDelegateImplV14(context, window, callback);
} else if (sdk >= 11) {
return new AppCompatDelegateImplV11(context, window, callback);
} else {
return new AppCompatDelegateImplV7(context, window, callback);
}
}
会发现 AppCompatActivity会做一些兼容,大于23版本的、大于14版本的、大于11版本的,然后点击AppCompatDelegateImplV23,一路点击进去,发现,最终其实是调用的 AppCompatDelegateImplV7,也就是说最终调用的是AppCompatDelegateImplV7 类下边的 setContentView(),
5>:AppCompatDelegateImplV7 类下边的 setContentView()代码如下:
@Override
public void setContentView(View v) {
ensureSubDecor();
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
contentParent.addView(v);
mOriginalWindowCallback.onContentChanged();
}
接下来我们就让MainActivity分别继承Activity和AppCompatActivity,然后打印下activity_main中的ImageView,观察打印结果到底有有什么不同。
继承Activity,打印结果如下:
Log.e("TAG", "" + mImageIv); // ImageView
继承AppCompatActivity,打印结果如下:
Log.e("TAG", "" + mImageIv); // AppCompatImageView
1>:AppCompatActivity设置了Factory,就不会执行系统的onCreateView(),而是去执行自己的onCreateView()方法的逻辑,
@Override
public void installViewFactory() {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
if (layoutInflater.getFactory() == null) {
LayoutInflaterCompat.setFactory(layoutInflater, this);
} else {
}
}
2>:而上边一旦设置了setFactory,也就是说mFactory 不会空,那么它就会执行自己的onCreateView()方法,进而执行自己的一系列流程,就会执行mFactory.onCreateView(name, context, attrs)逻辑;
View view;
// 前提是看你有没有设置Factory 继承AppCompatActivity他就设置了
if (mFactory2 != null) {
view = mFactory2.onCreateView(parent, name, context, attrs);
} else if (mFactory != null) {
view = mFactory.onCreateView(name, context, attrs);
} else {
view = null;
}
// 通过反射创建View
3>:AppCompatActivity它会执行自己中的方法,然后判断各种 View,从而执行自己对应的 AppCompatTextView、AppCompatImageView等等所有的View,从而达到拦截View的创建,截图如下:
图片.png
由以上可知,AppCompatActivity会拦截View的创建,不会执行系统的onCreateView(),而是执行自己的 onCreateView(),进而去替换一些View,比如上边的TextView、ImageView、Button、EditText、Spinner、ImageButton等所有系统的 View控件。
----------------------------------------------文章2 结束--------
----------------------------------------------------- 关于 兼容性 文章结束---
文章1:https://www.jianshu.com/p/0f3a4b34d7bb
文章2:https://www.jianshu.com/p/44c80a455325