Android幾種inflate的方式

前言

Android中幾種inflate的方法大家可能都已經(jīng)很熟悉了,但是這幾種方式到底有什么區(qū)別,讓我們一起來(lái)看下。

方式一:

View.inflate(Context context, @LayoutRes int resource, ViewGroup root)

方式二:

LayoutInflater inflater = LayoutInflater.from(Context context);
inflater.inflate(@LayoutRes int resource, @Nullable ViewGroup root)

方式三:

LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(@LayoutRes int resource, @Nullable ViewGroup root)

方式四:(Activity中)

LayoutInflater inflater = getLayoutInflater();
inflater.inflate(@LayoutRes int resource, @Nullable ViewGroup root)

先讓我們看下幾種獲取LayoutInflater的方式的區(qū)別

    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
        LayoutInflater factory = LayoutInflater.from(context);
        return factory.inflate(resource, root);
    }

可以看到在View的inflate方法中直接就調(diào)用了LayoutInflater.from(Context context)的方式生成LayoutInflater,
那么LayoutInflater.from(Context context)做了什么。

    public static LayoutInflater from(Context context) {
        LayoutInflater LayoutInflater =
                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (LayoutInflater == null) {
            throw new AssertionError("LayoutInflater not found.");
        }
        return LayoutInflater;
    }

結(jié)果發(fā)現(xiàn)就是方式三,是不是有種被欺騙的感覺(jué)...好吧,那么第四種是怎么回事呢。

    public LayoutInflater getLayoutInflater() {
        return getWindow().getLayoutInflater();
    }

調(diào)用了Window的getLayoutInflater方法,那么看下這個(gè)Window是什么東西。

    public Window getWindow() {
        return mWindow;
    }
final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        ...
        ...
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        ...
        ...
    }

可以看到在Activity attach方法中mWindow指向了PhoneWindow,看下PhoneWindow的getLayoutInflater方法。

    @Override
    public LayoutInflater getLayoutInflater() {
        return mLayoutInflater;
    }
    public PhoneWindow(Context context) {
        super(context);
        mLayoutInflater = LayoutInflater.from(context);
    }

最終還是調(diào)用了LayoutInflater.from(context)方法,又陷入了循環(huán)中...所以這幾種方式獲取的LayoutInflater是一樣的,既然是一樣的,我們下面就直接看它的inflate方法,傳不同的參數(shù)會(huì)有什么不同。

   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();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }

        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }

可以看到兩個(gè)參數(shù)的方法會(huì)調(diào)用三個(gè)參數(shù)的方法,attachToRoot 的值為:root != null,我們直接看 return inflate(parser, root, attachToRoot);方法做了什么。

    public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
      ...
      ...
              View result = root;
      ...
      ...
                    // Temp is the root view that was found in the xml
                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);

                    ViewGroup.LayoutParams params = null;

                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            temp.setLayoutParams(params);
                        }
                    }
      ...
      ...
                    // We are supposed to attach all the views we found (int temp)
                    // to root. Do that now.
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }

                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }
      ...
      ...
              return result;
    }

createViewFromTag方法就是吧layout布局變成了view,但是另外兩個(gè)參數(shù)會(huì)影響最終生成的view,當(dāng)root != null并且
attachToRoot為false的時(shí)候,可以看到view調(diào)用了setLayoutParams方法,而這個(gè)params是通過(guò)root.generateLayoutParams獲取到的,也就是說(shuō)root的LayoutParams會(huì)影響view,root != null && attachToRoot的時(shí)候把view添加到了root里面,這就好解釋為什么上面要給view設(shè)置root的LayoutParams了,我們直接在java代碼中創(chuàng)建控件的時(shí)候,給它設(shè)置LayoutParams時(shí)都要考慮它的父布局是什么類型,比如LinearLayout就要?jiǎng)?chuàng)建LinearLayout.LayoutParams。

總結(jié)

幾種方式最終生成view的狀態(tài)與root和attachToRoot有關(guān):
root!=null時(shí):
? ? attachToRoot==true:
? ? 最終返回root,layout生成的view會(huì)被添加到root中。
? ? attachToRoot==false:
? ? 最終返回layout生成的view,但是view會(huì)被root的LayoutParams影響。
root==null時(shí):
? ? 最終返回layout生成的view,不會(huì)被其他東西影響。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容