当前位置:网站首页>Graphic system - 1 Layout loading
Graphic system - 1 Layout loading
2022-06-28 18:25:00 【MrPeng1991】
be based on android10 To analyze android Graphics system
Graphics system ——1. Layout loading 
1. setContentView
public class MainActivity extends AppCompatActivity {
public static final String TAG = "_MainActivity_";
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// That's what we studied setContentView
setContentView(R.layout.activity_main);
mTv = findViewById(R.id.tv);
}
}
2 AppCompatActivity.java
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
@NonNull
public AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, this);
}
return mDelegate;
}
3 AppCompatDelegate.java
@NonNull
public static AppCompatDelegate create(@NonNull Activity activity,
@Nullable AppCompatCallback callback) {
return new AppCompatDelegateImpl(activity, callback);
}
public abstract void setContentView(@LayoutRes int resId);
4 AppCompatDelegateImpl.java
@Override
public void setContentView(int resId) {
// Make sure decorView and ContentView There is , If it doesn't exist, create it ---> The first stage
ensureSubDecor();
// You can see it android.R.id.content It's ours contentView Of id
ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
//contentView The view can only be filled after the root layout is cleared ----> The second stage
LayoutInflater.from(mContext).inflate(resId, contentParent);
mAppCompatWindowCallback.getWrapped().onContentChanged();
}
4.1 The first stage
private void ensureSubDecor() {
if (!mSubDecorInstalled) {
// Check your Appcompat Whether the attribute exists , Configure according to your theme properties Activity
mSubDecor = createSubDecor();
......
}
}
private ViewGroup createSubDecor() {
TypedArray a = mContext.obtainStyledAttributes(R.styleable.AppCompatTheme);
// The following sentence is too familiar , Every time we set the theme incorrectly or do not set the theme, we will report an error
if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) {
a.recycle();
throw new IllegalStateException(
"You need to use a Theme.AppCompat theme (or descendant) with this activity.");
}
// The following is to configure according to your theme properties Activity
if (a.getBoolean(R.styleable.AppCompatTheme_windowNoTitle, false)) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
} else if (a.getBoolean(R.styleable.AppCompatTheme_windowActionBar, false)) {
// Don't allow an action bar if there is no title.
requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR);
}
if (a.getBoolean(R.styleable.AppCompatTheme_windowActionBarOverlay, false)) {
requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR_OVERLAY);
}
if (a.getBoolean(R.styleable.AppCompatTheme_windowActionModeOverlay, false)) {
requestWindowFeature(FEATURE_ACTION_MODE_OVERLAY);
}
mIsFloating = a.getBoolean(R.styleable.AppCompatTheme_android_windowIsFloating, false);
a.recycle();
// The following two lines are important , It's about and Window The binding of
// So we need to know this first mWindow What is it ?
ensureWindow();
mWindow.getDecorView(); // The code is shown 4.3PhoneWindow.java
...
mWindow.setContentView(subDecor);// The code is shown 4.3PhoneWindow.java
.....
}
private void ensureWindow() {
...
if (mWindow == null && mHost instanceof Activity) {
//(Activity) mHost).getWindow() What the hell is it ?
attachToWindow(((Activity) mHost).getWindow());
}
...
}
private void attachToWindow(@NonNull Window window) {
...
// At present mWindow Is uniquely assigned here , The value is (Activity) mHost).getWindow()
mWindow = window;
}
//Activity.java
public Window getWindow() {
return mWindow;
}
//mWindow Where is it assigned ?
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, IBinder assistToken) {
...
attachBaseContext(context);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
// It will be mentioned later in this sentence
mWindow.getLayoutInflater().setPrivateFactory(this);
...
}
// there attach Where was the method called ? In fact, that is Activity Occurs during startup , Code in ActivityThread.java class
4.2 ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
// Notice the outerContext yes Activity
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken);
...
}
4.3 PhoneWindow.java
@Override
public final @NonNull View getDecorView() {
if (mDecor == null || mForceDecorInstall) {
installDecor();
}
return mDecor;
}
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
...
}
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
// Generate DecorView
mDecor = generateDecor(-1);
...
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
// Generate mContentParent
mContentParent = generateLayout(mDecor);
...
}
{
protected DecorView generateDecor(int featureId) {
...
// Explain a PhoneWindow Also create a DecorView
return new DecorView(context, featureId, this, getAttributes());
}
protected ViewGroup generateLayout(DecorView decor) {
...
// Find the ID_ANDROID_CONTENT Control
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
...
return contentParent;
}
4.2 The second stage
@Override
public void setContentView(int resId) {
// Make sure decorView and ContentView There is , If it doesn't exist, create it ---> The first stage
ensureSubDecor();
// You can see it android.R.id.content It's ours contentView Of id
ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
// In fact, this is equivalent to PhoneWindow Expose an object to fill view Class using
//contentView The view can only be filled after the root layout is cleared ----> The second stage
LayoutInflater.from(mContext).inflate(resId, contentParent);
mAppCompatWindowCallback.getWrapped().onContentChanged();
}
4.3 LayoutInflater.java
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) {
....
// Start parsing what we wrote XML The file
XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
....
}
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
...
// First go to root node
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
// Analyzers view
rInflateChildren(parser, temp, attrs, true);
// Add all nodes to view on the tree
if (root != null && attachToRoot) {
root.addView(temp, params);
}
}
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) {
...
// The parent class is AppcompatActivity according to view name new An object comes out .
View view = tryCreateView(parent, name, context, attrs);
// The parent class is Activity Or customized View Then reflection generates a view
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;
}
}
...
}
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);
}
// A face of meng mFactory2 What is it? ?mFactor What is it? ?mPrivateFactor What is it again? ?
// First of all mFactory2 Try loading view, If mFactory2 Use only when it is empty mFactory load
// If both are empty or both are created view It's all empty , Will try to make mPrivateFactory Create
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) {
// 4.1 Activity.java mWindow.getLayoutInflater().setPrivateFactory(this);
// mPrivateFactory In fact, that is Activity, So here is the call Activity Of onCreateView
view = mPrivateFactory.onCreateView(parent, name, context, attrs);
}
return view;
}
4.4 Activity.java —> mPrivateFactory
@Nullable
public View onCreateView(@Nullable View parent, @NonNull String name,
@NonNull Context context, @NonNull AttributeSet attrs) {
if (!"fragment".equals(name)) {
// This name Namely view Name , What we usually declare is TextView/Button wait
return onCreateView(name, context, attrs);
}
// So we know why we use <fragment> instead of <Fragment> establish fragment Node
// Only fragment Will be detected , Generate fragments through the fragment controller
return mFragments.onCreateView(parent, name, context, attrs);
}
@Nullable
public View onCreateView(@NonNull String name, @NonNull Context context,
@NonNull AttributeSet attrs) {
//Activity Only responsible for fragment The creation of , other view No matter
return null;
}
// Here you go mPrivateFactory Finished. , Let's look at the other two mFactory and mFactory2
4.5 LayoutInflater.java
// First find out where these variables are defined
@UnsupportedAppUsage
private Factory mFactory;
@UnsupportedAppUsage
private Factory2 mFactory2;
// Query the operation of assignment , There are three
protected LayoutInflater(LayoutInflater original, Context newContext) {
...
mFactory = original.mFactory;
mFactory2 = original.mFactory2;
mPrivateFactory = original.mPrivateFactory;
...
}
public void setFactory(Factory factory) {
...
mFactorySet = true;
if (mFactory == null) {
mFactory = factory;
} else {
mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
}
}
// Look for places to call this method layer by layer , Then the logic is reversed The call chain changes from order to reverse order
public void setFactory2(Factory2 factory) {
...
mFactorySet = true;
if (mFactory == null) {
mFactory = mFactory2 = factory;
} else {
mFactory = mFactory2 = new FactoryMerger(factory, factory, mFactory, mFactory2);
}
}
4.6 LayoutInflaterCompat.java
public static void setFactory2(
@NonNull LayoutInflater inflater, @NonNull LayoutInflater.Factory2 factory) {
inflater.setFactory2(factory);
if (Build.VERSION.SDK_INT < 21) {
final LayoutInflater.Factory f = inflater.getFactory();
if (f instanceof LayoutInflater.Factory2) {
// The merged factory is now set to getFactory(), but not getFactory2() (pre-v21).
// We will now try and force set the merged factory to mFactory2
forceSetFactory2(inflater, (LayoutInflater.Factory2) f);
} else {
// Else, we will force set the original wrapped Factory2
forceSetFactory2(inflater, factory);
}
}
}
4.7 AppCompatDelegateImpl.java
@Override
public void installViewFactory() {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
if (layoutInflater.getFactory() == null) {
// Parameters passed this, explain mFactory2 Namely AppCompatDelegateImpl example
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");
}
}
}
4.8 AppCompatActivity.java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
final AppCompatDelegate delegate = getDelegate();
// Do it here installViewFactory
delegate.installViewFactory();
delegate.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
4.9 MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
// The parent class performs the registration mFatory2 The job of
super.onCreate(savedInstanceState);
}
Now we have a little bit of certainty ,mFactory2 stay MainActivity.java Medium super.onCreate(savedInstanceState) You get the initialization .mFactory2 Namely AppCompatDelegateImpl Instantiate objects , Let's go back to 4.4 LayoutInflater.java Continue analysis in the code
边栏推荐
- The MySQL installed in Alibaba cloud server is version 8. Is it because the MySQL driver version of dataworks does not support it? Now mention
- konva系列教程3:自定义图形
- 7-user input and while loop
- An error is reported when ActiveMQ is started. The 1883 port occupation problem is solved
- Introduction to kubernetes resource object and common commands
- Detailed explanation of select in golang (forward)
- JQ plug-in analysis
- The fourth largest operator cannot be a "catfish"
- Ding! Techo day Tencent technology open day arrived as scheduled!
- 使用Pega进行一个简单的RPA程序开发
猜你喜欢

China gaobang brand story: standing guard for safety, gaobang pays attention to

kubeadm创建kubernetes集群

Analysis of response parsing process of SAP ui5 batch request

2022年化工自动化控制仪表考试模拟100题模拟考试平台操作

Le test de reconnaissance faciale comporte - t - il des préoccupations en matière de protection de la vie privée? Une entreprise étrangère a été arrêtée en cas d'urgence

CORBA 架构体系指南(通用对象请求代理体系架构)

Node foundation ~ node level

Database mysql statement final review CTGU

Kubeadm create kubernetes cluster

MySQL十种锁,一篇文章带你全解析
随机推荐
单片机修改网络硬件驱动(phy芯片更换)
The fourth largest operator cannot be a "catfish"
如何设计业务高性能高可用计算架构 - 作业
堆的概念和代码实现
Small program graduation design based on wechat driving school examination small program graduation design opening report function reference
oracle cdc 但是使用的服务名没有sid 该怎么配置呢?
第2章 处理文件、摄像头和图形用户界面cameo应用
Ask the bosses why the number type of Oracle CDC becomes a string when printed out. How can it be converted back?
Analysis of response parsing process of SAP ui5 batch request
Why insert is configured with'select last_ INSERT_ What if id() 'returns 0?
Kubernetes visual interface dashboard
6 - Dictionary
抓包整理外篇fiddler————了解工具栏[一]
华为云AOM发布2.0版本,3大特性亮相
[cloud resident co creation] shengteng heterogeneous computing architecture cann helps release the surging computing power of hardware
Does face recognition test involve privacy and security issues? A foreign company was urgently stopped
Introduction to kubernetes resource object and common commands
io模型初探
Three communication skills in software testing
June 27, 2022 to July 3, 2022 (UE4 video tutorial)