关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android中Context用法详解

    Android中Context用法详解

    2014-08-09 00:00:00 出处:ITJS
    分享

    本文我们一起来探讨一下关于Android中Context的作用以及Context的详细用法,这对我们学习Android的资源访问有很大的帮助,文章中也贴出了一些关于Android Context使用的示例代码,非常不错,以下是原文:

    Context基本概念

    Context是什么

    1) Context是一个抽象类,其通用实现在ContextImpl类中。

    2) Context:是一个访问application环境全局信息的接口,通过它可以访问application的资源和相关的类,其主要功能如下:

    启动Activity
    启动和停止Service
    发送广播消息(Intent)
    注册广播消息(Intent)接收者
    可以访问APK中各种资源(如Resources和AssetManager等)
    可以访问Package的相关信息
    APK的各种权限管理

    从以上分析可以看出,Context就是一个对APK包无所不知的大管家,大家需要什么,直接问它就可以了。

    Context与View的关系

    View与Context(或Activity)的关系类似于明星与经纪人的关系,所以创建View时,必须明确指定其Context(即经纪人或大管家),否则View就成不了明星。

    Context家族关系

    Context关键函数

    public abstract class Context {
    
    // 获取应用程序包的AssetManager实例
    public abstract AssetManager getAssets();
    
    // 获取应用程序包的Resources实例
    public abstract Resources getResources();
    
    // 获取PackageManager实例,以查看全局package信息
    public abstract PackageManager getPackageManager();
    
    // 获取应用程序包的ContentResolver实例
    public abstract ContentResolver getContentResolver();
    
    // 它返回当前进程的主线程的Looper,此线程分发调用给应用组件(activities, services等)
    public abstract Looper getMainLooper();
    
    // 返回当前进程的单实例全局Application对象的Context
    public abstract Context getApplicationContext();
    
    // 从string表中获取本地化的、格式化的字符序列
    public final CharSequence getText(int resId) {
    return getResources().getText(resId);
    }
    
    // 从string表中获取本地化的字符串
    public final String getString(int resId) {
    return getResources().getString(resId);
    }
    
    public final String getString(int resId, Object... formatArgs) {
    return getResources().getString(resId, formatArgs);
    }
    
    // 返回一个可用于获取包中类信息的class loader
    public abstract ClassLoader getClassLoader();
    
    // 返回应用程序包名
    public abstract String getPackageName();
    
    // 返回应用程序信息
    public abstract ApplicationInfo getApplicationInfo();
    
    // 根据文件名获取SharedPreferences
    public abstract SharedPreferences getSharedPreferences(String name,
    int mode);
    
    // 其根目录为: Environment.getExternalStorageDirectory()
    /*
    * @param type The type of files directory to return.  May be null for
    * the root of the files directory or one of
    * the following Environment constants for a subdirectory:
    * {@link android.os.Environment#DIRECTORY_MUSIC},
    * {@link android.os.Environment#DIRECTORY_PODCASTS},
    * {@link android.os.Environment#DIRECTORY_RINGTONES},
    * {@link android.os.Environment#DIRECTORY_ALARMS},
    * {@link android.os.Environment#DIRECTORY_NOTIFICATIONS},
    * {@link android.os.Environment#DIRECTORY_PICTURES}, or
    * {@link android.os.Environment#DIRECTORY_MOVIES}.
    */
    public abstract File getExternalFilesDir(String type);
    
    // 返回应用程序obb文件路径
    public abstract File getObbDir();
    
    // 启动一个新的activity
    public abstract void startActivity(Intent intent);
    
    // 启动一个新的activity
    public void startActivityAsUser(Intent intent, UserHandle user) {
    throw new RuntimeException("Not implemented. Must override in a subclass.");
    }
    
    // 启动一个新的activity
    // intent: 将被启动的activity的描述信息
    // options: 描述activity将如何被启动
    public abstract void startActivity(Intent intent, Bundle options);
    
    // 启动多个新的activity
    public abstract void startActivities(Intent[] intents);
    
    // 启动多个新的activity
    public abstract void startActivities(Intent[] intents, Bundle options);
    
    // 广播一个intent给所有感兴趣的接收者,异步机制
    public abstract void sendBroadcast(Intent intent);
    
    // 广播一个intent给所有感兴趣的接收者,异步机制
    public abstract void sendBroadcast(Intent intent,String receiverPermission);
    
    public abstract void sendOrderedBroadcast(Intent intent,String receiverPermission);
    
    public abstract void sendOrderedBroadcast(Intent intent,
    String receiverPermission, BroadcastReceiver resultReceiver,
    Handler scheduler, int initialCode, String initialData,
    Bundle initialExtras);
    
    public abstract void sendBroadcastAsUser(Intent intent, UserHandle user);
    
    public abstract void sendBroadcastAsUser(Intent intent, UserHandle user,
    String receiverPermission);
    
    // 注册一个BroadcastReceiver,且它将在主activity线程中运行
    public abstract Intent registerReceiver(BroadcastReceiver receiver,
    IntentFilter filter);
    
    public abstract Intent registerReceiver(BroadcastReceiver receiver,
    IntentFilter filter, String broadcastPermission, Handler scheduler);
    
    public abstract void unregisterReceiver(BroadcastReceiver receiver);
    
    // 请求启动一个application service
    public abstract ComponentName startService(Intent service);
    
    // 请求停止一个application service
    public abstract boolean stopService(Intent service);
    
    // 连接一个应用服务,它定义了application和service间的依赖关系
    public abstract boolean bindService(Intent service, ServiceConnection conn,
    int flags);
    
    // 断开一个应用服务,当服务重新开始时,将不再接收到调用,
    // 且服务允许随时停止
    public abstract void unbindService(ServiceConnection conn);
    
    // 返回系统级service句柄
    /*
    * @see #WINDOW_SERVICE
    * @see android.view.WindowManager
    * @see #LAYOUT_INFLATER_SERVICE
    * @see android.view.LayoutInflater
    * @see #ACTIVITY_SERVICE
    * @see android.app.ActivityManager
    * @see #POWER_SERVICE
    * @see android.os.PowerManager
    * @see #ALARM_SERVICE
    * @see android.app.AlarmManager
    * @see #NOTIFICATION_SERVICE
    * @see android.app.NotificationManager
    * @see #KEYGUARD_SERVICE
    * @see android.app.KeyguardManager
    * @see #LOCATION_SERVICE
    * @see android.location.LocationManager
    * @see #SEARCH_SERVICE
    * @see android.app.SearchManager
    * @see #SENSOR_SERVICE
    * @see android.hardware.SensorManager
    * @see #STORAGE_SERVICE
    * @see android.os.storage.StorageManager
    * @see #VIBRATOR_SERVICE
    * @see android.os.Vibrator
    * @see #CONNECTIVITY_SERVICE
    * @see android.net.ConnectivityManager
    * @see #WIFI_SERVICE
    * @see android.net.wifi.WifiManager
    * @see #AUDIO_SERVICE
    * @see android.media.AudioManager
    * @see #MEDIA_ROUTER_SERVICE
    * @see android.media.MediaRouter
    * @see #TELEPHONY_SERVICE
    * @see android.telephony.TelephonyManager
    * @see #INPUT_METHOD_SERVICE
    * @see android.view.inputmethod.InputMethodManager
    * @see #UI_MODE_SERVICE
    * @see android.app.UiModeManager
    * @see #DOWNLOAD_SERVICE
    * @see android.app.DownloadManager
    */
    public abstract Object getSystemService(String name);
    
    public abstract int checkPermission(String permission, int pid, int uid);
    
    // 返回一个新的与application name对应的Context对象
    public abstract Context createPackageContext(String packageName,
    int flags) throws PackageManager.NameNotFoundException;
    
    // 返回基于当前Context对象的新对象,其资源与display相匹配
    public abstract Context createDisplayContext(Display display);
    }

    ContextImpl关键成员和函数

    /**
    * Common implementation of Context API, which provides the base
    * context object for Activity and other application components.
    */
    class ContextImpl extends Context {
    private final static String TAG = "ContextImpl";
    private final static boolean DEBUG = false;
    
    private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
    new HashMap<String, SharedPreferencesImpl>();
    
    /*package*/ LoadedApk mPackageInfo; // 关键数据成员
    private String mBasePackageName;
    private Resources mResources;
    /*package*/ ActivityThread mMainThread; // 主线程
    
    @Override
    public AssetManager getAssets() {
    return getResources().getAssets();
    }
    
    @Override
    public Looper getMainLooper() {
    return mMainThread.getLooper();
    }
    
    @Override
    public Object getSystemService(String name) {
    ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
    return fetcher == null   null : fetcher.getService(this);
    }
    
    @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);
    }
    }

    ContextWrapper

    它只是对Context类的一种封装,它的构造函数包含了一个真正的Context引用,即ContextImpl对象。

    /**
    * Proxying implementation of Context that simply delegates all of its calls to
    * another Context.  Can be subclassed to modify behavior without changing
    * the original Context.
    */
    public class ContextWrapper extends Context {
    Context mBase; //该属性指向一个ContextIml实例
    
    public ContextWrapper(Context base) {
    mBase = base;
    }
    
    /**
    * Set the base context for this ContextWrapper.  All calls will then be
    * delegated to the base context.  Throws
    * IllegalStateException if a base context has already been set.
    *
    * @param base The new base context for this wrapper.
    * 创建Application、Service、Activity,会调用该方法给mBase属性赋值
    */
    protected void attachBaseContext(Context base) {
    if (mBase != null) {
    throw new IllegalStateException("Base context already set");
    }
    mBase = base;
    }
    
    @Override
    public Looper getMainLooper() {
    return mBase.getMainLooper();
    }
    
    @Override
    public Object getSystemService(String name) {
    return mBase.getSystemService(name);
    }
    
    @Override
    public void startActivity(Intent intent) {
    mBase.startActivity(intent);
    }
    }

    ContextThemeWrapper

    该类内部包含了主题(Theme)相关的接口,即android:theme属性指定的。只有Activity需要主题,Service不需要主题,所以Service直接继承于ContextWrapper类。

    /**
    * A ContextWrapper that allows you to modify the theme from what is in the
    * wrapped context.
    */
    public class ContextThemeWrapper extends ContextWrapper {
    private Context mBase;
    private int mThemeResource;
    private Resources.Theme mTheme;
    private LayoutInflater mInflater;
    private Configuration mOverrideConfiguration;
    private Resources mResources;
    
    public ContextThemeWrapper() {
    super(null);
    }
    
    public ContextThemeWrapper(Context base, int themeres) {
    super(base);
    mBase = base;
    mThemeResource = themeres;
    }
    
    @Override protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(newBase);
    mBase = newBase;
    }
    
    @Override public void setTheme(int resid) {
    mThemeResource = resid;
    initializeTheme();
    }
    
    @Override public Resources.Theme getTheme() {
    if (mTheme != null) {
    return mTheme;
    }
    
    mThemeResource = Resources.selectDefaultTheme(mThemeResource,
    getApplicationInfo().targetSdkVersion);
    initializeTheme();
    
    return mTheme;
    }
    }

    何时创建Context

    应用程序在以下几种情况下创建Context实例:

    1) 创建Application 对象时, 而且整个App共一个Application对象

    2) 创建Service对象时

    3) 创建Activity对象时

    因此应用程序App共有的Context数目公式为:

    总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context实例)

    ActivityThread消息处理函数与本节相关的内容如下:

    public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
    case LAUNCH_ACTIVITY: { // 创建Activity对象
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
    
    r.packageInfo = getPackageInfoNoCheck(
    r.activityInfo.applicationInfo, r.compatInfo);
    handleLaunchActivity(r, null);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    } break;
    
    case BIND_APPLICATION: // 创建Application对象
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
    AppBindData data = (AppBindData)msg.obj;
    handleBindApplication(data);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;
    
    case CREATE_SERVICE: // 创建Service对象
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
    handleCreateService((CreateServiceData)msg.obj);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;
    
    case BIND_SERVICE:  // Bind Service对象
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
    handleBindService((BindServiceData)msg.obj);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;
    }
    }

    创建Application对象时创建Context实例

    每个应用程序在第一次启动时,都会首先创建一个Application对象。从startActivity流程可知,创建Application的时机在handleBindApplication()方法中,该函数位于 ActivityThread.java类中 ,相关代码如下:

    // ActivityThread.java
    private void handleBindApplication(AppBindData data) {
    try {
    // If the app is being launched for full backup or restore, bring it up in
    // a restricted environment with the base application class.
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    mInitialApplication = app;
    ...
    } finally {
    StrictMode.setThreadPolicy(savedPolicy);
    }
    }
    
    // LoadedApk.java
    public Application makeApplication(boolean forceDefaultAppClass,
    Instrumentation instrumentation) {
    if (mApplication != null) {
    return mApplication;
    }
    
    Application app = null;
    
    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
    appClass = "android.app.Application";
    }
    
    try {
    java.lang.ClassLoader cl = getClassLoader();
    ContextImpl appContext = new ContextImpl(); // 创建ContextImpl实例
    appContext.init(this, null, mActivityThread);
    app = mActivityThread.mInstrumentation.newApplication(
    cl, appClass, appContext);
    appContext.setOuterContext(app); // 将Application实例传递给Context实例
    } catch (Exception e) {
    ...
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;
    
    return app;
    }
    private Context createBaseContextForActivity(ActivityClientRecord r,
    final Activity activity) {
    ContextImpl appContext = new ContextImpl();  // 创建ContextImpl实例
    appContext.init(r.packageInfo, r.token, this);
    appContext.setOuterContext(activity);
    
    // For debugging purposes, if the activity's package name contains the value of
    // the "debug.use-second-display" system property as a substring, then show
    // its content on a secondary display if there is one.
    Context baseContext = appContext;
    String pkgName = SystemProperties.get("debug.second-display.pkg");
    if (pkgName != null && !pkgName.isEmpty()
    && r.packageInfo.mPackageName.contains(pkgName)) {
    DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
    for (int displayId : dm.getDisplayIds()) {
    if (displayId != Display.DEFAULT_DISPLAY) {
    Display display = dm.getRealDisplay(displayId);
    baseContext = appContext.createDisplayContext(display);
    break;
    }
    }
    }
    return baseContext;
    }

    创建Service对象时创建Context实例

    通过startService或者bindService时,假如系统检测到需要新创建一个Service实例,就会回调handleCreateService()方法,完成相关数据操作。handleCreateService()函数位于 ActivityThread.java类,如下:

    private void handleCreateService(CreateServiceData data) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    
    LoadedApk packageInfo = getPackageInfoNoCheck(
    data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
    java.lang.ClassLoader cl = packageInfo.getClassLoader();
    service = (Service) cl.loadClass(data.info.name).newInstance();
    } catch (Exception e) {
    if (!mInstrumentation.onException(service, e)) {
    throw new RuntimeException(
    "Unable to instantiate service " + data.info.name
    + ": " + e.toString(), e);
    }
    }
    
    try {
    if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
    
    ContextImpl context = new ContextImpl(); // 创建ContextImpl实例
    context.init(packageInfo, null, this);
    
    Application app = packageInfo.makeApplication(false, mInstrumentation);
    context.setOuterContext(service);
    service.attach(context, this, data.info.name, data.token, app,
    ActivityManagerNative.getDefault());
    service.onCreate();
    mServices.put(data.token, service);
    try {
    ActivityManagerNative.getDefault().serviceDoneExecuting(
    data.token, 0, 0, 0);
    } catch (RemoteException e) {
    // nothing to do.
    }
    } catch (Exception e) {
    if (!mInstrumentation.onException(service, e)) {
    throw new RuntimeException(
    "Unable to create service " + data.info.name
    + ": " + e.toString(), e);
    }
    }
    }

    小结

    通过对ContextImp的分析可知,其方法的大多数操作都是直接调用其属性mPackageInfo(该属性类型为PackageInfo)的相关方法而来。这说明ContextImp是一种轻量级类,而PackageInfo才是真正重量级的类。而一个App里的所有ContextImpl实例,都对应同一个packageInfo对象。

    来自:博客园

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    帝国CMS7.5编辑器上传图片取消宽高的三种方法

    帝国cms如何自动生成缩略图的实现方法

    Windows 12即将到来,将彻底改变人机交互

    帝国CMS 7.5忘记登陆账号密码怎么办?可以phpmyadmin中重置管理员密码

    帝国CMS 7.5 后台编辑器换行,修改回车键br换行为p标签

    Windows 11 版本与 Windows 10比较,新功能一览

    Windows 11激活产品密钥收集及专业版激活方法

    IT头条

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    严重缩水!NVIDIA将推中国特供RTX 5090 DD:只剩24GB显存

    00:17

    无线路由大厂 TP-Link突然大裁员:补偿N+3

    02:39

    Meta 千万美金招募AI高级人才

    00:22

    技术热点

    windows 7系统中下载保存文件时不显示桌面选项的解决方法图解

    一起来说 Vim 语

    MySQL DriverCS来连接MySQL的代码示例

    windows 7系统下触控笔连按数位板出现水波纹该怎么解决?

    windows 7系统的电脑发出嘟嘟嘟的声音该怎么解决?

    MySQL访问限制的实际设置的2种方法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。