首先这里的源码是sdk 29 的也就是Android 10.0的代码,其实和其他的版本区别不大
Inflater 方法的区别
View.inflate(this,R.layout.activity_main,null);
LayoutInflater.from(this).inflate(R.layout.activity_main,null,false);
View.inflate(this,R.layout.activity_main,null);方法里面也是调用LayoutInflater.from(this).inflate(),所以本质还是LayoutInflater.from(this).inflate()这个方法
从LayoutInflater.from()开始
LayoutInflater.from(this)
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;
}
这里的getSystemService()是一个抽象方法,需要找到context的具体实现对象
这里context的实现类是ContextImpl类
看一下UML时序图 
最终走到SystemServiceRegister的getSystemService()方法中
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
SYSTEM_SERVICE_FETCHERS本质是一个ArrayMap,用来存储系统注册的服务
在这里要获取的是Context.LAYOUT_INFLATER_SERVICE这个服务,通过这个服务来获取View
inflate()
观看下面源码解析的时候先看一下时序图 
class LayoutInflater
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) + ")");
    }
    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();
    }
}
XmlResourceParser parser = res.getLayout(resource)这个是解析器,用于解析xml
关键在inflate(parser, root, attachToRoot);
tryCreateView()
class LayoutInflater
public final View tryCreateView(@Nullable View parent, @NonNull String name,
    @NonNull Context context,
    @NonNull AttributeSet attrs) {
    if (name.equals(TAG_1995)) {
        // Let's party like it's 1995!
        return new BlinkLayout(context, attrs);
    }
    View view;
    if (mFactory2 != null) {
        view = mFactory2.onCreateView(parent, name, context, attrs);
    } else if (mFactory != null) {
        view = mFactory.onCreateView(name, context, attrs);
    } else {
        view = null;
    }
    if (view == null && mPrivateFactory != null) {
        view = mPrivateFactory.onCreateView(parent, name, context, attrs);
    }
    return view;
}
这里会判断mFactory2、mFactory、mPrivateFactory是否为空,不为空就调用相应的onCreateView()方法。
回到createViewFromTag()方法观看下面,
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
       ....
        try {
            View view = tryCreateView(parent, name, context, attrs);
            if (view == null) {
                final Object lastContext = mConstructorArgs[0];
                mConstructorArgs[0] = context;
                try {
                    if (-1 == name.indexOf('.')) {
                        view = onCreateView(context, parent, name, attrs);
                    } else {
                        view = createView(context, name, null, attrs);
                    }
                } finally {
                    mConstructorArgs[0] = lastContext;
                }
            }
            return view;
            ....
    }
当mFactory2、mFactory、mPrivateFactory为空,那么view也是null,那么会用自己的onCreateView()方法,注意这里的if(-1 == name.indexOf('.'))
name是使用xml解析工具解析xml文件获取到的属性,这个是判断有没有自己定义的控件如com.example.TestText这种自己定义的控件,那么就调用相应的创建方法。
好,回到上面tryCreateView()方法中,这个mFactory什么时候被赋值,在哪里赋值?
经过一番最终和查找,发现在AppCompatActivity中的OnCreate() 中有一个delegate.installViewFactory();方法,点进去就是在 AppCompatDelegateImpl类中 installViewFactory() 方法中将Factory赋值
赋值Factory
class AppCompatDelegateImpl
public void installViewFactory() {
    LayoutInflater layoutInflater = LayoutInflater.from(mContext);
    if (layoutInflater.getFactory() == null) {
        LayoutInflaterCompat.setFactory2(layoutInflater, this);
    } else {
        if (!(layoutInflater.getFactory2() instanceof AppCompatDelegateImpl)) {
            Log.i(TAG, "The Activity's LayoutInflater already has a Factory installed"
                    + " so we can not install AppCompat's");
        }
    }
}
LayoutInflaterCompat.setFactory2(layoutInflater, this);将自己传入进去,那么LayoutInflate类走的onCreateView()方法就是LayoutInflaterCompat.onCreateView() 继续往下走就是走的**AppCompatViewInflater.onCreate()**方法,然后我们可以看到
class AppCompatViewInflater
final View createView(View parent, final String name, @NonNull Context context,
        @NonNull AttributeSet attrs, boolean inheritContext,
        boolean readAndroidTheme, boolean readAppTheme, boolean wrapContext) {
    final Context originalContext = context;
    // We can emulate Lollipop's android:theme attribute propagating down the view hierarchy
    // by using the parent's context
    if (inheritContext && parent != null) {
        context = parent.getContext();
    }
    if (readAndroidTheme || readAppTheme) {
        // We then apply the theme on the context, if specified
        context = themifyContext(context, attrs, readAndroidTheme, readAppTheme);
    }
    if (wrapContext) {
        context = TintContextWrapper.wrap(context);
    }
    View view = null;
    // We need to 'inject' our tint aware Views in place of the standard framework versions
    switch (name) {
        case "TextView":
            view = createTextView(context, attrs);
            verifyNotNull(view, name);
            break;
        case "ImageView":
            view = createImageView(context, attrs);
            verifyNotNull(view, name);
            break;
        case "Button":
            view = createButton(context, attrs);
            verifyNotNull(view, name);
            break;
            ....
        default:
            // The fallback that allows extending class to take over view inflation
            // for other tags. Note that we don't check that the result is not-null.
            // That allows the custom inflater path to fall back on the default one
            // later in this method.
            view = createView(context, name, attrs);
    }
    if (view == null && originalContext != context) {
        // If the original context does not equal our themed context, then we need to manually
        // inflate it using the name so that android:theme takes effect.
        view = createViewFromTag(context, name, attrs);
    }
    if (view != null) {
        // If we have created a view, check its android:onClick
        checkOnClickListener(view, attrs);
    }
    return view;
}
这里会看一下解析出来的属性有没有Button、TextView、ImageView等等,有的话就会为我们创建相应的View, view = createViewFromTag(context, name, attrs);这一行是用来处理那一些自定义View,通过反射将对象new出来。跟上面一样。
这样AppCompatViewInflater就对View的创建进行了拦截。这个就是View的Inflater加载大概过程。
自己拦截View的创建
看了上面的源码,我们可以尝试一下自己来进行拦截View的创建,尝试拦截View将所有Button变成TextView
public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        LayoutInflater layoutInflater = LayoutInflater.from(this);
        LayoutInflaterCompat.setFactory(layoutInflater,new LayoutInflaterFactory(){
            @Override
            public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
                Log.d("TAG","拦截view的创建");
                if(name.equals("Button")){
                    TextView tv = new TextView(BaseActivity.this);
                    tv.setText("拦截");
                    return tv;
                }
                return null;
            }
        });
        super.onCreate(savedInstanceState);
        ....
    }
}





























