美文网首页
Android基础知识(一)------Context

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

作者: C调路过 | 来源:发表于2017-06-22 16:58 被阅读0次

    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

          本文链接:https://www.haomeiwen.com/subject/sdvfcxtx.html