【Android話題-3.4アプリケーションプロセス】Contextへの理解について

25220 ワード

考察内容:
  • Contextの役割を理解する
  • Contextの初期化プロセス
  • に詳しい
  • 異なるアプリケーションコンポーネント間のContextの違いを深く理解する
  • いくつかの質問に答えます.
  • アプリケーションにはContextがいくつありますか?Contextの違いは何ですか?
  • ActivityのthisとgetBaseContextの違いは何ですか?
  • getApplicationとgetApplicationContextの違いは何ですか?
  • アプリケーションコンポーネントの構造、onCreate、attachBaseContext呼び出し順序?

  • Contextは抽象クラスです
    public abstract calss Context{
      public abstract Resources getResources();
      public abstract Object getSystemService(String name);
      public abstract void startActivty(Intent intent);
      public abstract void sendBroadcast(Intent intent);
      ......
    }
    

    その実装はすべてContextImplにある
    class ContextImpl extends Context{
      final ActivityThread mMainThread;  //   
      final LoadedApk mPackageInfo;  //     
    
      private final ResourcesManager mResourcesManager; //      
      private final Resources mResources;
    
      private Resoures.Theme mThreme = null; //    
      private PackageManager mPackageManager; //   
      //      
      final Object] mServiceCache = SystemServiceRegistry.createServiceCache();
    }
    

    Contextというアプリケーションコンポーネントがあるからこそ意味があり、システムサービスにアクセスしたり、システムリソースにアクセスしたりすることができます.ContextがなければActivityは普通のjavaオブジェクトにすぎません.
    Contextはどこで作成されましたか?
    どのコンポーネントに独自のContextがありますか?
  • Application
  • Activity
  • Service(Broadcast、ContentProviderは独自のContextを持たない)
  • Application Context
    【Application Contextの初期化】:Application ContextはApplicationとともに初期化され、Applicationはアプリケーションプロセスの起動とともに初期化されます.アプリケーションプロセスの起動はどのようなものですか?まずzygoteがアプリケーションプロセスを作成し、アプリケーションプロセスが起動するとjavaクラスのエントリ関数、すなわちActivity Threadのmain関数が実行されます.この関数はAMSに報告されます:私はすでに起動しました.AMSが受信すると次のコマンド:Applicationを作成します.AMSはアプリケーションにApplicationを作成させ、アプリケーション側の処理関数は以下の通りである.
    private void handleBindApplication(AppBindData data){
      //     Application  
      Application app = data.info.makeApplication(...);
      //      onCreate  
      app.onCreate();
    }
    
    public Application makeApplication(...){
      //     Context:    newContextImpl(...)
      ContextImpl appContext = ContextImpl.createAppContext(...);
      Application app;
      //     Application  ,  appContext  
      app = mActivityThread.mInstrumentation.newApplication(appContext);
      return app;
    }
    
    //  Application  :
    application newApplication(ClassLoader cl, String className, Context context){
      //  classLoader   Application 
      return newApplication(cl.loadClass(className), context);
    }
    
    Application newApplication(Class<?> clazz, Context context){
      //     newInstance
      //newInstance           ,    Application  
      Application app = (Application)clazz.newInstance();
      //   app  context
      app.attach(context); //   attachBaseContext(context);
      return app;
    }
    
    

    【アプリケーションの継承関係】:
    public class Application extends ContextWrapper{
      ......
    }
    
    public class ContextWrapper extends Context{
      Context mBase;
      
      protected void attachBaseContext(Context base){
        mBase = base;
      }
     
      public Context getBaseContext(){
        return mBase;
      }
    
      @Overrid
      public Resources getResources() {
        return mBase.getResources();
      }
     
      @Override
      public Object getSystemService(String name) {
        return mBase.getSystemService(name);
      }
     
      @Override
      public void startActivity(Intent intent) {
        mBase.startActivity(intent);
      }
    }
    

    Application自体がContextなのに、どうしてContextが入っているのでしょうか.これはなぜですか.Contextに関するすべての呼び出しが実際には中のmBaseオブジェクトに手を回していることがわかります.これは典型的な静的エージェントモードです.もし私たちが反射で中のmBaseオブジェクトを交換したらどうなりますか?たとえばgetSystemService関数を呼び出すと、別のContextのインプリメンテーションにジャンプする可能性があり、戻ってきたSystemService管理オブジェクトに手を加えることができます.このメカニズムは一般的にプラグインで使われます.
    【Applicationの結論】:
  • 継承関係:Application
  • 呼び出し順序:->attachBaseContext->onCreate
  • ContextWraperにはContextが含まれており、呼び出しは
  • に委任されています.
    Activity Context
    【Activity Contextの初期化】:ActivityのContextはActivityの起動に伴って一緒に初期化されます.
    private Activity performLaunchActivity(){
      Activity activity = null;
      //  Actvity  
      activity mInstrumentation.newActivity();
      //        application
      Application app = r.packageInfo.makeApplication();
      // Activity    Context:    new ContextImpl()
      Context appContext = createBaseContextForActivity(r, activity);
      // appContext application  activity
      activity.attach(appContext, app, ...); //   attachBaseContext(context);
      //  Activity       
      activity.onCreate();
      return activity;
    }
    
    public Activity newActivity(ClassLoader cl, String className){
      //  ClassLoader  Activity ,   newInstance     Acivity     ,    Activity   
      return (Activity)cl.loadClass(className).newInstance();
    }
    

    【Activityのクラス継承関係】:
    public class Activity extends ContextThemeWrapper{
      ...
    }
    
    public class ContextThemeWrapper extends ContextWrapper{
      private int mThemeResource;
      private Resources.Theme mTheme;
      private LayoutInflater mInflater;
      private Configuration mOverrideConfiguration;
      private Resources mResources;
    }
    
    public class ContextWrapper extends Context{
      Context mBase;
      ......
    }
    

    【Activityの結論】:
  • Activity
  • 呼び出し順序->attachBaseContext->onCreate
  • Service Context
    【Service Contextの初期化】:
    private void handleCreateService(CreateServiceData data) {
      Servie service = null;
      //  classLoader  Service  ,    newInstance
      //newInstance   Service           Service  
      servie = (Service)cl.loadClass(data.info.name).newInstance();
      //    Context:    new ContextImpl(...)
      ContextImpl context = ContextImpl.createAppContext(this, packageInfo)
      context.setOuterContext(service);
      //       application  
      Application app = packageInfo.makeApplication();
      // context application  service
      service.attach(context, app); //   attachBaseContext(context);
      //  Service    
      servcie.onCreate();
    }
    

    【サービスの継承関係】:
    public abstract class Service extends ContextWrapper{
      ......
    }
    

    BroadcastReceiver
    public abstract class BroadcastReceiver {
      public abstract void onReceive(Context context, Intent intent);
      ......
    }
    

    【ブロードキャスト結論】:ブロードキャストはContext抽象クラスを継承していない抽象クラスであり、Contextに関するグローバル変数もなく、onReceive抽象関数が1つしかなく、この関数にはパラメータ:Contextが付いている.動的に登録されたブロードキャストであれば、このContextはcontextを使用する.registeReceiver登録ブロードキャスト時に使用するcontext;静的に登録されたブロードキャストであれば、Activity Contextではなく、ApplicationをmBaseとするContextWrapperです.
    ContentProvider
    public abstract class ContentProvider {
      private Context mContext = null;
      ......
    }
    

    ContentProviderはブロードキャストと同じようにContextWrapperも継承されていませんが、その中にmContextメンバー変数があります.ContextProviderが初期化されたときに外から伝わり、Application Contextが伝わります.ちなみにContentProviderの初期化はApplicationのコンストラクション関数およびattachBaseContextの後ですが、アプリケーションです.onCreate()の前に呼び出されました.つまりContentProviderのonCreateはアプリケーションよりもonCreateは早いです.
    いくつかの質問に答えます.
  • アプリケーションにはContextがいくつありますか?Contextの違いは何ですか?a)Activityの数+Serviceの数+Applicationの数.アプリケーションはマルチプロセスである可能性があるため、アプリケーションは複数ある可能性があります.違い:ActivityはUIを表示するためContextThemeWrapperを継承し、ServiceやApplicationのような非UIコンポーネントはContextWrapperを直接継承します.
  • ActivityのthisとgetBaseContextの違いは何ですか?A:ActivityはContextを継承しているので、これはActivityオブジェクト自身に戻ります.getBaseContextはContextWrapperの中のmBaseを返します.
  • getApplicationとgetApplicationContextの違いは何ですか?答:getApplicationContext()はcontextの抽象関数であり、getApplication()はActivityとServiceに特有のものである.例えば、ブロードキャストのonReciever(context)のcontextはgetApplication()を調整できず、getApplicationContext()を調整するしかない.
  • アプリケーションコンポーネントの構造、onCreate、attachBaseContext呼び出し順序?A:コンポーネント構築関数->attachBaseContext->onCreate
  • あなたのContextに対する理解を話します
  • Contextの役割a)Contextはアプリケーションのコンテキストであり、Contextアプリケーションコンポーネントがあればシステムリソースにアクセスしやすく、システムサービス
  • を呼び出すことができる.
  • はアプリケーションの中にいくつかのContextがあることを言い出して、それぞれ関係
  • を継承します
  • Contextの初期化プロセス
  • について説明する