Activity A
啓動另外一個Activity B
,回調以下: Activity A 的onPause()
→ Activity B的onCreate()
→ onStart()
→ onResume()
→ Activity A的onStop()
; 若是B是透明主題又或則是個DialogActivity
,則不會回調A的onStop
;如何將一個 Activity 設置成窗口的樣式? 只須要給咱們的 Activity 配置以下屬性便可:
android:theme="@android:style/Theme.Dialog"
html
Activity 的 onSaveInstanceState() 和 onRestoreInstanceState()並非生命週期方法,它們不一樣於 onCreate()、onPause()等生命週期方法,它們並不必定會被觸發。java
lateinit var textView: TextView [注1]
var gameState: String? = null override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
gameState = savedInstanceState?.getString(GAME_STATE_KEY)
setContentView(R.layout.activity_main)
textView = findViewById(R.id.text_view)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY)
}
override fun onSaveInstanceState(outState: Bundle?) {
outState?.run {
putString(GAME_STATE_KEY, gameState)
putString(TEXT_VIEW_KEY, textView.text.toString())
}
super.onSaveInstanceState(outState)
}
複製代碼
Koltin中屬性在聲明的同時也要求要被初始化,不然會報錯。 例如如下代碼:linux
private var name0: String //報錯
private var name1: String = "xiaoming" //不報錯
private var name2: String? = null //不報錯
複製代碼
但是有的時候,我並不想聲明一個類型可空的對象,並且我也沒辦法在對象一聲明的時候就爲它初始化,那麼這時就須要用到Kotlin提供的延遲初始化。 Kotlin中有兩種延遲初始化的方式。一種是lateinit var,一種是by lazy。
android
LaunchMode | 說明 |
---|---|
standard | 系統在啓動它的任務中建立 activity 的新實例 |
singleTop | 若是activity的實例已存在於當前任務的頂部,則系統經過調用其onNewIntent(),不然會建立新實例 |
singleTask | 系統建立新 task 並在 task 的根目錄下實例化 activity。但若是 activity 的實例已存在於單獨的任務中,則調用其 onNewIntent() 方法,其上面的實例會被移除棧。一次只能存在一個 activity 實例 |
singleInstance | 相同 singleTask,activity始終是其task的惟一成員; 任何由此開始的activity 都在一個單獨的 task 中打開[注2] |
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
//step 1: 建立LoadedApk對象
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
... //component初始化過程
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
//step 2: 建立Activity對象
Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
//step 3: 建立Application對象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
//step 4: 建立ContextImpl對象
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
//step5: 將Application/ContextImpl都attach到Activity對象
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);
...
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
//step 6: 執行回調onCreate
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart(); //執行回調onStart
r.stopped = false;
}
if (!r.activity.mFinished) {
//執行回調onRestoreInstanceState
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
...
r.paused = true;
mActivities.put(r.token, r);
}
return activity;
}
複製代碼
Android instrumentation是Android系統裏面的一套控制方法或者」鉤子「。 這些鉤子能夠在正常的生命週期(正常是由操做系統控制的)以外控制Android控件的運行。 它們同時能夠控制Android如何加載應用程序。git
Base class for implementing實現 application instrumentation code工具代碼. When running with instrumentation turned on, this class will be instantiated for被實例化 you before any of the application code, allowing you to monitor all of the interaction交互 the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml's tag.github
AMS是系統的引導服務,應用進程的啓動、切換和調度、四大組件的啓動和管理都須要AMS的支持。面試
ActivityStarter是加載Activity的控制類,收集全部的邏輯來決定如何將Intent和Flags轉爲Activity並將其與Task和Stack關聯。算法
AMS 經過操做ActivityStackSupervisor來管理Activitysql
ActivityStack從名稱來看是跟棧相關的類,其實它是一個管理類,用來管理系統全部Activity的各類狀態。它由ActivityStackSupervisor來進行管理的,而ActivityStackSupervisor在AMS中的構造方法中被建立。數據庫
它是ActivityThread的私有內部類,也是一個Binder對象。在此處它是做爲IApplicationThread對象的server端等待client端 的請求而後進行處理,最大的client就是AMS.
能夠在後臺執行長時間運行操做而沒有用戶界面的應用組件
Service 分爲兩種工做狀態,一種是啓動狀態,主要用於執行後臺計算;另外一種是綁定狀態,主要用於其餘組件和 Service 的交互。
對於同一 app 來講,默認狀況下 Service 和 Activity 是在同一個線程中的,main Thread (UI Thread)。
一樣 建議結合源碼去看,這裏給出調用鏈
@UnsupportedAppUsage
private void handleCreateService(CreateServiceData data) {
···
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
}
···
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
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();
}
}
···
}
複製代碼
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.
ContextImpl做爲Context的抽象類,實現了全部的方法,咱們常見的getResources(),getAssets(),getApplication()等等的具體實現都是在ContextImpl的
這塊內容太多,好比能夠看看這個 AMP/AMN/AMS AT/ATP/ATN
Zygote 是android系統應用中一個至關重要的進程,其主要功能是執行Android應用程序。在android系統中運行新的應用,須要跟Zygote進程(擁有應用程序運行時所須要的各類元素和條件)結合後才能執行。
Zygote進程運行時,會初始化Dalvik虛擬機,並啓動它。android的應用程序是由java編寫的,不能直接以本地進程的形態運行在linux上,只能運行在Dalvik虛擬機中。而且每一個應用程序都運行在各自的虛擬機中,應用程序每次運行都要從新初始化並啓動虛擬機,這就至關耗時。在android中,應用程序運行前,Zygote進程經過共享已運行的虛擬機的代碼與內存信息,縮短應用程序運行所耗費的時間。而且,它會事先將應用程序要使用的android Fromework中的類和資源加載到內存中,並組織造成所用資源的連接信息。新運行的 android 應用程序在使用所須要的資源時沒必要每次從新造成資源的連接信息,這樣提升程序運行速度。
在android中,使用Zygote進程的目的?對於手機,爲了是應用程序在有限的資源型有更快的運行響應速度,提升資源利用率和設備使用時間。android使用Zygote來有效的減小系統負擔,提升運行速度。
若是僅僅只是爲了開啓一個後臺任務,那麼可使用startService方法。
若是想獲取Service中提供的代理對象,那麼必須經過bindService方法,進行綁定服務。 使用場景好比:音樂播放器,第三方支付等。
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
···
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
···
}
}
複製代碼
值 | 說明 |
---|---|
START_NOT_STICKY | 若是系統在 onStartCommand() 返回後終止服務,則除非有掛起 Intent 要傳遞,不然系統不會重建服務。這是最安全的選項,能夠避免在沒必要要時以及應用可以輕鬆重啓全部未完成的做業時運行服務 |
START_STICKY | 若是系統在 onStartCommand() 返回後終止服務,則會重建服務並調用 onStartCommand(),但不會從新傳遞最後一個 Intent。相反,除非有掛起 Intent 要啓動服務(在這種狀況下,將傳遞這些 Intent ),不然系統會經過空 Intent 調用 onStartCommand()。這適用於不執行命令、但無限期運行並等待做業的媒體播放器(或相似服務 |
START_REDELIVER_INTENT | 若是系統在 onStartCommand() 返回後終止服務,則會重建服務,並經過傳遞給服務的最後一個 Intent 調用 onStartCommand()。任何掛起 Intent 均依次傳遞。這適用於主動執行應該當即恢復的做業(例以下載文件)的服務 |
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
複製代碼
Notification notification = new Notification(icon, text, System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, title, mmessage, pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
複製代碼
IntentService是Service的子類,是一個異步的,會自動中止的服務,很好解決了傳統的Service中處理完耗時操做忘記中止並銷燬Service的問題
一種普遍運用在應用程序之間傳輸信息的機制,經過發送Intent來傳送咱們的數據
內部通訊實現機制:經過android系統的Binder機制.
LocalBroadcastManager.getInstance(MainActivity.this).registerReceiver(receiver, filter);
複製代碼
public class MyBroadCastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyBroadCastReceiver", "收到信息,內容是 : " + intent.getStringExtra("info") + "");
}
}
複製代碼
<receiver android:name=".MyBroadCastReceiver">
<intent-filter>
<action android:name="myBroadcast.action.call"/>
</intent-filter>
</receiver>
複製代碼
//onCreate建立廣播接收者對象
mReceiver = new MyBroadCastReceiver();
//註冊按鈕
public void click(View view) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("myBroadcast.action.call");
registerReceiver(mReceiver, intentFilter);
}
複製代碼
@Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
複製代碼
ContentProvider 管理對結構化數據集的訪問。它們封裝數據,並提供用於定義數據安全性的機制。 內容提供程序是鏈接一個進程中的數據與另外一個進程中運行的代碼的標準界面。
ContentProvider 沒法被用戶感知,對於一個 ContentProvider 組件來講,它的內部須要實現增刪該查這四種操做,它的內部維持着一份數據集合,這個數據集合既能夠是數據庫實現,也能夠是其餘任何類型,如 List 和 Map,內部的 insert、delete、update、query 方法須要處理好線程同步,由於這幾個方法是在 Binder 線程池中被調用的。
ContentProvider 經過 Binder 向其餘組件乃至其餘應用提供數據。當 ContentProvider 所在的進程啓動時,ContentProvider 會同時啓動併發布到 AMS 中,須要注意的是,這個時候 ContentProvider 的 onCreate 要先於 Application 的 onCreate 而執行。
// Queries the user dictionary and returns results
mCursor = getContentResolver().query(
UserDictionary.Words.CONTENT_URI, // The content URI of the words table
mProjection, // The columns to return for each row
mSelectionClause // Selection criteria
mSelectionArgs, // Selection criteria
mSortOrder); // The sort order for the returned rows
複製代碼
public class Installer extends ContentProvider {
@Override
public boolean onCreate() {
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}
複製代碼
[🔥 面試必備:高頻算法題彙總「圖文解析 + 教學視頻 + 範例代碼」之 字符串處理+動態規劃 合集!🔥 (juejin.im/post/5daad1…)
按期分享Android開發
溼貨,追求文章幽默與深度
的完美統一。
倉庫地址:超級乾貨!精心概括視頻、歸類、總結
,各位路過的老鐵支持一下!給個 Star !