Android framework:contextの理解


慕課網frameworkノート
3-4 contextに対する理解について述べる
考察:
contextの役割を理解する
context初期化プロセスに詳しい
異なるアプリケーションコンポーネント間のcontextの違いを深く理解する
 
質問に答える:
1,アプリケーションの中で何個のcontextを使って、異なったcontextの間は上から区別します
2,ActivityのthisとgeteBaseContextの違い
3,getApplicationとgetApplicationContextの違い
4,アプリケーションコンポーネントの構築,onCreate,attachBaseContext呼び出し順序
 
1,contextの役割
contextクラスの定義を見てみましょう.抽象クラスで、インタフェースではありません.これは注意してください.
注釈を見て、このクラスを理解するのに役立ちます.
//interface to global information about an application environment.
//this is an abstract class whose implimentation is provided by the android system.
//it allows access to application-specific resources and classes,as well as up-calls for application-level operations 
//such as launching activities, boradcasting and receiving intents,etc.
//                  ,    
//       ,      android     ,
//   ,      AP       ,       AP       activity,    ,  intents 
//  context      ,            
public abstract class Context{
    public abstract Resources getResources();   //    
    public abstract Object getSystemService(String name);  //      
    public abstract void startActivity(Intent intent);  //  Acitivity
    public abstract void sendBroadcast(Intent intent);    //     
    ......
}
//        ,   ContextImpl  
//        ,             ,
class ContextImpl extends Context{
    final ActivityThead mMainThread;   //      
    final LoadedApk mPackageInfo;    //      
    
    //      
    private final ResourcesManager mResourcesManager;
    private final Resource mResources;
    
    private Resources.Theme mTheme = null;    //    
    private PackageManager mPackageManager;    //   
    
    final Object[] mServiceCache = 
        SystemServiceRegistry.createServiceCache();  //       
}

 
contextがあるからこそ、これらのアプリケーションコンポーネントは意味があり、システムサービス、システムリソースにアクセスすることができます.
contextがなければActivityは普通のjavaオブジェクトにすぎず、
皇帝のように、様々な機構がなければ、このような大きな江山を管理することはできません.もし権利がなければ、皇帝は普通の人です.
Activityが皇帝であればcontextは権力であり,権力があれば各リソースを呼び出すことができる.
 
2,contextはどこで作成しますか?」?
まず、どのcontextがあるか、つまりどのコンポーネントが独自のcontextを持っているかを理解します.
Applicatoin,Activity,Service,
放送とcontent providerには自分のcontext'がありません
まずApplication contextを見て
Application contextはApplicationとともに初期化され、ApplicationはAPプロセスの起動とともにinitされます.
APプロセス起動プロセス:
zygote fork->AP、AP起動後javaクラスのエントリ関数(Activity Threadのmain)を起動します.この関数はAMSに起動が報告されます.
AMSが受信すると、APにApplicationを作成させるコマンドが発行されます.
AP処理の関数:
private void handleBindApplication(AppBindData data){
    //  Application  
    Application app = data.info.makeApplication(...);
    //    onCreate  
    app.onCreate();
}
//      Application  
public Application makeApplication(...){
    //  context,       new   ContextImpl(...)  
    ContextImpl appContext = ContextImpl.createAppContext(...);
    Application app;
    //  Application  ,      context  ,    
    app = mActivityThread.mInstrumentation.newApplication(appContext);
    return app;
}
//  Application
Application newApplication(ClassLoader cl, String className, Context context){
    // classload  Applicatoin 
    return newApplication(cl.loadClass(className), context);
}
Application newApplication(Class> clazz, Context context)
{
    //newInstance        ,  Application  ,
    Application app = (Application)clazz.newInstance();
    //  Application    context
    //         attachBaseContext(),
    app.attach(context);
    return app;
}
//    attachBaseContext,   Application      :
    //application   ContextWrapper
public class Application extends ContextWrapper{
    ...
}
//ContextWrapper    context,
public class ContextWrapper extends Context{
    Context mBase;
    //   ContextWrapper mBase  ,mBase    context,
    //ContextWrapper    Context,        context?
    protected void attachBaseContext(Context base){
        mBase = base;
    }
    
    public Context getBaseContext(){
        return mBase;
    }
}
//ContextWrapper    Context,        context?
//  ContextWrapper   context         mBase  ,
//         
public class ContextWrapper extends Context{
    Context mBase;
    
    @Override
    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);
    }
}

反射でmBaseオブジェクトを交換すると、
getSystemServiceを呼び出すと、別のcontextインプリメンテーションにジャンプし、返されるSystem Service管理オブジェクトに手を加えることができます.
このメカニズムは一般的にプラグインで使用されます.
 
Applicationの結論:
継承関係:アプリケーション
呼び出し順序:(Applicationのコンストラクション関数)=>attachBaseContext(contextの設定)="onCreate
ContextWrapperにはContextが含まれています.呼び出しはすべて依頼されます.mBaseでしょう.
 
2,ActivityのContextはどのように初期化しますか?
Activityが起動したときに一緒にinitしたものです
Activityの起動を確認します.
private Activity performLaunchActivity(){
    Activity activity = null;
    //   
    activity = mInstrumentation.newActivity();
    
    //Application          ,          
    Application app = r.packageInfo.makeApplication();
    // Activity    context:new ContextImpl(...)
    Context appContext = createBaseContextForActivity(r, activity);
    
    // context  activity,
    //attach      attachbaseContext(context);  context  Activity   mBase
    //mBase ContextWrapper         ,       
    activity.attach(appContext, app,...);
    
    //   onCreate      。
    activity.onCreate();
    return activity;
}

//newActivity newApplication     ,loadClass   ,  NewInstance            
public Activity newActivity(ClassLoader cl, String className){
    return (Activity)cl.loadClass(className).newInstance();
}

アプリケーションと同様のプロセスが表示されます.
コンポーネントオブジェクトを作成し、コンポーネントにcontextを作成し、contextを割り当て、コンポーネントのonCreateライフサイクルを呼び出します.
 
3,initプロセスを終了し,Activityのクラス継承関係を見る.
ActivityとApplicationは少し異なり、ContextThemeWrapperから継承されています.
 
public class Activity extends ContextThemeWrapper{...}

// ContextWrapper     Theme,     
public class ContextThemeWrapper extends ContextWrapper{
    //        ,     ,    ,   Activity        
    //              ,  Context   ,      ContextWrapper   mBase   
    private int mThemeResource;
    private Resources.Theme mTheme;
    private LayhoutInflater mInflater;
    private Configuration mOverrideConfiguiration;
    private Resources mResources;
}

 
Activityの結論:
クラス継承関係:Activity
ApplicationはContextWrapperを直接継承していますが、Activityはインタフェースの展示も担当しているので、ContextThemeWrapperという層が1つ増えています.
呼び出し順序:(Activityのコンストラクション関数、contextの作成)->attachBaseContext(contextをActivityに割り当てる)->onCreate
 
4、サービスを見て
サービスはアプリケーションと同様にContextWrapperから継承されており、インタフェースを表示する必要はありません.
public abstract class Service extend ContextWrapper{...}
 
サービスの初期化:
private void handleCreateService(CreateServiceData data){
    Service service = null;
    //       ClassLoader  service  ,   newInstance      ,  service  
    service = (Service) cl.loadClass(data.info.name).newInstance();
    
    //  context,    new ContextImpl(...)
    ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
    context.setOuterContext(service);
    
    // service  Applicatoin,   makeApplication,                Application  。
    Application app = packageInfo.makeApplication();
    // Context Application    Service
    //     attachBaseContext(context),   Application   , Context  ContextWrapper   mBase
    service.attach(context, app);
    //   service onCreate      
    service.onCreate();
}

 
5、ラジオを見て
 
抽象クラスであり、ContextWrapperもContextのメンバー変数も継承されていません.
パラメータcontextはonReceve関数が1つしかありません
public bastract class BoradcastReceiver{ public adstract void onReceive(Context context, Intent intent); .... }
 
ブロードキャストが動的に登録する場合、contextはブロードキャストを登録する際に用いるcontext:contextである.registerReceiver
静的登録であれば、これもApplicationのcontextではありません.ApplicatoinをmBaseとするContextWrapperで、後で話したいです.ここで結論を記す.
 
6 contentProviderを見て
ContextWrapperも継承されていませんが、contextメンバー変数があります.
これはCOntextProvider初期化時に渡された、渡されたApplicatoinのcontextで、
ContextProviderの初期化はApplicationのコンストラクション関数とAttachBaseContextの後ですが、
しかし、アプリケーションのonCreateの前に呼び出されました.
だから、ContextProviderのonCreateはApplicationのonCreateより早いので、これは注意しましょう
public abstract class ContentProvider{ private Context mContext = null; .... }
 
質問に戻ります.
1,APには何個のcontextがありますか.異なるcontextにはどんな違いがありますか.
Apの中にはApplication,Activity,Serviceだけが自分のcontextを持っていて、
ブロードキャストとContextProviderはありませんが、
何個のcontextがあるか計算してみましょう
Activity個数+Service個数+Application個数、Applicationはプロセスに従っているので、contextが複数ある可能性があります.
 
違い:
ActivityはUIを表示するので、ContextThemeWraperを継承し、ApplicatoinとserviceはContextWrapperを継承しますが表示する必要はありません.
 
2,ActivvytのthisとgetBaseContextの違いは何ですか?
Activityはcontextを継承するので、これはActivity自身に戻ります.
getBaseContextはContextWrapperの中のmBaseを返します.
 
3,getApplicationとgetApplicationContextの違いは何ですか?
いずれもApplicatoinオブジェクトを返します.getApplicationContextはcontextの抽象関数です.
getApplicatoinはActivityやサービスに特有で、他の場所では使えませんが、
ブロードキャストの場合、onReceive()の最初のパラメータは、このcontextを取得するとgetApplicationを呼び出すことができないgetApplicationContextのみを呼び出すことができます.
 
4,アプリケーションコンポーネントの構築,onCreate,attachBaseContext呼び出し順序
コンポーネントのコンストラクション関数を呼び出し、次にattach context、最後にonCreate
 
まとめ:
1,Contextの役割をはっきり説明する:
アプリケーションコンポーネントのコンテキストであり、contextがあれば、アプリケーションコンポーネントはシステムリソースにアクセスしやすく、システムサービスを呼び出すことができます.
2,APにはいくつかのコンポーネントがあります.自分のcontextがあります.彼らはどんな違いがありますか.継承関係はどうですか.
3,contextの初期化プロセスについて