辉夜的博客

繁花似锦,辉夜如昼

0%

Android学习笔记(四)

Context

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

正常设置UI时的Context

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//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时会设置这个字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 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,并通过他访问应用的启动图标,然后呈现在内容页

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

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