Android Context类

Context及其子类:

这个家族一共有7个类:

Context就像应用程序的大管家,可以启动activity和service、调用资源和系统服务等。activity和application和service最终都继承context,所以APP内共有Context的数量为: Activity数量+Service数量+1个Application内的Context 

Context源码:

public abstract class Context {

  // 1,四大组件的交互:启动activity,发送广播,注册服务,获取ContentResolver
  public abstract void startActivity(@RequiresPermission Intent intent);
  public abstract void sendBroadcast(@RequiresPermission Intent intent);
  public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,
                                          IntentFilter filter);
  public abstract void unregisterReceiver(BroadcastReceiver receiver);
  public abstract ComponentName startService(Intent service);
  public abstract boolean stopService(Intent service);
  public abstract boolean bindService(@RequiresPermission Intent service,
                                      @NonNull ServiceConnection conn, @BindServiceFlags int flags);
  public abstract void unbindService(@NonNull ServiceConnection conn);
  public abstract ContentResolver getContentResolver();

  // 2,获取系统/应用资源:包括AssetManager、Resources、PackageManager、ClassLoader、一些文件等
  public abstract AssetManager getAssets();
  public abstract Resources getResources();
  public abstract PackageManager getPackageManager();
  public abstract Context getApplicationContext();
  public abstract ClassLoader getClassLoader();
  public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) { ... }

  public final String getString(@StringRes int resId) { ... }
  public final int getColor(@ColorRes int id) { ... }
  public final Drawable getDrawable(@DrawableRes int id) { ... }
  public abstract Resources.Theme getTheme();
  public abstract void setTheme(@StyleRes int resid);
  public final TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) { ... }

  // 3,获取应用相关信息
  public abstract ApplicationInfo getApplicationInfo();
  public abstract String getPackageName();
  public abstract Looper getMainLooper();
  public abstract int checkPermission(@NonNull String permission, int pid, int uid);

  // 4,获取缓存文件
  public abstract File getSharedPreferencesPath(String name);
  public abstract File getDataDir();
  public abstract boolean deleteFile(String name);
  public abstract File getExternalFilesDir(@Nullable String type);
  public abstract File getCacheDir();
    ...
  public abstract SharedPreferences getSharedPreferences(String name, @PreferencesMode int mode);
  public abstract boolean deleteSharedPreferences(String name);

  // 5,数据库相关
  public abstract SQLiteDatabase openOrCreateDatabase(...);
  public abstract boolean deleteDatabase(String name);
  public abstract File getDatabasePath(String name);
    ...

  // 其它,如监听配置信息改变、内存不足等
  public void registerComponentCallbacks(ComponentCallbacks callback) { ... }
  public void unregisterComponentCallbacks(ComponentCallbacks callback) { ... }
    ...
}

public interface ComponentCallbacks {
  void onConfigurationChanged(Configuration newConfig);
  void onLowMemory();
}
ContextWrapper源码:这是一个装饰类,这儿运用到了装饰者模式,ContextWrapper和它的子类都是装饰者,ContextImpl是被装饰者。
public class ContextWrapper extends Context {
    //竟然只有这一个成员,看来是相当重要了,记住mBase,mBase,mBase,重要的事儿说三遍
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
        
    //重要:注意这个方法,ContextWrapper就是通过这个方法将ContextImpl对象赋值给mBase成员变量的
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    //得到的是mBase
    public Context getBaseContext() {
        return mBase;
    }
    //看,下面的方法都是通过mBase来执行的,所以这是个代理类
    @Override
    public AssetManager getAssets() {
        return mBase.getAssets();
    }

    @Override
    public Resources getResources() {
        return mBase.getResources();
    }

    @Override
    public PackageManager getPackageManager() {
        return mBase.getPackageManager();
    }

    @Override
    public ContentResolver getContentResolver() {
        return mBase.getContentResolver();
    }

    @Override
    public Looper getMainLooper() {
        return mBase.getMainLooper();
    }

    @Override
    public Executor getMainExecutor() {
        return mBase.getMainExecutor();
    }

    //常常用的方法,getApplicationContext方法是在ContextWrapper类实现的,但最终是在ContextImpl实现的
    @Override
    public Context getApplicationContext() {
        return mBase.getApplicationContext();
    }

    @Override
    public Resources.Theme getTheme() {
        return mBase.getTheme();
    }

    @Override
    public ClassLoader getClassLoader() {
        return mBase.getClassLoader();
    }

    @Override
    public String getPackageName() {
        return mBase.getPackageName();
    }

    @Override
    public ApplicationInfo getApplicationInfo() {
        return mBase.getApplicationInfo();
    }

    @Override
    public String getPackageCodePath() {
        return mBase.getPackageCodePath();
    }

    @Override
    public SharedPreferences getSharedPreferences(String name, int mode) {
        return mBase.getSharedPreferences(name, mode);
    }
    ...
}

ContextThemeWrapper源码:可以看出,相比ContextWrapper,虽然都是Context的代理类,但ContextThemeWrapper有自己的Resource和Theme成员,并且可以通过构造函数初始化自己的Resource和Theme,也就是说,ContextThemeWrapper和它的mBase成员在Resource和Theme相关的行为上是不同的。

public class ContextThemeWrapper extends ContextWrapper {
    private int mThemeResource;
    private Resources.Theme mTheme;
    private LayoutInflater mInflater;
    private Configuration mOverrideConfiguration;
    private Resources mResources;

    public ContextThemeWrapper() {
        super(null);
    }

    public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
        super(base);
        mThemeResource = themeResId;
    }

    public ContextThemeWrapper(Context base, Resources.Theme theme) {
        super(base);
        mTheme = theme;
    }

    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);
    }

    public void applyOverrideConfiguration(Configuration overrideConfiguration) {
        if (mResources != null) {
            throw new IllegalStateException(
                    "getResources() or getAssets() has already been called");
        }
        if (mOverrideConfiguration != null) {
            throw new IllegalStateException("Override configuration has already been set");
        }
        mOverrideConfiguration = new Configuration(overrideConfiguration);
    }

    public Configuration getOverrideConfiguration() {
        return mOverrideConfiguration;
    }

    @Override
    public AssetManager getAssets() {
        // Ensure we're returning assets with the correct configuration.
        return getResourcesInternal().getAssets();
    }

    @Override
    public Resources getResources() {
        return getResourcesInternal();
    }

    private Resources getResourcesInternal() {
        if (mResources == null) {
            if (mOverrideConfiguration == null) {
                mResources = super.getResources();
            } else {
                final Context resContext = createConfigurationContext(mOverrideConfiguration);
                mResources = resContext.getResources();
            }
        }
        return mResources;
    }

    @Override
    public void setTheme(int resid) {
        if (mThemeResource != resid) {
            mThemeResource = resid;
            initializeTheme();
        }
    }

    @Override
    public int getThemeResId() {
        return mThemeResource;
    }

    @Override
    public Resources.Theme getTheme() {
        if (mTheme != null) {
            return mTheme;
        }

        mThemeResource = Resources.selectDefaultTheme(mThemeResource,
                getApplicationInfo().targetSdkVersion);
        initializeTheme();

        return mTheme;
    }

    @Override
    public Object getSystemService(String name) {
        if (LAYOUT_INFLATER_SERVICE.equals(name)) {
            if (mInflater == null) {
                mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
            }
            return mInflater;
        }
        return getBaseContext().getSystemService(name);
    }

    protected void onApplyThemeResource(Resources.Theme theme, int resId, boolean first) {
        theme.applyStyle(resId, true);
    }

    private void initializeTheme() {
        final boolean first = mTheme == null;
        if (first) {
            mTheme = getResources().newTheme();
            final Resources.Theme theme = getBaseContext().getTheme();
            if (theme != null) {
                mTheme.setTo(theme);
            }
        }
        onApplyThemeResource(mTheme, mThemeResource, first);
    }
}

ContextImpl源码:这是Context的主要实现类,可以用于创建Activity、Service和Application的mBase成员,即ContextWrapper和ContextThemeWrapper代理的是ContextImpl对象本身;

而且ContextImpl相比ContextThemeWrapper没有Configuration对象,在ContextThemeWrapper类中,Resource是根据Configuration对象初始化的;

还可以看出Service和Application使用同一个Resource,和Activity使用的不同。

class ContextImpl extends Context {
    //整个App的主线程
    final ActivityThread mMainThread;
    //整个App的相关信息
    final LoadedApk mPackageInfo;
    //资源解析器
    private final ResourcesManager mResourcesManager;
    //App资源类
    private final Resources mResources;
    //外部Context的引用
    private Context mOuterContext;
    //默认主题
    private int mThemeResource = 0;
    private Resources.Theme mTheme = null;
    //包管理器
    private PackageManager mPackageManager;

    
    // 用于创建 Activity Context
    static ContextImpl createActivityContext(...) {
        ContextImpl context = new ContextImpl(...);
        context.setResources(resourcesManager.createBaseActivityResources(...));
        return context;
    }
    
    // 用于创建 Application Context、Service Context
    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        ContextImpl context = new ContextImpl(...);
        context.setResources(packageInfo.getResources());
        return context;
    }
    
    private static Resources createResources(...) {
        return ResourcesManager.getInstance().getResources(...);
    }

    //启动Activity的地方
     @Override
     public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
            getOuterContext(), mMainThread.getApplicationThread(), null,
            (Activity)null, intent, -1, options);
    }



    //看,特熟悉的getApplicationContext,最终就是在这儿实现的,不管是哪个方法,最后都是返回的都是当前应用的Application对象
    //另外Activity类中的getApplication()方法返回的也是当前应用的Application对象,只是返回值类型不同而已
    @Override
    public Context getApplicationContext() {
        return (mPackageInfo != null) ?
                mPackageInfo.getApplication() : mMainThread.getApplication();
    }


    // ContextThemeWrapper 没有重写父类的 setResources
    // 因此会调用 mBase 的 setResources,即和 ContextImpl 的行为一样
    void setResources(Resources r) {
        if (r instanceof CompatResources) {
            ((CompatResources) r).setContext(this);
        }
        mResources = r;
    }
    
    @Override
    public Resources getResources() {
        return mResources;
    }
    
    
    /* ---------- 主题相关 ------------ */
    
    @Override
    public void setTheme(int resId) {
        synchronized (mSync) {
            if (mThemeResource != resId) {
                mThemeResource = resId;
                initializeTheme();
            }
        }
    }
    
    // 直接创建一个 Themem 对象,相比 ContextThemeWrapper,少了一部分内容
    private void initializeTheme() {
        if (mTheme == null) {
            mTheme = mResources.newTheme();
        }
        mTheme.applyStyle(mThemeResource, true);
    }

    @Override
    public Resources.Theme getTheme() {
        synchronized (mSync) {
            // 和 ContextThemeWrapper 基本一样
            if (mTheme != null) {
                return mTheme;
            }

            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
                    getOuterContext().getApplicationInfo().targetSdkVersion);
            initializeTheme();

            return mTheme;
        }
    }

}

未完待续。。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值