|
|
发表于 2016-11-5 05:33:58
|未经授权,严禁转载,违者必究...
|
|阅读模式
视图 摸索 加载 LayoutInflater Android layoutinflater layoutinflater用法 layoutinflater.from getlayoutinflater layoutinflater是什么 layoutinflater 参数 获取layoutinflater layoutinflater详解 layoutinflater的作用
此次跟大师分享的是关于LayoutInflater的利用,在开辟的过程中,LayoutInfalter经常用于加载视图,对,今天咱们来聊的就是,关于加载视图的一些事儿,我记得之前一位曾共事过的一位同事问到我一个问题,activity是若何加载资本文件来显示界面的,古话说得好,知其然不知其所以然,是以在写这篇文章的时辰我也做了不少的预备,在这里我先引出几个问题,然后我们经由过程问题在源码中寻找谜底。
在LayoutInflater里面,经由过程静态方式from(Context),然后继续挪用Context中的方式getSystemService获取LayoutInflater,我们往Context继续看。
大师会发现,怎么点进去这是个抽象方式,其实Context是一个抽象类,真正实现的是ContextImpl这个类,我们就继续看ContextImpl:
ContextImpl.java:
SystemServiceRegistry.java:
SystemServiceRegistry这个类中的静态方式getSystemService,经由过程SYSTEM_SERVICE_FETCHERS获取ServiceFetcher,我们先看看SYSTEM_SERVICE_FETCHERS跟ServiceFetcher在SystemServiceRegistry中的界说。
SystemServiceRegistry.java:
SYSTEM_SERVICE_FETCHERS在SystemServiceRegistry这个类中作为全局常量,经由过程键值对的体例用来保留ServiceFetcher,而ServiceFetcher又是什么?在源码中,ServiceFetcher是一条接口,经由过程泛型T界说了getService(ContextImpl)来获取办事对象。那么具体ServiceFetcher具体的实此刻什么处所?在SystemServiceRegistry中,有一段如许的代码:
SystemServiceRegistry.java:
在这个静态代码块中,经由过程registerService进行初始化注册办事。我们先看看这个静态方式。
registerService这个一段函数的感化就是用来经由过程键值对的体例,保留办事对象,也就是说,SystemServiceRegistry会初始化的时辰注册各类办事,而我们的也看到Context.LAYOUT_INFLATER_SERVICE作为key来获取LayoutInfalter。
我们继续看看ServiceFetcher的实现类:
CachedServiceFetcher的感化用于保留我们的泛型T,同时这个CachedServiceFetcher有一个抽象方式createService,createService这个方式用来建立这个办事,是以利用这个类就必需重写这个方式,我们继续看回:
此刻看回来这里,注册办事不就是经由过程经由过程键值对的体例进行保留这个对象,然而我们获取到的LayoutInflater其实是PhoneLayoutInflater。PhoneLayoutInflater继续于LayoutInfalter.
context的实现类contextImpl,挪用SystemServiceRegistry.getSystemService,经由过程键值对的体例获取PhoneLayoutInflater对象,从中我们也看到,这种体例经由过程键值对的体例缓存起这个对象,避免建立过多的对象,这是也一种单例的设计模式。
在结构文件中,我设置其layoutwidth与layout_height别离是填充屏幕。
在activity的content_main.xml结构:
LayoutInflater.java:
方式一:
方式二:
我们从代码中看到,无论是方式一,仍是方式二,最终仍是会挪用方式二进行加载,我们就从方式二的三个参数,进行阐发一下。
从方式一看到,其实就是在挪用方式二,只是方式一的第三个传参操纵root!=null进行判定罢了,现实上最终仍是挪用方式二。
我们加载统一个结构文件my_btn.xml,获取到view,然后别离输出,不雅察有什么纷歧样:
问题来了,为什么我加载统一个结构,获得的view一个是Button,一个是RelativeLayout,我们每一个阐发一下:
View2:
LayoutInflater.from(this).inflate(R.layout.my_btn, mContainer, false);
同上可得,第三个参数attachToRoot 为false.也就是不把这个view添加到root里面去
是以,返回的是view2,就是Button.
View4:
LayoutInflater.from(this).inflate(R.layout.my_btn, mContainer);
按照方式一跟方式二的比力,root!=null.view4跟view3的加载是一样的,同理返回的是RelativeLayout.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mContainer = (RelativeLayout) findViewById(R.id.content_main);
Button btn = (Button) LayoutInflater.from(this).inflate(R.layout.my_btn, null);
mContainer.addView(btn);
}
2091165-430198464a788f9e.png
无题目.png
大师看到问题了吗?为什么我在my_btn.xml中设置了button的结构宽高是全屏,怎么不起感化了?莫非说在my_btn.xml中Button的layout_width和layout_height起不了感化?我们从源码中看一下:
经由过程资本治理获取xml解析器,继续往下看:
在这一块代码中,先声明一个变量result,这个result用来返回最终的成果,在我们的演示中,假如inflate(resource,root,isAttachRoot)中的root为空,那么结构参数params为空,而且按照要害代码D可得,返回的result就是temp,也就是Button自己。是以在以上例子中,假如说root不为空的话,Button中声明的layout_width与layout_height起到了感化。
注:假如经由过程LayoutInflater.from(this).inflate(R.layout.my_btn, mContainer)或者LayoutInflater.from(this).inflate(R.layout.my_btn, mContainer,true)加载视图,不需要再额外的利用mContainer.addView(view),因为返回的默认就是root自己,在要害代码C中可看到:
root会添加temp进去,在代码初始化的时辰,result默认就是root,我们不需要addView,在inflate中会帮我们操作,假如我们还要addView的话,就会抛出异常:
The specified child already has a parent. You must call removeView() on the child's parent first.
我们往setContentView继续摸索,找到Activity的setContentView()
getWindow()现实上是获取window对象,但Window类是抽象类,具体的实现是PhoneWindow,我们往这个类看看:
PhoneWindow.java:
activity加载视图,最后仍是经由过程LayoutInflater进行加载视图,activity的界面布局如下:
我们的mContentView就是ContentView,是以经由过程LayoutInflater加载视图进入ContentView。而root就是mContentView,是以我们在Activity不需要本身addView().
总结:
知其然不知其所以然,这对于LayoutInflater描述再合适不外了,文章中原本还涉及到了关于若何利用LayoutInflater中遍历view,代码太长就纷歧一展示,并且在inflate中我们可以看到,经由过程利用merge标签,可以削减view的层级,直接把merge标签内的子view直接添加到rootview中,是以结构优化能提高视图加载的机能,提高效率。还有获取LayoutInflater的体例,经由过程键值对进行缓存LayoutInflater,这是在android中单例设计的一种体验。
|
|