插件化开发 - LayoutInflate2。源码解析

之前解决了自定义LayoutInflate问题,使用自定义的LayoutInflate.inflate可以得到插件资源。1.layout

1.LayoutInflate解析。

//当root传入null时候,attachToRoot默认传入false
414   public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
   //getContext返回mContext,就是我们在构造函数传入的 为插件生成的context(里面只有插件资源)
415        final Resources res = getContext().getResources();
421        final XmlResourceParser parser = res.getLayout(resource);
423        return inflate(parser, root, attachToRoot);
427    }

接下来inflate传入解析的XmlResourceParser,逐个生成veiw
主要代码492行 createViewFromTag

451   public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
			//inflaterContext就是传入的插件mContext
458            mConstructorArgs[0] = inflaterContext;
459            View result = root;
461            try {
474                final String name = parser.getName();
483                if (TAG_MERGE.equals(name)) {
489                    rInflate(parser, root, inflaterContext, attrs, false);
490                } else {
491                    // Temp is the root view that was found in the xml
492                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);
//忽略代码,设置layoutparams带有attrs到temp中
514                    // Inflate all children under temp against its context.
515                    rInflateChildren(parser, temp, attrs, true);
553    }

注意,创建子view时候会调用context.getTheme,获取att,所以要重写getTheme返回Android系统的theme否则会因为找不到宿主style资源而报错。

748    View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
749            boolean ignoreThemeAttr) {
//ignoreThemeAttr是false就先设置theme到context中
//如果有mPrivateFactory就调用Factory的createView
//最后应该调用这里
790			view = createView(name, null, attrs);
813    }

这里主要找到具体的类,获得构造函数,调用构造函数,传入两个args,1.mContext 。2.attrs

575   
592    public final View createView(String name, String prefix, AttributeSet attrs)
593            throws ClassNotFoundException, InflateException {
594        Constructor<? extends View> constructor = sConstructorMap.get(name);
595        if (constructor != null && !verifyClassLoader(constructor)) {
596            constructor = null;
597            sConstructorMap.remove(name);
598        }
599        Class<? extends View> clazz = null;
600
601        try {
602            Trace.traceBegin(Trace.TRACE_TAG_VIEW, name);
603
604            if (constructor == null) {
605                // Class not found in the cache, see if it's real, and try to add it
606                clazz = mContext.getClassLoader().loadClass(
607                        prefix != null ? (prefix + name) : name).asSubclass(View.class);
608
609                if (mFilter != null && clazz != null) {
610                    boolean allowed = mFilter.onLoadClass(clazz);
611                    if (!allowed) {
612                        failNotAllowed(name, prefix, attrs);
613                    }
614                }
615                constructor = clazz.getConstructor(mConstructorSignature);
616                constructor.setAccessible(true);
617                sConstructorMap.put(name, constructor);
618            } else {
619                // If we have a filter, apply it to cached constructor
620                if (mFilter != null) {
621                    // Have we seen this name before?
622                    Boolean allowedState = mFilterMap.get(name);
623                    if (allowedState == null) {
624                        // New class -- remember whether it is allowed
625                        clazz = mContext.getClassLoader().loadClass(
626                                prefix != null ? (prefix + name) : name).asSubclass(View.class);
627
628                        boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
629                        mFilterMap.put(name, allowed);
630                        if (!allowed) {
631                            failNotAllowed(name, prefix, attrs);
632                        }
633                    } else if (allowedState.equals(Boolean.FALSE)) {
634                        failNotAllowed(name, prefix, attrs);
635                    }
636                }
637            }
638
639            Object lastContext = mConstructorArgs[0];
640            if (mConstructorArgs[0] == null) {
641                // Fill in the context if not already within inflation.
642                mConstructorArgs[0] = mContext;
643            }
644            Object[] args = mConstructorArgs;
645            args[1] = attrs;
646
647            final View view = constructor.newInstance(args);
648            if (view instanceof ViewStub) {
649                // Use the same context when inflating ViewStub later.
650                final ViewStub viewStub = (ViewStub) view;
651                viewStub.setLayoutInflater(cloneInContext((Context) args[0]));
652            }
653            mConstructorArgs[0] = lastContext;
654            return view;
680    }
681
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值