AndroidはContext-ServiceにおけるContextの作成過程を深く理解している

4241 ワード

このシリーズは4つの文章に分けてContextを詳しく紹介して、これは第3編です
  • Android Context–ApplicationにおけるContextの作成プロセス
  • を深く理解
  • Android Context–ActivityにおけるContextの作成プロセス
  • を深く理解
  • Android Context–ServiceにおけるContextの作成プロセス
  • を深く理解
  • Android Context–Context使用の誤り
  • を深く理解
  • 本明細書はサービスのContext作成プロセスを分析するため、ActivityThread.handleCreateServiceから直接分析を開始します.これまでの論理がよく分からない場合は、サービスを参照してプロセスソース分析を開始できます.
    @UnsupportedAppUsage
        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 {
                //-----1-----
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
                service = packageInfo.getAppFactory()
                        .instantiateService(cl, data.info.name, data.intent);
            } 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);
                //-----2-----
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
    
                //-----3-----
                context.setOuterContext(service);
                //-----4-----
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                //-----5-----
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
                //-----6-----
                service.onCreate();
                mServices.put(data.token, service);
                try {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to create service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
        }
    
  • 注記1serviceオブジェクトが作成されます.
  • 注記2で、サービスのContextImplオブジェクトを作成します.
  • 注記3setOuterContextは、サービスオブジェクトをContextImplのmOuterContextに割り当て、ContextImplがサービスのメソッドおよび変数にアクセスできるようにします.
  • 注記4でApplicationを作成し、前述のAndroidでContextを深く理解しています.
  • 注釈5service.attachが呼び出され、作成されたcontextがサービスに渡される.
  • 注釈6においてservice.onCreate()が呼び出される.
  • 注釈4のコード部分を主に見て、service.attach:
    public abstract class Service extends ContextWrapper {
        @UnsupportedAppUsage
        public final void attach(
                Context context,
                ActivityThread thread, String className, IBinder token,
                Application application, Object activityManager) {
            attachBaseContext(context);
            mThread = thread;           // NOTE:  unused - remove?
            mClassName = className;
            mToken = token;
            mApplication = application;
            mActivityManager = (IActivityManager)activityManager;
            mStartCompatibility = getApplicationInfo().targetSdkVersion
                    < Build.VERSION_CODES.ECLAIR;
        }
    }
    
    public class ContextWrapper extends Context {
        protected void attachBaseContext(Context base) {
            if (mBase != null) {
                throw new IllegalStateException("Base context already set");
            }
            mBase = base;
        }
    }
    
  • に入ります.
  • は、最終的には、サービスタイプのContextImplをContextWrapperのmBase変数に割り当てます.これにより、ContextWrapperを呼び出す方法は、実際にはmBaseという本当のContextImplを呼び出す方法です.
  • これでサービスに関するContextの分析は終わります.