1. 程式人生 > >啟動Activity的流程(Launcher中點選圖示啟動)

啟動Activity的流程(Launcher中點選圖示啟動)

啟動Activity一般有多種方式,常見的有三種:

  1. 在Launcher桌面點選app圖示

  2. 呼叫startActivity啟動一個Activity

  3. 命令am start啟動

這三種方式在服務端的處理方式基本相同,客戶端的請求方式也差別不大,理解其中之一就可以類推到其他方式。本文結合案例分析在Launcher桌面點選app圖示啟動應用的方式,再簡要給出其他兩種方式的區別。

案例

應用名稱為TestLaunchApp,包含A和B兩個Activity,A為入口類,點選按鈕跳轉到B

A.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 packagecom.example.startapptest; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; publicclassAextendsActivity{ privatefinalstaticStringTAG="StartAppTest"; @Override protectedvoidonCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); Log.i(TAG,"A"+"--------------onCreate()"); setContentView(R.layout.a_layout); } @Override protectedvoidonResume(){ // TODO Auto-generated method stub Log.i(TAG,"A"+"--------------onResume()"); super.onResume(); } @Override protectedvoidonPause(){ // TODO Auto-generated method stub Log.i(TAG,"A"+"--------------onPause()"); super.onPause(); } publicvoidfuncA(View view){ startActivity(newIntent("com.feeyan.www.b_activity")); } @Override publicvoidonBackPressed(){ // TODO Auto-generated method stub finish(); super.onBackPressed(); } }
B.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 packagecom.example.startapptest; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; publicclassBextendsActivity{ privatefinalstaticStringTAG="StartAppTest"; @Override protectedvoidonCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); Log.i(TAG,"B"+"--------------onCreate()"); setContentView(R.layout.b_layout); } @Override protectedvoidonResume(){ Log.i(TAG,"B"+"--------------onResume()"); super.onResume(); } @Override protectedvoidonPause(){ // TODO Auto-generated method stub Log.i(TAG,"B"+"--------------onPause()"); super.onPause(); } publicvoidfuncB(View view){ startActivity(newIntent("com.feeyan.www.a_activity")); finish(); } }
a_layout.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?xml version="1.0"encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin">    <Button        android:id="@+id/button_a_id"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:layout_marginBottom="50dp"        android:onClick="funcA"        android:text="@string/button_a_text"        android:textSize="20sp"/>    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:layout_centerHorizontal="true"        android:layout_marginTop="154dp"        android:text="@string/page_a_text"        android:textSize="30sp"/> </RelativeLayout>
b.layout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?xml version="1.0"encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin">    <Button        android:id="@+id/button_b_id"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:layout_marginBottom="50dp"        android:onClick="funcB"        android:text="@string/button_b_text"        android:textSize="20sp"/>    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_above="@+id/button_b_id"        android:layout_centerHorizontal="true"        android:layout_marginBottom="140dp"        android:text="@string/page_b_text"        android:textSize="30sp"/> </RelativeLayout>
AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <?xml version="1.0"encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.startapptest"    android:versionCode="1"    android:versionName="1.0">    <uses-sdk        android:minSdkVersion="17"        android:targetSdkVersion="21"/>    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme">        <activity            android:name=".A"            android:label="@string/app_name">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>            </intent-filter>            <intent-filter>                <action android:name="com.feeyan.www.a_activity">                </action>                <category android:name="android.intent.category.DEFAULT">                </category>            </intent-filter>        </activity>        <activity            android:name=".B"            android:label="@string/app_name">            <intent-filter>                <action android:name="com.feeyan.www.b_activity">                </action>                <category android:name="android.intent.category.DEFAULT">                </category>            </intent-filter>        </activity>    </application> </manifest>

當點選A中的按鈕時,跳轉到B,先暫停A,A從前臺轉入到後臺,開始執行B的onCreate、onResume方法,B被調入到棧頂,B現在可見,日誌為:

1 2 3 4 5 I/StartAppTest(26256):A--------------onCreate() I/StartAppTest(26256):A--------------onResume() I/StartAppTest(26256):A--------------onPause() I/StartAppTest(26256):B--------------onCreate() I/StartAppTest(26256):B--------------onResume()

啟動一個Activity的標誌是開始執行生命週期onCreate方法,轉入到後臺的標誌是onPause方法,正在執行、可見的標誌是onResume方法,本文將從原始碼著手,分析啟動activity的過程。

1. 在Launcher桌面點選app圖示啟動入口Activity

本文基於android5.1.1原始碼,在Launcher主頁面當點選圖表時,呼叫過程為:

onClick—->……—->startActivitySafely—->startActivity(v, intent, tag)—->startActivity(intent, optsBundle);

原始碼:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

intent設定了FLAG_ACTIVITY_NEW_TASK標誌,表示開啟一個新任務,在新任務中啟動activity,本案例沒有特殊的動畫設定,optsBundle為null。

framework層客戶端

過程1    frameworks\base\core\java\android\app\Activity.java

startActivity所屬的物件是this,表示當前啟動類Launcher物件,下一步執行到Activity的startActivity方法,過程為:

startActivity(Intent intent, @Nullable Bundle options)

—-> startActivityForResult(intent, -1)

—-> startActivityForResult(intent, requestCode, null)

注:由於原始碼較長,本文不貼上全部原始碼,只給出方法名稱、部分程式碼以及原始碼路徑

action為字串“com.feeyan.www.b_activity”,requestCode等於-1,如果>=0, B被啟動後會返回到A中,且A中的onActivityResult()方法會被呼叫。即便是呼叫startActivity,還是會調到 startActivityForResult,只不過此時requestCode是-1了。

mParent:如果不為空,表示當前Activity有子類,本案例沒有子類,為空,程序執行到:

1 2 3 4 Instrumentation.ActivityResult ar=                mInstrumentation.execStartActivity(                    this,mMainThread.getApplicationThread(),mToken,this,                    intent,requestCode,options);

要搞懂原始碼,最關鍵的就是弄清楚引數的具體含義,原始碼中引數有時候多達十幾個,如果不清楚引數的來龍去脈,無從分析。

this:當前程序還是在Launcher所在的程序,this就是Launcher類的一個物件。

mMainThread.getApplicationThread():返回一個ApplicationThread物件型別,也是一個IBinder物件型別,,mMainThread是ActivityThread的一個物件,代表當前Launcher主執行緒物件

mToken:也是一個IBinder物件型別

requestCode仍為-1,options為null

過程2    frameworks\base\core\java\android\app\Instrumentation.java

1 2 3 4 5 publicActivityResult execStartActivity(            Context who,IBinder contextThread,IBinder token,Activity target,            Intent intent,intrequestCode,Bundle options){            ...... }

this物件傳給execStartActivity,該函式的第一個形參who是Context型別,第4個形參target是Activity型別,其實際型別都是Launcher物件,只是名字起的不一樣,這就是一種共識,代表著某種含義,讀者看到名字就能猜得著其用意。

1 IApplicationThread whoThread=(IApplicationThread)contextThread;

contextThread既是IBinder物件,也是IApplicationThread物件,此處向上轉型為IApplicationThread物件,

1 2 3 4 5 intresult=ActivityManagerNative.getDefault()                .startActivity(whoThread,who.getBasePackageName(),intent,                        intent.resolveTypeIfNeeded(who.getContentResolver()),                        token,target!=null?target.mEmbeddedID:null,                        requestCode,0,null,options);

ActivityManagerNative實現了IActivityManager介面,呼叫getDefault方法最終返回ActivityManagerService的代理類ActivityManagerProxy的一個物件,於是,startActivity便轉入到ActivityManagerProxy物件中開始執行。

過程3    frameworks\base\core\java\android\app\ActivityManagerNative.java

1 2 3 4 5 publicintstartActivity(IApplicationThread caller,StringcallingPackage,Intent intent,            StringresolvedType,IBinder resultTo,StringresultWho,intrequestCode,            intstartFlags,ProfilerInfo profilerInfo,Bundle options)throwsRemoteException{ ...... }

分析引數時,結合實際引數來看,否則單獨看形參不能確定具體含義。

caller:前面傳過來的值,代表ApplicationThread物件

callingPackage:由who.getBasePackageName()的值傳遞而來,who是Context物件,getBasePackageName()的實現在ContextImple中,返回當前啟動類的包名,就是Launcher的包名

resolvedType:解析當前傳送的Intent的MIME資料型別,本案例沒有為intent設定type、data屬性,因此,intent.resolveTypeIfNeeded(who.getContentResolver())返回null

resultTo:Ibinder物件,具體含義後面繼續看

resultWho:由target != null ? target.mEmbeddedID : null得來,target是activity物件即啟動類Launcher物件,不為空,該語句返回mEmbeddedID,一個id號,這個值必須要從Launcher這個apk啟動中獲得,在Launcher啟動後,代表Launcher啟動類的物件是一個ActivityClientRecord物件,該物件所屬的類路徑為:

frameworks\base\core\java\android\app\ActivityThread.java

該物件的scheduleLaunchActivity方法中,有一句:

ActivityClientRecord r = new ActivityClientRecord();

在ActivityClientRecord的構造方法中會把embeddedID初始化為null,因此mEmbeddedID為空

startFlags:整型值,已經初始化為0,具體作用後面分析

profilerInfo:為null,具體作用後面分析

這些引數都會被打包到持久化類Parcel的物件data中,把data作為transact的引數進行跨程序傳遞:

mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);

該方法通過binder通訊機制會傳遞到ActivityManagerNative的onTransact方法,在onTransact方法中,根據傳送命令START_ACTIVITY_TRANSACTION找到case處理語句,把data中的資料取出來賦給相應的變數,繼續呼叫:

1 2 intresult=startActivity(app,callingPackage,intent,resolvedType,                    resultTo,resultWho,requestCode,startFlags,profilerInfo,options);

startActivity最終會呼叫到服務端ActivityManagerService中。此時,程序也從啟動類Launcher所在的程序切換到了服務端程序。從ActivityManagerNative.getDefault().startActivity一直到ActivityManagerService的startActivity方法,主要由binder通訊實現,該過程相當複雜,但binder通訊不屬於本文重點,而且binder機制貫穿於整個Android系統、核心、驅動部分,本文如再遇到binder通訊機制,直接給出最終被呼叫的類及方法。

在進入到服務端之前,看看客戶端到底做了哪些工作?

主要是獲得了一些必要的引數:IApplicationThread物件、啟動類包名、Intent的MIME資料型別、IApplicationToken.Stub型別物件resultTo等,除了這些,沒有其他特殊的操作了,其實最關鍵的操作還是在服務端進行的,這就是為何本文一開始提到無論哪種啟動方式,客戶端都是大同小異。

framework層服務端

過程4    frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

startActivity—->startActivityAsUser—->mStackSupervisor.startActivityMayWait

1 2 3 mStackSupervisor.startActivityMayWait(caller,-1,callingPackage,intent,                resolvedType,null,null,resultTo,resultWho,requestCode,startFlags,                profilerInfo,null,null,options,userId,null,null);

這幾步沒有太多的操作,獲得了一個使用者id,用來作一些檢測

過程5    frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java

1 2 3 4 5 6 7 8 finalintstartActivityMayWait(IApplicationThread caller,intcallingUid,            StringcallingPackage,Intent intent,StringresolvedType,            IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor,            IBinder resultTo,StringresultWho,intrequestCode,intstartFlags,            ProfilerInfo profilerInfo,WaitResult outResult,Configuration config,            Bundle options,intuserId,IActivityContainer iContainer,TaskRecord inTask){    ...... }

先看多了哪些引數:
voiceSession:IVoiceInteractionSession物件型別,被初始化null。IVoiceInteractionSession本是一個aidl遠端介面,定義了任務棧啟動taskStarted、任務棧結束taskFinished等方法

voiceInteractor:IVoiceInteractor物件型別,被初始化為null。IVoiceInteractor也是一個aidl遠端介面

outResult:WaitResult物件型別,被初始化為null。WaitResult是IActivityManager的內部類,實現了Parcelable介面,主要用來儲存啟動Activity後返回的結果資訊

config:Configuration物件型別,被初始化為null。Configuration描述了所有裝置相關的配置資訊,比如,本地語言、螢幕大小、螢幕方向、輸入法模式,可以通過Resources的getConfiguration獲得改物件

iContainer:IActivityContainer物件型別,被初始化為null。IActivityContainer也是一個aidl遠端介面

inTask:TaskRecord物件型別,被初始化為null。TaskRecord很重要,會經常用到此類,描述一個任務棧,每個任務棧可以包含多個Activity物件,每個TaskRecord物件都有一個當前棧ActivityStack的引用,每個棧可以對應多個TaskRecord物件

除了這些多餘的引數,其他引數都是從客戶端傳遞而來。

1 booleancomponentSpecified=intent.getComponent()!=null;

getComponent方法返回一個ComponentName物件,該物件表示通過intent要啟動的元件類,本案例就對應A這個Activity,ComponentName物件一般用包名和類名標識一個元件,因此,componentSpecified為true

1 intent=newIntent(intent);

根據客戶端傳遞過來的Intent物件重新構建一個Intent物件,這樣做是不要破壞客戶端傳遞來的Intent物件

1 2 3 4 5 6 7 ActivityInfo aInfo=resolveActivity(intent,resolvedType,startFlags,                profilerInfo,userId); ActivityInfo resolveActivity(Intent intent,StringresolvedType,intstartFlags,            ProfilerInfo profilerInfo,intuserId){    ...... }

resolveActivity方法開始解析Intent物件,返回intent對應的目標Activity類的ActivityInfo物件,ActivityInfo類專門用來描述AndroidManifest.xml中Activity、Receiver元件資訊的,本案例返回的就是A這個類對應的資訊,ActivityInfo的成員變數name就是類名稱,packageName就是包名稱,對應本案例分別為com.example.startapptest.A和com.example.startapptest

1 2 3 4 5 6 7 8 if(callingUid>=0){    callingPid=-1; }elseif(caller==null){    callingPid=realCallingPid;    callingUid=realCallingUid; }else{    callingPid=callingUid=-1; }

callingUid傳過來時為-1,call又不為空,程序執行else字句callingPid = callingUid = -1;

1 2 3 4 5 6 7 8 ActivityContainer container=(ActivityContainer)iContainer; finalActivityStack stack; if(container==null||container.mStack.isOnHomeDisplay()){    stack=getFocusedStack(); }else{    stack=container.mStack; }

iContainer為空,那麼container也為空,呼叫getFocusedStack獲得當前正在前臺的棧,也就是Launcher所在的棧。

1 2 3 4 if(aInfo!=null&&                    (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE)!=0){    ...... }

aInfo雖然不為空,但aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE卻為0,因為沒有設定這種屬性,因此跳過該if語句,開始執行:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 intres=startActivityLocked(caller,intent,resolvedType,aInfo,                    voiceSession,voiceInteractor,resultTo,resultWho,                    requestCode,callingPid,callingUid,callingPackage,                    realCallingPid,realCallingUid,startFlags,options,                    componentSpecified,null,container,inTask); finalintstartActivityLocked(IApplicationThread caller,            Intent intent,StringresolvedType,ActivityInfo aInfo,            IVoiceInteractionSession voiceSession,IVoiceInteractor voiceInteractor,            IBinder resultTo,StringresultWho,intrequestCode,            intcallingPid,intcallingUid,StringcallingPackage,            intrealCallingPid,intrealCallingUid,intstartFlags,Bundle options,            booleancomponentSpecified,ActivityRecord[]outActivity,ActivityContainer container,            TaskRecord inTask){    ...... }

callingPid:int型變數,看字面意思與pid相關,具體含義後面再看

callingUid:int型變數,看字面意思與uid相關,具體含義後面再看

realCallingPid:啟動類所在程序的pid,本案例是Launcher

realCallingUid:啟動類所在程序的uid,本案例是Launcher

componentSpecified:為true,表明intent對應的目標Activity類存在

outActivity:ActivityRecord陣列名稱,初始化為null,ActivityRecord是一個動態生成的物件,代表Activity在歷史棧中的記錄,ActivityRecord包含了Activity所有資訊。

1 2 3 4 5 6 7 8 9 10 11 12 13 ProcessRecord callerApp=null;        if(caller!=null){            callerApp=mService.getRecordForAppLocked(caller);            if(callerApp!=null){                callingPid=callerApp.pid;                callingUid=callerApp.info.uid;            }else{                Slog.w(TAG,"Unable to find app for caller "+caller                      +" (pid="+callingPid+") when starting: "                      +intent.toString());                err=ActivityManager.START_PERMISSION_DENIED;            }        }

相關推薦

啟動Activity流程(Launcher中點圖示啟動)

啟動Activity一般有多種方式,常見的有三種: 在Launcher桌面點選app圖示 呼叫startActivity啟動一個Activity 命令am start啟動 這三種方式在服務端的處理方式基本相同,客戶端的請求方式也差別

Activity啟動流程【從Launcher圖示】和【在Activity中呼叫startActivity()】

從Launch程序啟動Application及Activity Android系統是基於Linux的,所以它的所有應用也是基於Linux的Init程序創建出來的, 首先Init程序啟動Zygote(受精卵)程序,然後再fork出其他程序(包括SystemServer),最後開

android 從點圖示啟動Activity流程

一、前期準備 1.一些概念的介紹 ActivityManagerServices,簡稱AMS,服務端物件,負責系統中所有Activity的生命週期 ActivityThread,App的真正入口。當開啟App之後,會呼叫main()開始執行,開啟訊息迴圈佇列,這就是傳說

解決:Android App 在執行時候按下 home 鍵,讓App 在後臺執行,點圖示再次進入時防止應用重新啟動

一:app 退出時,讓 app 在後臺執行,類似於 home 鍵的功能,最小化 重寫 onkeydown 和 onBackPressed 方法,主要是 movetoBack 方法。 注意在 MainA

AMS之開機啟動Launcher、開機廣告後啟動LauncherLauncher啟動activity

activity的啟動關閉最終都是由AMS控制的。從刷了rom到第一開機引導、launcher啟動、點選啟動特定app,這之間ams控制開機引導activity、launcher、app啟動有什麼不同嗎?還是same流程?下面讓我們一探究竟。文章分三部分:第一部總體概述、第二

android關於每次點圖示進入應用後都會重新建立啟動頁的問題

android關於每次點選圖示進入應用後都會重新建立啟動頁的問題 原創   2017年07月26日 11:49:21 標籤: android / 啟動模式 932

Android Launcher分析和修改9——Launcher啟動APP流程

  本來想分析AppsCustomizePagedView類,不過今天突然接到一個臨時任務。客戶反饋說機器介面的圖示很難點選啟動程式,經常點選了沒有反應,Boss說要優先解決這問題。沒辦法,只能看看是怎麼回事。今天分析一下Launcher啟動APP的過程。從使用者點選到程式啟動的流程,下面針對WorkSpac

app切換到後臺,點圖示快速啟動

專案中發現切換到後臺,點選圖示,載入比較慢。 在網上找到解決方法。 第一步: 找到入口activity,設定其為standard。 第二步: 在你的app的AndroidManifest.xml檔案的

Android 點圖示使APP由後臺切換至前臺重新啟動歡迎頁的問題

問題:當我們的APP切到後臺執行時,點選桌面的應用圖示使APP重新回到前臺,此時APP會重新啟動歡迎頁。 但是我們並不需要這種操作,我們需要直接把APP切至前臺。 解決:我們只需要在歡迎頁的onCr

launcher 啟動應用流程簡述

在Launcher程序中,首先呼叫startActivity(),然後呼叫startActivityForResult(),然後呼叫到Instrumention的execStartActivity(),

Android應用返回桌面後,每次點圖示啟動介面都會出現

現象描述 通過QQ或者微信下載App並安裝 點選Home鍵返回Launch介面 點選安裝好的軟體圖示 發現軟體再次出現啟動介面 原因分析 解決辦法 新建一個程式入口Activity /** * 這個類的職責是: * 解決從QQ等第三方平臺安裝後

呼叫startActivityForResult啟動activity,返回當前頁不響應的問題(附帶activity攜帶引數流程

最近在專案遇到這樣一個問題,原始的activity不是為我寫,後面我要改成返回activity攜帶引數。我改好了之後 發現不能呼叫onActivityResult。除錯也沒有問題,activity結束

如何找到Android app啟動activity和頁面元素信息

dump ref adg 按鈕 配置環境變量 好的 too 啟動app ace 在實施app自動化的時候,我們需要知道app 的啟動activity和頁面元素信息,以此啟動app和定位頁面元素,那麽如何在沒有源碼的情況下找打他們呢?當然是有好的工具啦,有Android sd

手把手教你_怎麽找android應用的包名和啟動activity

color don dsm too key 包名 ani 一個 col 自己主動化測試中常常遇到這個問題,關於這個題目,方法眾多,咱的目的是找個比較簡單靠譜的: 方法一: 先進入cmd窗體,adb shell 後: cd /data/d

Linux系統啟動流程

linux開機開機自檢(BIOS)MBR引導(光盤、磁盤)GRUB菜單(選擇內核,一般只有一個內核)加載內核運行init進程,選擇運行級別(Linux的第一個運行程序)讀取/etc/inittab配置文件執行/etc/rc.d/rc.sysinit腳本(系統的初始化腳本,設置主機名和IP地址)執行/etc/r

啟動activity的標準的action常量及對應的字符串

nbsp alt .cn img 字符串 9.png 字符 技術分享 cti 啟動activity的標準的action常量及對應的字符串

activity的生命周期和啟動模式

發生 完成 nbsp 本質 top 但是 可見 自動 res 1.常見生命周期說明 2.兩個常見問題 問題一答案:本質上就是onstart和onstop方法是是否可見進行調用,而onresume和onpause是看是否為前臺互動而調用。 問題二答案:先

Android 跨進程啟動Activity黑屏(白屏)的三種解決方案

orien 但是 解決 icon draw lun 簡單 android基礎 分享 原文鏈接:http://www.cnblogs.com/feidu/p/8057012.html 當Android跨進程啟動Activity時,過程界面很黑屏(白屏)短暫時間(幾百毫秒?)。

Weblogic安裝啟動流程及免密後臺啟動

con sof util ack change tab roo 正在 default Weblogic安裝啟動流程一、安裝步驟: 1.啟動安裝程序:$ <YOUR_JAVA_HOME>/bin/java -jar -Xmx1200m wls1211_generi

CentOS5、6、7啟動具體流程

CentOS5 啟動 具體流程 CentOS5、6系統的啟動流程基於Intel X86架構平臺的系統啟動流程:1.POST:Power-On Self Testing,加電自檢;CMOS:在這裏面有一個EPROM,可擦寫可編程的只讀存儲器;在這裏面保存了一小段程序叫做BIOS程序,全稱為Basic