編輯:關於Android編程
轉載請注明出處:http://blog.csdn.net/droyon/article/details/29830157
本文以Android內核剖析為基准,結合android4.0源代碼,進行理解總結。主要闡述了如下認識:
1、何為Context,如何認識Context。
2、Application、Activity、Service等實例化流程。
3、Context的實例化對象ContextImpl對象是如何和Application、Activity、Service發生聯系的
4、初步認識下,Application、Activity等的生命周期onCreate、onStart方法的調用時機。
Context譯為場景,一個應用程序可以認為是一個工作環境,在這個工作環境中可以存在許多場景,coding代碼的場景 ,打電話的場景,開會的場景。這些場景可以類比不同的Activity,service。
第一:Activity繼承自Context,同時Activity還實現了其他的interface,我們可以這樣看,activity在語法上extends了Context,其本質上是一個Context,但同時其實現了許多interface,擴充了Context的功能,擴充之後的類成為Activity或者Service。
第二:Context本質上包含了場景的所有元素,故而設定其為abstract,Activity和Service繼承自Context,它們本質上可以認為就是Context。
step 1、Ams通過遠程Binder調用ActivityThread的內部類ApplicationThread的bingApplication方法,參數包括ApplicationInfo,這個對象由Ams創建,通過IPC傳遞到ActivityThread的內部類ApplicationThread中。
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;">public final void bindApplication(String processName,
ApplicationInfo appInfo, List step 3、調用H Handler,執行handleBindApplication()方法。 step 3.1、給AppBindData的info變量賦值。 我們著重看一下step 3.1和step3.3. step 3.1:mPackages和mResourcePackages集合,以packageName為key值,我們知道一個應用程序中的packageName是相同的,也就是說,此處一旦創建,其他地方再次調用此函數,就不需要創建了。總結:也就是說一個應用程序中的LoadedApk對象是唯一的。此處的LoadedApk,也被稱為packageInfo。 framework/base/core/java/android/app/LoadedApk.java step 1、Ams通過遠程Binder調用ActivityThread的Application的scheduleLaunchActivity方法,參數包括ActivityInfo,這個對象由Ams創建,通過IPC傳遞到ActivityThread的內部類ApplicationThread中。 step 3、調用H Handler,執行handleLaunchActivity()方法。 其中step 3,又可分為10小步。 step 3、調用H Handler,執行handleCreateService()方法。 其中step 3又可分為一下5步。 綜上所述: 1、無論是Application還是Activity、Service,他們的LoadedApk對象都是同一個,或者說packageInfo為同一個對象。 2、在創建ContextImpl對象時,Application和SErvice通過getPackageInfoNoCheck方法,Activity通過getPackageInfo方法得到。 3、一個應用程序中Context的個數 = Activity的數量+Service的數量 +1。這裡的1代表Application。 4、應用程序中包含著多個ContextImpl對象,其內部的PackageInfo卻是同一個。這樣設計意味著ContextImpl是一個輕量級類,PackageInfo是一個重量級類,所有和包相關的操作封裝到PackageInfo中,有利於代碼的封裝與隱藏。static final class AppBindData {
LoadedApk info;
String processName;
ApplicationInfo appInfo;
List
第三步可以又可以分為三小步。
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//data.info對象為LoadApk,此時data.info為null,使用getPackageINfoNoCheck創建此對象。
step 3.2、初始化Instrumentation對象。
mInstrumentation = new Instrumentation();//初始化Instrumentation對象,一個應用程序對應一個Instrumentation對象
step 3.3、創建Application對象。
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true);
}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {/*includeCode 默認為true*/
synchronized (mPackages) {
WeakReference
step 3.3、總結:每個應用程序都存在一個Application,用戶可以在AndroidManifest中重寫它,如果不重寫也存在一個默認的Application對象。
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";//1、每個工程都存在一個Application對象,默認的Application對象為android.app.Application,客戶端可以重寫
}
try {
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = new ContextImpl();//2、創建ContextImpl對象,這才是Context的實際實現類
appContext.init(this, null, mActivityThread);//3、執行ContextImpl對象的init方法,initResource等對象
app = mActivityThread.mInstrumentation.newApplication(//4、以appContext為參數得到Application對象。
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);//5、將創建的Application對象,加入到A來了Application中。
mApplication = app;
if (instrumentation != null) {//6、此時的instrumentation為null。
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
return app;
}
5、Activity中Context的創建過程
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
Bundle state, List
step 2、構建ActivityClientRecord對象,如上代碼所示。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {//1、如果packageInfo為null,則調用getPackageInfo的得到LoadedApk
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
Activity activity = null;
try {//2、調用mInstrumentation的newActivity方法,得到Activity對象
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//3、獲取Application對象
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {//4、創建ContextImpl對象
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo, r.token, this);
appContext.setOuterContext(activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);//5、執行Activity的attach方法,將此ContextImpl對象,設置給Activity,activity會調用attachBaseContext
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();//6、設置主題
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
mInstrumentation.callActivityOnCreate(activity, r.state);//7、執行Activity的onCreate方法
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();//8、執行Activity的onStart方法
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);//9、質細膩感onRestoresInstanceState方法
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
mInstrumentation.callActivityOnPostCreate(activity, r.state);
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);//10、將包含activity信息集的r對象,也就是ActivityClientRecord,加入到mActivities中,r.token為key值。
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
總結:activity的packageInfo對象和application的packageInfo是同一個對象。
6、Service中Context的創建過程
step 1、Ams通過遠程Binder調用ActivityThread的內部類ApplicationThread的scheduleCreateService方法,參數包括serviceInfo,這個對象由Ams創建,通過IPC傳遞到ActivityThread的內部類ApplicationThread中。
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo) {
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
queueOrSendMessage(H.CREATE_SERVICE, s);
}
step 2、構建CreateServiceData對象,如上代碼所示。
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);//1、得到packageInfo,調用getPackageInfoNoCheck
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();//2、創建ContextImpl對象
context.init(packageInfo, null, this);
Application app = packageInfo.makeApplication(false, mInstrumentation);//3、得到Application對象
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());//4、調用service的attach方法,將實例化的ContextImpl設置給Service
service.onCreate();
mServices.put(data.token, service);//5、將service對象加入到mService集合中,key值為data.token。
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);
}
}
}
class ContextImpl extends Context {
private final static String TAG = "ApplicationContext";
private final static boolean DEBUG = false;
private static final HashMap
ListView 控件可使用四種不同視圖顯示項目。通過此控件,可將項目組成帶有或不帶有列標頭的列,並顯示伴隨的圖標和文本。可使用 ListView 控件將稱作 ListI
android 系統集成了一個輕量級的數據庫,SQLite只是一個嵌入式的數據庫引擎;android提供SQLiteDatabase代表一個數據庫,一旦應用程序獲得了SQ
首先上圖:如何達到該View的效果?波浪如何繪制?(1)在實現該View之前,先要了解Xfermode什麼是Xfermode:稱之為圖像混合模式,Android官方給了張
本文將用兩個方法來寫類似汽車荷載的進度用LinearLayout的addview方法加上for循環用自定義控件的方法先上截圖1. 用LinearLayout的addvie