Context和UI渲染 | 青训营笔记

89 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第6天 今天的内容是Context和UI渲染

Context

Context是一个控制全局资源的抽象类,由Android系统负责具体实现。各个组件都需要利用Context才能访问res中的字符串,图片等资源。同时一些应用级功能也要通过Context实现

正常设置UI时的Context

正常设置UI是使用setContentView(R.layout.activity_main),这个函数会调用getDelegate().setContentView(layoutResID);递归地查找并且生成定义在xml中的各个View:

//in AppCompatActivity.java
public void setContentView(@LayoutRes int layoutResID) {
    initViewTreeOwners();
    //调用了Activity的Delegate的同名方法,设置了mDelegate.mContext
    getDelegate().setContentView(layoutResID);
}

//in AppCompatDelegate.java
@Override
public void setContentView(int resId) {
    ensureSubDecor();
    ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);
    contentParent.removeAllViews();
    /*这一句会触发后续的递归查找*/
    LayoutInflater.from(mContext).inflate(resId, contentParent);
    mAppCompatWindowCallback.getWrapped().onContentChanged();
}

在这个过程中AppCompactDelegat类带有一个字段mContext,这个字段用在了解析xml度过程中。可以看到,调用getDelegate时会设置这个字段

/**
 * Return The AppCompatDelegate being used by this Activity.
 */
@NonNull
public AppCompatDelegate getDelegate() {
    if (mDelegate == null) {
        mDelegate = AppCompatDelegate.create(this, this);
    }
    return mDelegate;
}

//in AppCompatDelegate.java(抽象类)
public static AppCompatDelegate create(@NonNull Activity activity, 
@Nullable AppCompatCallback callback) {
    return new AppCompatDelegateImpl(activity, callback);
}

//in AppCompatDelegateImpl.java(实现)
AppCompatDelegateImpl(Activity activity, AppCompatCallback callback) {
    //调用另一个构造器
    this(activity, null, callback, activity);
}

//in AppCompatDelegateImpl.java
private AppCompatDelegateImpl(Context context, Window window, AppCompatCallback callback,
            Object host) {
    mContext = context;
    mAppCompatCallback = callback;
    mHost = host;
    ...
}

我们可以发现Activity本身就是mDelegate的context和callback。事实上Activity隔着漫长的继承链继承了Context类。 正是因为有了Context,这个解析过程在能够把id和xml中的内容联系起来。

直接使用View

这里以imageview为例,通常我们都是在xml中定义的View组件,这样它们就会在上述的一系列过程中被加载出来,最后作为一整个activity呈现。 如果单独定义iv,就要显式指定Context,这里我们仍然用activity作为context,并通过他访问应用的启动图标,然后呈现在内容页

    ImageView iv = new ImageView(this);
    iv.setImageResource(R.mipmap.ic_launcher);
    setContentView(iv);

在这里,同样是通过Context才能用R文件中的int常量直接找到图片。

总结

Context是存放了R文件中值与View对象的映射关系的一个类,最常用的Context就是activity本身。