Android中级——getSystemService和LayoutInflater

getSystemService和LayoutInflater

  • 使用容器管理单例模式
  • getSystemService()
  • LayoutInflater

使用容器管理单例模式

将单例统一管理,隐藏实现,第一次获取时创建,下次直接从缓存中获取,避免重复创建对象

class SingletonManager {
    private static Map sMap = new HashMap<>();

    private SingletonManager() {

    }

    public static void registerService(String key, Object instance) {
        if (!sMap.containsKey(key)) {
            sMap.put(key, instance);
        }
    }

    public static Object getService(String key) {
        return sMap.get(key);
    }
}

getSystemService()

上述代码其实就是Context中getSystemService()获取系统服务的简略实现,其是抽象方法,实现类是ContextImpl,如下

@Override
public Object getSystemService(String name) {
    ......
    return SystemServiceRegistry.getSystemService(this, name);
}

调用SystemServiceRegistry的getSystemService(),如下

public static Object getSystemService(ContextImpl ctx, String name) {
    if (name == null) {
        return null;
    }
    final ServiceFetcher fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    if (fetcher == null) {
        ......
        return null;
    }

    final Object ret = fetcher.getService(ctx);
   	......
    return ret;
}

SYSTEM_SERVICE_FETCHERS存储ServiceFetcher,其在static语句块进行注册,如下

private static final Map> SYSTEM_SERVICE_FETCHERS = new ArrayMap>();

private static  void registerService(String serviceName, Class serviceClass, ServiceFetcher serviceFetcher) {
    ......
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}

static {
    ......
   	registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
   	new CachedServiceFetcher() {
    @Override
    public LayoutInflater createService(ContextImpl ctx) {
        return new PhoneLayoutInflater(ctx.getOuterContext());
    }});

    ......
}

会调用ServiceFetcher的子类的CachedServiceFetcher的getService(),若已经创建则从缓存中获取,否则调用createService()创建并加入缓存

static abstract interface ServiceFetcher {
    T getService(ContextImpl ctx);
}

static abstract class CachedServiceFetcher implements ServiceFetcher {
	......
    @Override
    @SuppressWarnings("unchecked")
    public final T getService(ContextImpl ctx) {
        final Object[] cache = ctx.mServiceCache;
		......
        T ret = null;
        for (;;) {
            ......
            synchronized (cache) {
                T service = (T) cache[mCacheIndex];
                if (service != null || ......) {
                    ret = service;
                    break;
                }
				......
            }

            if (doInitialize) {
                T service = null;
                ......
                try {
                    service = createService(ctx);
                    ......
                }......
                ret = service;
                break;
            }
			......  
        }
        .....
        return ret;
    }

    public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
}

LayoutInflater

LayoutInflater是抽象类,分析其inflate()方法,如果有预先编译则设置LayoutParams返回View

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
    return inflate(resource, root, root != null);
}

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
    final Resources res = getContext().getResources();
    ......
    View view = tryInflatePrecompiled(resource, res, root, attachToRoot);
    if (view != null) {
        return view;
    }
    XmlResourceParser parser = res.getLayout(resource);
    try {
        return inflate(parser, root, attachToRoot);
    } finally {
        parser.close();
    }
}

否则通过xml解析器解析

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    synchronized (mConstructorArgs) {
        final Context inflaterContext = mContext;
        final AttributeSet attrs = Xml.asAttributeSet(parser);
        Context lastContext = (Context) mConstructorArgs[0];
        mConstructorArgs[0] = inflaterContext;
        View result = root;
        
        try {
            advanceToRootNode(parser);
            final String name = parser.getName();	//找到第一个标签元素
            ......
            if (TAG_MERGE.equals(name)) {	//加载merge标签,并依附到root
                ......
                rInflate(parser, root, inflaterContext, attrs, false);
            } else {		
            	//解析非merge标签,name即为控件名如LinearLayout
                final View temp = createViewFromTag(root, name, inflaterContext, attrs);
                ViewGroup.LayoutParams params = null;
                if (root != null) {
                    ......
                    params = root.generateLayoutParams(attrs);	//若root不为空根据root生成LayoutParams
                    if (!attachToRoot) {	//若不依附到root则直接为View设置LayoutParams
                        temp.setLayoutParams(params);
                    }
                }
                ......
                rInflateChildren(parser, temp, attrs, true);	//解析子View并依附到temp
                ......
                if (root != null && attachToRoot) {	//若依附到root则添加
                    root.addView(temp, params);
                }
                ......
                if (root == null || !attachToRoot) {	//若不依附到root则直接返回
                    result = temp;
                }
            }
        }......
        return result;
    }
}

调用createViewFromTag()生成View的过程如下

private View createViewFromTag(View parent, String name, Context context, AttributeSet attrs) {
    return createViewFromTag(parent, name, context, attrs, false);
}

View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
        boolean ignoreThemeAttr) {
    if (name.equals("view")) {
        name = attrs.getAttributeValue(null, "class");
    }

    if (!ignoreThemeAttr) {		//加载自定义的attr标签
        final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
        final int themeResId = ta.getResourceId(0, 0);
        if (themeResId != 0) {
            context = new ContextThemeWrapper(context, themeResId);
        }
        ta.recycle();
    }
    try {
        View view = tryCreateView(parent, name, context, attrs); //使用自定义的LayoutInflater.Factory加载View
        if (view == null) {
            final Object lastContext = mConstructorArgs[0];
            mConstructorArgs[0] = context;
            try {
                if (-1 == name.indexOf('.')) {	//若不存在.说明是系统控件,调用onCreateView()加上包名
                    view = onCreateView(context, parent, name, attrs);
                } else {	//自定义控件自带包名com.xxx.xxx
                    view = createView(context, name, null, attrs);
                }
            } finally {
                mConstructorArgs[0] = lastContext;
            }
        }
        return view;
    }......
}


@Nullable
public View onCreateView(@NonNull Context viewContext, @Nullable View parent,
        @NonNull String name, @Nullable AttributeSet attrs)
        throws ClassNotFoundException {
    return onCreateView(parent, name, attrs);
}

protected View onCreateView(View parent, String name, AttributeSet attrs)
        throws ClassNotFoundException {
    return onCreateView(name, attrs);
}

接下来会调用到子类PhoneLayoutInflater的onCreateView(),为系统控件添加上包名

public class PhoneLayoutInflater extends LayoutInflater {
    private static final String[] sClassPrefixList = {
        "android.widget.",
        "android.webkit.",
        "android.app."
    };

    @Override protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
        for (String prefix : sClassPrefixList) {
            try {
                View view = createView(name, prefix, attrs);
                if (view != null) {
                    return view;
                }
            }......
        }
        return super.onCreateView(name, attrs);
    }
}

再调用回LayoutInflater的onCreateView()、createView()

protected View onCreateView(String name, AttributeSet attrs)
        throws ClassNotFoundException {
    return createView(name, "android.view.", attrs);
}

public final View createView(String name, String prefix, AttributeSet attrs)
        throws ClassNotFoundException, InflateException {
    Context context = (Context) mConstructorArgs[0];
    if (context == null) {
        context = mContext;
    }
    return createView(context, name, prefix, attrs);
}

最终和自定义View一样调用到4个参数的createView()

public final View createView(@NonNull Context viewContext, @NonNull String name, @Nullable String prefix, @Nullable AttributeSet attrs) throws ClassNotFoundException, InflateException {
    ......
    //从缓存中获取构造函数,若不是同一个ClassLoader则置空和删除缓存
    Constructor constructor = sConstructorMap.get(name);
    if (constructor != null && !verifyClassLoader(constructor)) {
        constructor = null;
        sConstructorMap.remove(name);
    }
    Class clazz = null;
    try {
        ......
        if (constructor == null) {	//若构造函数不在缓存,则根据包名生成构造函数添加到缓存
            clazz = Class.forName(prefix != null ? (prefix + name) : name, false,
                    mContext.getClassLoader()).asSubclass(View.class);
            if (mFilter != null && clazz != null) {
                boolean allowed = mFilter.onLoadClass(clazz);
                if (!allowed) {
                    failNotAllowed(name, prefix, viewContext, attrs);
                }
            }
            constructor = clazz.getConstructor(mConstructorSignature);
            constructor.setAccessible(true);
            sConstructorMap.put(name, constructor);
        }......
        
        Object lastContext = mConstructorArgs[0];
        mConstructorArgs[0] = viewContext;
        Object[] args = mConstructorArgs;
        args[1] = attrs;
        try {
            final View view = constructor.newInstance(args);	//利用反射构造View
            if (view instanceof ViewStub) {
                final ViewStub viewStub = (ViewStub) view;
                viewStub.setLayoutInflater(cloneInContext((Context) args[0]));	
            }
            return view;
        }......
    }......
}

接下来分析用于解析View树的rInflateChildren()

final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs,
        boolean finishInflate) throws XmlPullParserException, IOException {
    rInflate(parser, parent, parent.getContext(), attrs, finishInflate);
}

调用rInflate()

void rInflate(XmlPullParser parser, View parent, Context context, AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {

    final int depth = parser.getDepth();	//深度优先遍历获取树的深度
    int type;
    boolean pendingRequestFocus = false;
    while (((type = parser.next()) != XmlPullParser.END_TAG ||
            parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
        if (type != XmlPullParser.START_TAG) {
            continue;
        }
        
        final String name = parser.getName();
        if (TAG_REQUEST_FOCUS.equals(name)) {	//解析requestFocus标签
            pendingRequestFocus = true;
            consumeChildElements(parser);
        } else if (TAG_TAG.equals(name)) {	//解析tag标签
            parseViewTag(parser, parent, attrs);
        } else if (TAG_INCLUDE.equals(name)) {	//解析include标签
            if (parser.getDepth() == 0) {
                throw new InflateException(" cannot be the root element");
            }
            parseInclude(parser, context, parent, attrs);
        } else if (TAG_MERGE.equals(name)) {	//merge不是根标签抛出异常
            throw new InflateException(" must be the root element");
        } else {
            final View view = createViewFromTag(parent, name, context, attrs);	//同上根据控件名进行解析
            final ViewGroup viewGroup = (ViewGroup) parent;
            final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
            rInflateChildren(parser, view, attrs, true);	//递归调用
            viewGroup.addView(view, params);	//将解析的View添加到父View
        }
    }
    if (pendingRequestFocus) {	//若存在requestFocus,则获取焦点
        parent.restoreDefaultFocus();
    }
    if (finishInflate) {
        parent.onFinishInflate();
    }
}

你可能感兴趣的:(#,Android中级,android,java,开发语言)