结尾
最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
高级UI,自定义View
UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。
不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
if (name.equals(“TextView”))
{
Button button = new Button(context, attrs);
return button;
}
运行你会发现,界面上的TextView变成了Button
是不是很惊奇,但是我们已经能够确定这个方法的确能够根据布局文件中的信息去创建对应的View了。
你可以会问,谁没事干把TextView换成Button哇,就没什么靠谱的作用吗?
还真有,假设你的项目编写了一半,忽然有个需求需要自定义一个TextView(称为:MyTextView)来替换系统的TextView:
那么现在你就不必去打开以前的布局文件把TextView全部进行修改,直接在BaseActivity里面进行下面的操作就可以了:
if (name.equals(“TextView”))
{
MyTextView view = new com.zhy.MyTextView(context,attrs);
return view;
}
对于自定义的View,你也可以通过比对name(随便设置个name都可以,不需要去完整的编写全路径了),然后直接去new出该对象。这么做有一个好处,相比系统去帮你创建,效率会高一点,因为系统有一些逻辑需要走,并且最终是通过反射的方式帮你创建View。
不过,对于setFactory的使用,可能会面临下面的问题。
现在开发App的时候,我们一般Activity都继承于AppCompatActivity
,而在AppCompatActivity
中,实际上也调用了setFactory
方法。
如果你自己还调用了setFactory
就可能带来一些问题,因为setFactory并不能重复调用。
3、setFactory已经被v7包占领
打开AppCompatActivity的源码,找到onCreate,你会发现如下代码:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
getDelegate().installViewFactory();
//…
}
installViewFactory的具体实现为:
@Override
public void installViewFactory() {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
if (layoutInflater.getFactory() == null) {
LayoutInflaterCompat.setFactory(layoutInflater, this);
} else {
Log.i(TAG, “The Activity’s LayoutInflater already has a Factory installed”
- " so we can not install AppCompat’s");
}
}
这里你会发现,AppCompatActivity中也尝试去setFactory,如果我们再其之前调用了setFactory,就会打印上面的info信息,并且造成其setFactroy不会生效,其实从Log中也能看出:
AppCompatDelegate﹕ The Activity’s LayoutInflater
already has a Factory installed
so we can not install AppCompat’s
这么来看,如果我们使用AppCompatActivity
,我们是不应该按照我们前面的方式,直接设置setFactory,否则我们可能会带来一些影响。
我们会带来什么影响呢?
其实AppCompatActivity的setFactory也是想根据name去生成一些类,大家还记得,更新v7包的时候,忽然我们的TextView就支持了一些属性,比如tint
属性,以前是不支持的,怎么能够做到使用v7包,然后就能支持且向下兼容的呢?
哈哈,原理就在这里,看下面的代码片段
switch (name) {
case “TextView”:
view = new AppCompatTextView(context, attrs);
break;
case “ImageView”:
view = new AppCompatImageView(context, attrs);
break;
case “Button”:
view = new AppCompatButton(context, attrs);
break;
case “EditText”:
view = new AppCompatEditText(context, attrs);
break;
//…
}
可以看到系统其实是利用setFactory,瞒着我们把TextView等类早就换成AppCompatTextView等类了。
如果你使用AppCompatActivty你可以通过打印textview.getClass()
来验证。
ok,看到这里,我们上面的一个问题也就知道答案了:
我们按照前面的方式直接设置setFactory,会带来什么影响呢?
会造成没有办法使用一些新的特性,比如tint
等。
4、解决方案
我们具体看下appcompat中onCreateView的全部代码:
@Override
public final View onCreateView(View parent, String name,
Context context, AttributeSet attrs) {
// First let the Activity’s Factory try and inflate the view
final View view = callActivityOnCreateView(parent, name, context, attrs);
if (view != null) {
return view;
}
// If the Factory didn’t handle it, let our createView() method try
return createView(parent, name, context, attrs);
}
可以看到其最终是调用:createView
方法完成view的创建,并且值得高兴的是该方法是public的。
也就是说,我们可以自己设置factory中,依然可以保证appcompat中创建View的代码的执行。
LayoutInflaterCompat.setFactory(LayoutInflater.from(this), new LayoutInflaterFactory()
{
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs)
{
//你可以在这里直接new自定义View
//你可以在这里将系统类替换为自定义View
//appcompat 创建view代码
AppCompatDelegate delegate = getDelegate();
View view = delegate.createView(parent, name, context, attrs);
return view;
}
});
下面看一个我们常见的场景。
5、高效统一设置app中所有字体
很多时候我们为了app更加个性,然后整体采用外部引入的字体。
很多开发者的实现是这样的,在BaseActivity的onCreate中去从跟布局去递归遍历所有的View,类似的代码如下:
public void setTypeface(ViewGroup root, Typeface typeface){
if(rootnull || typefacenull){
return;
}
int count = root.getChildCount();
for(int i=0;i<count;++i){
View view = root.getChildAt(i);
if(View instanceof TextView){
((TextView)view).setTypeface(typeface);
}else if(View instanceof ViewGroup){
setTypeface((ViewGroup)view, typeface);
}
}
}
这种方式虽然方便,但是肯定会带来一定性能问题。
说到这,我估计你心理已经有全新的解决方案了,那就是利用setFactory,相关代码如下(在BaseActivity中):
public static Typeface typeface;
@Override
protected void onCreate(Bundle savedInstanceState)
{
if (typeface == null)
{
typeface = Typeface.createFromAsset(getAssets(), “hwxk.ttf”);
}
LayoutInflaterCompat.setFactory(LayoutInflater.from(this), new LayoutInflaterFactory()
{
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs)
{
AppCompatDelegate delegate = getDelegate();
View view = delegate.createView(parent, name, context, attrs);
if ( view!= null && (view instanceof TextView))
{
((TextView) view).setTypeface(typeface);
}
return view;
}
});
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
仅仅几行代码就能完成字体的全局统一设置了,而且非常高效。
我在布局文件中放了3个控件,看下效果图:
我们这里是恰好appcompat中对于上述常见的三个控件都进行了AppCompat化。
假设还有继承自TextView的自定义View如何处理呢?
最后
说一千道一万,不如自己去行动。要想在移动互联网的下半场是自己占有一席之地,那就得从现在开始,从今天开始,马上严格要求自己,既重视业务实现能力,也重视基础和原理。基础夯实好了,高楼才能够平地而起,稳如泰山。
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
搜索资料的时间来学习,也可以分享给身边好友一起学习。
[外链图片转存中…(img-1pjL7fMk-1715844976041)]
[外链图片转存中…(img-FNj9YUfZ-1715844976041)]
[外链图片转存中…(img-5ctk1hWC-1715844976042)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!