android源码设计模式解析与实战 读书笔记 2 单例模式(下)
来源:互联网 发布:小明看看地址永久域名 编辑:程序博客网 时间:2024/05/17 09:44
android源码中的单例模式:LayoutInflater。
LayoutInflater的获取通过context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);Context是一个抽象类,我们需要找到它的具体实现。一个Activity的入口时ActivityThread的main方法,在main方法中,会调用其attach函数,参数为false(非系统应用),在attach中会通过Binder机制与ActivityManagerService通信,并且最终调用handleLaunchActivity函数,在该函数会调用performLaunchActivity函数,之后就会通过createBaseContextForActivity函数为该Activity创建Context,从中我们可以知道Context的具体实现类是ContextImpl。在ContextImpl中维护了一个SYSTEM_SERVICE_MAP的Service静态容器,并在其的静态语句块中实现了对LAYOUT_INFLATER_SERVICE服务的注册,至此我们就发现LAYOUT_INFLATER_SERVICE就是通过之前的静态实现的单例的。
深入理解LayoutInflater:
LayoutInflater是一个抽象类,所以我们还需要找到它的具体实现,从刚刚将LAYOUT_INFLATER_SERVICE注册入手。如下代码
registerService(LAYOUT_INFLATER_SERVICE,new ServiceFetcher(){
public Object createService(ContextImpl ctx){
return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
}
})
继续看PolicyManager.makeNewLayoutInflater方法:
public LayoutInflater makeNewLayoutInflater(Context context){ return sPolicy.makeNewLayoutInflater(context);}// 在Policy中public LayoutInflater makeNewLayoutInflater(Context context){ return new PhoneLayoutInflater(context);}
至此我们知道LayoutInflater的具体实现类是PhoneLayoutInflater,继续深入看PhoneLayoutInfla
public class PhoneLayoutInflater extends LayoutInflater{/* 内置View类型的前缀,如TextView的完整路径是android.widget.TextView*/private static final String[] sClassPrefixList={"android.widget","android.webkit"};protect View onCreateView(String name,AttributeSet attires)throws ClassNotFoundException{for(String prefix :sClassPrefixList){View view = createView(name,prefix,attires);if(view != null){return view;}}return super.onCreateView(name,attrs);}}
通过传递进来的View的名字加上前缀得到完整路径来构造对应的View对象。
具体流程:
Activity的setContentView会调用Window的同名方法,而Window的具体实现时PhoneWindow,如下是PhoneWindow中对应方法:
public void setContentView(int layoutResID){ //当mContentParent为空时先构建DecorView,并将包裹到mContentParent中 if(mContentParent == null){ installDecor(); }else{ mContentParent.removeAllViews(); } //解析layoutResID mLayoutInflater.inflate(layoutResID,mContentParent);}
在看下一个Window的View层级结构,从外到内分别是:Activity-PhoneWindow-DecorView-DefaultLayout-ViewGroup mContentParent-用户自己的XML布局。
接下来就是解析XML,并将其中的View添加到mContentParent中来。
inflater方法的主要有下面几步:
- 解析XML中根标签(第一个元素);
- 如果根标签是merge,那么调用rInflate进行解析,rInflate会merge标签下的所有子View直接添加到根标签中;
- 如果标签是普通元素,那么调用createViewFromTag对该元素进行解析;
- 调用rInflate解析temp根元素下的所有子View,并且将这些子View都添加到temp下;
- 返回解析到的根视图。
主要分析下createViewFromTag:
- 首先判断用户是否设置LayoutInflater的factory来自行解析View(忽略);
- 通过View的name中是否包含”.”来区分是自定义控件还是系统控件,系统控件将会拼接成完整的路径,这样就保证后面创建View时使用的是完整路径;
- 通过反射构造View(这里有构造函数的缓存处理)。
看完构造View,在看解析整个视图树,由rInflate完成;rInflate通过深度优先遍历来构造视图树,每解析到一个View元素就会递归rInflate,直到这条路径下的最后一个元素,然后再回溯过来将每个View元素添加到它们的parent中。通过rInflate的解析之后,整个视图树就构建完成,从而显示在我们的视野中。
运用单例模式:
在我们使用的ImageLoader中,它的创建我们就是使用的DCL单例,代码如下:
public static ImageLoader getInstance(){
if(sInstance == null){
synchronized(ImageLoader.class){
if(sInstance == null){
sInstance = new ImageLoader();
}
}
}
}
单例优点:
- 由于单例模式在内存中只有一个实例,减少类内存开支;
- 减少类系统的性能开销;
- 可以避免对资源的多重占用;
- 可以在系统设置全局的访问点,优化和共享资源访问;
单例缺点:
1. 一般没有接口,扩展很困难;
2. 单例如果持有Context,很容易引发内存泄漏,此时应使用ApplicationContext来代替。
- android源码设计模式解析与实战 读书笔记 2 单例模式(下)
- android源码设计模式解析与实战 读书笔记 2 单例模式(上)
- 《Android源码设计模式解析与实战》读书笔记(二)——单例模式
- 【读书笔记】Android源码设计模式解析与实战(二)——单例模式
- 《Android源码设计模式解析与实战》读书笔记(一)
- 《Android源码设计模式解析与实战》读书笔记(二)
- 《Android源码设计模式解析与实战》读书笔记(三)
- 《Android源码设计模式解析与实战》读书笔记(四)
- 《Android源码设计模式解析与实战》读书笔记(五)
- 《Android源码设计模式解析与实战》读书笔记(六)
- 《Android源码设计模式解析与实战》读书笔记(七)
- 《Android源码设计模式解析与实战》读书笔记(八)
- 《Android源码设计模式解析与实战》读书笔记(九)
- 《Android源码设计模式解析与实战》读书笔记(十)
- 《Android源码设计模式解析与实战》读书笔记(十一)
- 《Android源码设计模式解析与实战》读书笔记(十二)
- 《Android源码设计模式解析与实战》读书笔记(十二)
- 《Android源码设计模式解析与实战》读书笔记(十三)
- wc2013 糖果公园
- 用鼠标在图片上画矩形框
- 曼德勃罗(Mandelbrot)集合与其编程实现
- python 钩子函数详解
- 猴王水果竞猜网站源码 思路 兼容所有手机
- android源码设计模式解析与实战 读书笔记 2 单例模式(下)
- python2016-03-11
- 正则表达式
- Oracle之RMAN数据库在非归档模式下的备份和恢复
- 关于百度地图SDK联网初始化的一个坑
- 单例模式及C++实现代码
- cocos2dx 加速度传感器
- Android Stutio 提示错误:Plugin is too old, please update to a more recent version......的解决办法
- C/C++学习笔记