Android基础知识(一)------Context

Context

1.context是一个抽象类,定义了一些枚举和获取资源方法

继承关系如下:

     Context --> ContextImpl
        |            |
        v            |
  ContextWrapper<-----
        |
        -----------------------------------------------
        |                   |                       |
        v                   v                       v
    Application            Service          ContextThemeWrapper
                                                    |
                                                    v
                                                Activity

ContextThemeWrapper与ContextWrapper的区别:
在于为Activity加载定义的Theme中的样式,Application和Service都不需要界面上的展示

2.如何保证访问资源的唯一性?

我们直接来看ContextImpl中的源码

private ContextImpl(ContextImpl container, ActivityThread mainThread,
        LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
        Display display, Configuration overrideConfiguration, int createDisplayWithId) {
    mOuterContext = this;

    ......

    mPackageInfo = packageInfo;
    mResourcesManager = ResourcesManager.getInstance();

    .....

    Resources resources = packageInfo.getResources(mainThread);
    if (resources != null) {
        if (displayId != Display.DEFAULT_DISPLAY
                || overrideConfiguration != null
                || (compatInfo != null && compatInfo.applicationScale
                        != resources.getCompatibilityInfo().applicationScale)) {

            if (container != null) {
                // This is a nested Context, so it can't be a base Activity context.
                // Just create a regular Resources object associated with the Activity.
                resources = mResourcesManager.getResources(
                        activityToken,
                        packageInfo.getResDir(),
                        packageInfo.getSplitResDirs(),
                        packageInfo.getOverlayDirs(),
                        packageInfo.getApplicationInfo().sharedLibraryFiles,
                        displayId,
                        overrideConfiguration,
                        compatInfo,
                        packageInfo.getClassLoader());
            } else {
                // This is not a nested Context, so it must be the root Activity context.
                // All other nested Contexts will inherit the configuration set here.
                resources = mResourcesManager.createBaseActivityResources(
                        activityToken,
                        packageInfo.getResDir(),
                        packageInfo.getSplitResDirs(),
                        packageInfo.getOverlayDirs(),
                        packageInfo.getApplicationInfo().sharedLibraryFiles,
                        displayId,
                        overrideConfiguration,
                        compatInfo,
                        packageInfo.getClassLoader());
            }
        }
    }
    mResources = resources;

    .....
}

首先一个应用只有唯一的mPackageInfo这个能够保证,mResourcesManager是取的一个单例。

3.单例模式的正确运用

在一个需要使用context来初始化的单例中,我们需要在获取单例是传入context。
我们已有的只是告诉我们,持有activity的context在activity销毁之后会造成内存泄漏,且单例一般如工具类都需要做到与应用的生命周期相同,所以我们可以直接使用Application的context来进行初始化。

public class Singleton {
  private static volatile Singleton instance = null;

  private Context mContext;

  public Singleton(Context context) {
      this.mContext = context;
  }

  public Singleton getInstance(Context context) {
     if (instance == null) {
            synchronized (Singleton.class) {
               if (instance == null) {
                   instance = new Singleton(context.getApplicationContext());
              }
           }
       }
       return instance;
 }
}

从代码中可以看到,用context的getApplicationContext()来保证我们使用的只会是Application的Context。

4.如果用Application的context是否可以启动一个activity,会出现什么异常情况?

我们直接尝试利用Application的Context来启动Activity,跟网上说的会报异常或者创建在新的任务中的结论不符啊,有大神看到麻烦指点下。
--!

5.如果用Application的context是否可以inflateLayout,会出现什么异常情况?

由于Activity是继承于ContextThemeWrapper,所以用Activity的Context创建的View或者Dialog等会带有自定义的Theme,若使用Service或者Application的Context则会使用系统默认的样式。

6.避免将context用来创建static变量

网上的一个例子:

private static Drawable sDrawable;
sDrawable = context.getDrawable(R.mipmap.ic_launcher);

将一个静态变量drawable用context(假设为Activity的context)进行初始化,由于被静态变量所持有,会导致内存泄漏问题。

tips

不要让比context生命周期长的对象持有该context,如在Activity中使用presenter的问题,必须要进行相应的解决。

参考

Android Context 熟悉还是陌生?

Android基础之Context

Android应用Context详解及源码解析

你可能感兴趣的:(Android基础知识(一)------Context)