1. 程式人生 > >Android Hello world程式再分析【Android程式的啟動流程】

Android Hello world程式再分析【Android程式的啟動流程】

   HelloWorld幾乎是每一個程式設計師學習過程中必會遇到的,所謂溫故而知新,今天我們來深入瞭解一下Android中的helloworld程式。

   首先,在eclipse中新建一個Android專案:

  

然後在MainActivity的onCreate方法中打一個斷點


然後除錯,進入除錯介面,在除錯介面中可以看到這樣的東西,這裡就是我們的程式執行時的方法棧

將這裡的方法劃分為幾個部分


如圖中所示:

Android程式啟動流程大約可以分為6個部分:

  1. zygote孵化
  2. 執行ActivityThread的main方法
  3. 執行main方法,輪詢
  4. 輪詢到訊息,派發訊息
  5. 例項化並啟動Activity
  6. 呼叫Activity的onCreate方法
接下來結合原始碼深入分析整個啟動流程              1,Zygote孵化:Zygote是Android中第一個DalvikVM,在系統啟動時(開機)就啟動了,這裡這個步驟是啟動這個HelloWorld程式,Zygote孵化出一個新的程序(也就是DalvikVM)             2,通過反射找到ActivityThread的main方法,並呼叫( invoke)             3,執行ActivityThread的main方法,像所有的java程式一樣,Android程式也是從main方法中開始的。這裡主要乾的事情就是通過Android的訊息機制(Looper+Handler+Message)將主執行緒變成一個輪詢執行緒,不斷地從訊息佇列(MessageQueue)中獲取訊息(Message)並派發訊息(dispatchMessage
())。不明白訊息機制的童靴可以看看我另外一篇部落格:自己動手寫訊息機制           原始碼位於:frameworks\base\core\java\android\app\ActivityThread.java
public static void main(String[] args) {
		 
		...省略部分我看不懂的程式碼(hah)
        
		Looper.prepareMainLooper();
		
		...
        
		Looper.loop();//開始輪詢

        //一般來說程式不會執行到這一行,為什麼不會執行到這裡呢,我們去看看Looper.loop();
		throw new RuntimeException("Main thread loop unexpectedly exited");
	}
          原始碼位於:frameworks\base\core\java\android\os\Looper.java
public static void loop() {
	        final Looper me = myLooper();//獲取當前執行緒的Looper,main方法中Looper.prepareMainLooper();已經初始化了當前執行緒的Looper
	        if (me == null) {
	        	//丟擲異常說明沒有呼叫Looper.prepare()來初始化Looper
	            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
	        }
	        final MessageQueue queue = me.mQueue;//獲取訊息佇列

	        ...

	        for (;;) {//這裡就是一個死迴圈,這裡我不明白為什麼不用while,兩者有什麼區別,知道的童靴請告訴我一聲哈
	            Message msg = queue.next(); // might block
	            if (msg == null) {
	                // No message indicates that the message queue is quitting.
	                return;//只有訊息為null的情況下才會退出迴圈
	            }

	           ...刪繁就簡,抓住問題的核心

	           msg.target.dispatchMessage(msg);//派發訊息的處理事件
	           ...
	            
	           msg.recycle();
	        }
	    }


            4,步驟3中的輪詢(Looper)獲取到了一個訊息(Message),這個Message是ActivityThread中的成員H(H是一個Handler)發來的。這個步驟獲取到訊息,派發訊息,這個訊息的處理事件就是啟動一個Activity,即是呼叫ActivityThread中的handlerLaunchActivity()方法,輾轉呼叫 performLaunchActivity()方法。         H是ActivityThread中的一個巢狀類,在ActivityThread的main方法中,通過IPC告訴AMS要啟動一個Activity,最後呼叫了ActivityThread中的handlerLaunchActivity()方法
private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        ...
        public void handleMessage(Message msg) {
        	...
        	switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);//呼叫ActivityThread的handleLaunchActivity()方法
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                ...
        }
        ...
	}
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        //主要就是這一句
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
          ...
        } else {
            // If there was an error, for any reason, tell the activity
            // manager to stop us.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null);
            } catch (RemoteException ex) {
                // Ignore
            }
        }
    }
private Activity performLaunchActivity(ActivityClientRecord r,
			Intent customIntent) {
		// System.out.println("##### [" + System.currentTimeMillis() +
		// "] ActivityThread.performLaunchActivity(" + r + ")");

		ActivityInfo aInfo = r.activityInfo;
		if (r.packageInfo == null) {
			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 activity = null;
		try {
			java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
			// 這裡就是通過反射構造Activity
			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);
			...
			if (activity != null) {
				Context appContext = createBaseContextForActivity(r, activity);
				...
				//呼叫Activity的attach方法
				activity.attach(appContext, this, getInstrumentation(),
						r.token, r.ident, app, r.intent, r.activityInfo, title,
						r.parent, r.embeddedID,
						r.lastNonConfigurationInstances, config);

				...
				//呼叫Activity的OnCreate方法
				activity.mCalled = false;
				mInstrumentation.callActivityOnCreate(activity, r.state);
				...
			}
			r.paused = true;

			mActivities.put(r.token, r);

		} 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;
	}



            5,步驟4中的performLaunchActivity()方法呼叫了Instrumentation的callActivityOnCreate()方法,實際上,ActivityThread並沒有直接管理Activity,而是通過Instrumentation間接管理Activity,這種關係就像是,ActivityThread是一個外交官,負責與ActivityManagerService溝通,當AMS讓ActivityThread啟動一個Activity或者rusume一個Activity的時候,ActivityThread就告訴Instrumentation,“幫我啟動某某某Activity”,然後Instrumentation就啟動相應的Activity,Instrumentation負責例項化Activity並管理Activity的宣告週期。             6,MainActivity的onCreate()方法。開發者重寫的方法。

相關推薦

Android Hello world程式分析Android程式啟動流程

   HelloWorld幾乎是每一個程式設計師學習過程中必會遇到的,所謂溫故而知新,今天我們來深入瞭解一下Android中的helloworld程式。    首先,在eclipse中新建一個Android專案:    然後在MainActivity的onCreate方法中

Android Hello World程式

package com.example.android_hello; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app

藍芽檔案傳輸之obex層之上的分析Android原始碼解析

 在上節中我們仔細分析了藍芽檔案傳輸過程中涉及到的UI介面,最終定格在藍芽裝置掃描的介面,我們只要選擇自己想要傳輸的藍芽裝置就可以進行藍芽檔案的傳輸了。那就是這樣一個簡單的裝置選擇的點選會引發哪些

08 CoCos Creator 打包釋出原生平臺-Android-hello world

1. 專案 -> 構建釋出 2. 構建釋出-選擇Android 依次構建->編譯->執行 3. 編譯APK生成位置 D:\CoCosCreator\HelloWorld\build\jsb-link\frameworks\runtim

Android 虛擬機器簡單介紹——ART、Dalvik、啟動流程分析

Android 虛擬機器方面的知識,我是通過《深入理解 Android 核心設計思想》來學習的,內容特別多(只有一章,但有 160 頁),但感覺和 Android 開發有些偏了,因此很多內容都沒有認真去看,比如 EFL 格式等,這裡只是選取了一些感覺比較重要的做

BZOJ 4195 程式自動分析並查集+離散化

Description  在實現程式自動分析的過程中,常常需要判定一些約束條件是否能被同時滿足。 考慮一個約束滿足問題的簡化版本:假設x1,x2,x3,…代表程式中出現的變數,給定n個形如xi=xj或xi≠xj的變數相等/不等的約束條件,請判定是否可以分別為每一個變數賦予

CUDA C 最佳實踐:應用程式效能分析讀書筆記

以下為長截圖,CSDN 限定了圖片長度,請點選檢視原圖   gprof:   gprof 支援的選項: -b 不再輸出統計圖表中每個欄位的詳細描述。 -q 只輸出函式的呼叫圖(Call graph的那部分資訊)。 -p 只輸出函式的時間

Android系統分析之Activity的啟動流程

1 參考連結 2 概念 Activity就是被用來進行與使用者互動和用來與android內部特性互動的元件,在應用程式中用到的所有activity都需要在manifest.xml檔案中進行註冊。那麼Activity又是怎樣一種元件,怎麼樣進行顯示

Android Intent傳遞物件和ArrayList大明進化十八

         以前做專案的時候,需要Intent 傳遞複雜型別,例如:陣列,ArrayList型別,傳遞類物件,今天抽空寫了個例子,方便以後用的時候查詢!有問題可以留言; 轉載請標明出處:               程式主介面:                  

Lenovo k860i 移植Android 4.4 cm11進度記錄上篇已完結

2014.5.16 為了驗證一下下載的CM11的原始碼有沒有問題,決定編譯一下cm官方支援的機器,手上正好有臺nexus7 2012,就拿它為例測試一下在mac os x平臺的整個編譯過程。 1. 最開始,是在os x下面搭編譯環境,以前有說過的,詳見xda這個帖子。 http://forum.xda-dev

android的常用控制元件總結安卓入門五

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。                                             RadioButton單選

Netty Hello World 入門原始碼分析

第一節簡單提了什麼是網路程式設計,Netty 做了什麼,Netty 都有哪些功能元件。這一節就具體進入 Netty 的世界,我們從用 Netty 的功能實現基本的網路通訊開始分析 各個元件的使用。 1. 一個簡單的傳送接收訊息的例子 話不多說,先來實現一個傳送接收訊息的例子。本例項基於 SpringBoot

程式之計算器 C++ STL棧實現 + C 陣列模擬棧實現 適用VC, DEV, codeblack

自己寫的小程式,記錄一下提醒這兩個只能在DEV或者codeblack 執行。 VC能執行的在最後面(哎,畢竟課程設計是在VC裡面測試)。  C++版本的,用STL棧實現的: #include <cstdio> #include <cstring>

Android原始碼解析之(九)-->SystemServer程序啟動流程

上面一文中我們講過android系統中比較重要的幾個程序:init程序,Zygote程序,SystemServer程序已經各種應用程序,其中Zygote程序是整個android系統的根程序,包含SystemServer程序已經各種應用程序在內的程序都是通過Z

實驗二:命令列選單小程式V1.0實驗樓系列shiyanlou.com

一、實驗要求 1、程式碼風格規範: 程式碼風格的原則:簡明、易讀、無二義性; 縮排、命名、註釋等程式碼編排的風格規範; 《構建之法》4.1程式碼規範 高質量C++/C程式設計指南(林銳) 2、具體要求(參照視訊中的具體實驗過程): 實現一個

Android runtime機制(二)zygote程序的啟動流程

在前一章裡介紹了Android runtime的Init程序的啟動,在Init程序裡,我們知道了runtime環境是如何搭建的和系統屬性設定在什麼時候設定的,並瞭解了使用配置檔案Init.rc來啟動系統Service和其他操作處理。 在這一章裡,我們將繼續跟進

Docker容器啟動問題容器啟動時, exceptions.JedisConnectionException:Could not get a resource from the pool

問題現場環境: 1、本地虛擬機器CentOS7 下的docker環境。 2、docker下的redis、mysql已正常啟動,且虛擬機器外可正常訪問。 3、啟動容器(SpringCloud 閘道器服務)需要使用 docker下的redis、MySql。   問題現象

Netty原始碼分析:1.4伺服器啟動流程

第一章節是主要是伺服器啟動的程式碼分析。章節目錄有: |———1.1初始化NioEventLoopGroup |———1.2初始化NioEventLoop |———1.3初始化NioServerSocketChannel |———1.4伺服器啟動流程 為什麼先從初始化開

ARChon 分析之七:啟動流程分析

引文 通過前面幾篇文章的介紹,現在來看ARChon的js程式碼就簡單多了。基礎程式碼是 ARC 的執行環境。然後ChromeApp啟動,ChromeApp在配置項中配置了apk的路徑。然後呼叫 ARChon的擴充套件程式。開啟一個視窗。 那麼 ARChon 從哪裡看起呢? mai

Linux開機啟動指令碼開機指令碼存放位置問題

我在使用Ubuntu系統設定開機啟動指令碼的時候,按如下方式設定 $ sudo vim /etc/rc.localls > /home/wsdc/jk.txt echo 'ss' > /j.txt exit 0 後來發現根目錄下確實生成了j.txt,但是/ho