Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 【Android 應用開發】 Application 使用分析

【Android 應用開發】 Application 使用分析

編輯:關於Android編程

一. Application 分析

1. Application 簡介

(1) Application 概念

Application 概念: Application 屬於組件范疇;

--本質: Application 與 四大組件 一樣也屬於 Android 中的組件;

--作用: 用於存儲系統 和 用戶定義的全局信息;

--Application 創建: 應用開始運行時創建 Application 對象, 可以自定義, 也可以讓系統自動創建;

--Application 單例性: 每個應用只創建一個 Application 對象, 該類屬於單例模式;

--Application 生命周期: Application 生命周期 從應用啟動開始 到 應用退出結束,與應用的生命周期是相同的;

--Application 作用: 在任何組件中調用 getApplication() 或者通過 Context 對象調用 getApplicationContext() 方法獲取的 Application 對象都是相同的, 因此可以使用 Application 進行數據共享, 數據緩存操作;

(2) Application 與 全局變量

Application 與 全局變量:

--基本作用: Application 在 Android 中是為了保存全局變量而設計的類;

--Android 全局變量定義: 在 Android 中可以不使用 public static 定義全局變量, 定義在 Application 中的普通變量在Android應用中可以當作全局變量使用;

(3) Application 使用方法

Application 使用方法:

--自定義 Application: 自定義一個 class 類, 繼承android.app.Application類;

--配置 Application: 在 AndroidManifest.xml 中配置 Application;

--獲取 Application: 在組件類(Activity, Service 等)中直接調用 getApplication() 方法即可, 在普通類中調用 Context 的 getApplicationContext() 方法;

2. Application 生命周期 及 對應方法

(1) onCreate()

onCreate() 方法簡介: 該方法是 Android 程序的入口;

--執行時機: 該方法在應用創建時自動回調;

--注意: 在父類 Application 中, onCreate() 方法方法體是空的, 這裡可以不用執行 super.onCreate()方法;

關於程序入口:

--Android 程序入口: Android 程序入口是 Application, 並不是 Activity, 因為有的 應用是沒有 Activity 的;

--Java 和 C 程序入口: 這兩種語言的程序入口是工程中的 main() 函數;

(2) onLowMemory()

onLowMemory() 方法簡介:

--調用時機: 在內存不足時會回調該方法;

--重寫方法: 重寫時需要執行父類方法 super.onLowMemory(), 同時根據本應用特點, 釋放掉一些不必要的數據;

(3) onTerminate()

onTerminate() 方法簡介:

--調用時機: 只有在模擬器中終止程序時才會回調該方法, 在 Android 真機中是不會回調該方法的;

--注意: Application 的 onTerminate() 方法體是空的, 這裡不許要執行父類的方法 super.onTerminate();

(4)onConfigurationChanged()

onConfigurationChanged() 方法簡介:

--調用時機: 配置改變時回調這個方法;

(5) Application 代碼分析

Application 相關代碼:

/**	 * Called when the application is starting, before any other application	 * objects have been created.Implementations should be as quick as	 * possible (for example using lazy initialization of state) since the time	 * spent in this function directly impacts the performance of starting the	 * first activity, service, or receiver in a process.	 * If you override this method, be sure to call super.onCreate().	 */	public void onCreate() {	}	/**	 * This method is for use in emulated process environments.It will	 * never be called on a production Android device, where processes are	 * removed by simply killing them; no user code (including this callback)	 * is executed when doing so.	 */	public void onTerminate() {	}	public void onConfigurationChanged(Configuration newConfig) {		Object[] callbacks = collectComponentCallbacks();		if (callbacks != null) {			for (int i=0; i

3. Application 使用場景 1 --> 組件間的數據傳遞

(1) 使用 Application 傳遞數據

Application 媒介傳遞數據方式:

--Appliction 集合: 在 Application 中維護一個集合, 創建一個 HashMap 成員變量, 鍵是字符串, 值是 Object 對象, 這樣 這個 HashMap 可以存儲任何類型的對象;

--共享過程: Activity A 將數據存儲到 HashMap 中, 將 鍵 通過 Intent 的 Bundle 傳遞給 Activity B, 之後在 Activity B 中取出對象, 並將 HashMap 中的對象刪除;

--適用范圍: 如果跳轉的兩個 Activity 在同一個 應用 中, 可以使用這種方法;

(2) 傳統傳遞數據方式

傳統數據傳遞:Activity A 跳轉到 Activity B;

--實體類 Bean 處理: bean 實體類必須實現Serializable或者Parcellable接口, 才可以將實體類 bean 對象放入 Intent 的 Bundle 中;

--數據傳遞過程: 在 Activity A 中將 實現了 Serializable 或者 Parcellable 接口的實體類對象放入 Intent 的 Bundle 中, 跳轉到 Activity B;

4. Application 使用場景 2 --> 應用中的數據緩存

Application 緩存數據:

--緩存少量數據: 從互聯網獲取的少量數據可以直接存放在 Application 中用於數據緩存的 HashMap 中;

--緩存大量數據: 如果緩存 數據 或者 文件, 可以將文件緩存到本地, 然後在 Application 中緩存一個 文件路徑字符串即可;

--釋放緩存: 在 onLowMemory() 方法中可以釋放這些緩存, 因為這些緩存可有可無, 這裡為了性能犧牲訪問速度;

數據傳遞, 緩存 Application 示例:

package cn.org.octopus.application;import java.util.HashMap;import java.util.Map;import android.app.Application;public class MyApplication extends Application {	/** 用於數據傳遞的 Map 集合 */	private Map transferMap;	/** 用於緩存數據的 Map 集合 */	private Map cacheMap; 		@Override	public void onCreate() {		super.onCreate();				//初始化用於數據傳遞的 Map 集合		transferMap = new HashMap();		//初始化用於數據緩存的 Map 集合		cacheMap = new HashMap();	}	/**	 * 獲取數據傳遞 Map 集合	 * @return	 * 		數據傳遞 Map 集合	 */	public Map getTransferMap() {		return transferMap;	}	/**	 * 獲取數據緩存 Map 集合	 * @return	 * 		數據緩存 Map 集合	 */	public Map getCacheMap() {		return cacheMap;	}		}

5. Application 與 內存洩漏

(1) Application 內存洩漏

Application 內存分析:

--注意存放對象: Application 中如果保存了一些大的對象, 例如 Activity 等組件, 如果沒有釋放, 將會引起很多內存洩漏;

--內存釋放: 在 Application 中要經常注意釋放不許要的對象, 使用完畢後能釋放掉的就釋放, 在 onLowMemory() 方法中將所有的緩存數據都清空;

(2) Application 盡量不要持有 組件引用

組件持有 Context 對象:

--創建組件: TextView tv = new TextView(Activity activity), 這樣一來 組件持有了 Activity 或者 Context 對象;

--組件持久化: 當將持有 Context的 tv 組件設置為靜態 或者 將 tv 組件設置到 Application 中時, tv 的聲明周期就變成了整個應用的聲明周期了;

--Context 無法釋放: 此時 當 Activity 退出後, 組件仍然存在, Conetxt 無法釋放, 一旦多次訪問這個 Activity, 每次都會洩漏 Context 大小的內存;

防止內存洩漏方法:

--組件: Activity 中的組件的聲明周期不要超出 Activity 生命周期;

--圖片: 組件使用的 Drawable 對象不要超出 Actiity 聲明周期;

--線程持有對象: 不要在線程中持有 Context, 否則在線程執行完畢之前都處於內存洩漏狀態;

--內部類作用域不要超出 Activity: 如果在 Activity A 中定義了內部類, 不要將這個內部類傳遞給其它 Activity 等組件, 否則該 Activity A 不能釋放,建議將內部類設置成 static 或者 單獨寫成一個類;

二. Application 應用層源碼分析

1. Application 類結構分析

(1) Application 繼承關系

Application 類繼承結構:

--Application 類:public class Application extends ContextWrapper implements ComponentCallbacks2;

--ContextWrapper 類:public class ContextWrapper extends Context;

--Context 類:public abstract class Context;

--ComponentCallbacks2 接口:public interface ComponentCallbacks2 extends ComponentCallbacks;

--ComponentCallbacks 接口:public interface ComponentCallbacks;

--UML 圖:

\

(2) 相關類介紹

Application 相關類介紹:

--Application 類: 用於存儲應用的全局變量;

--ContextWrapper 類: 該類是 Context 簡單的代理實現, 代表了對另一個 Context 的調用, 在該類的子類中可以重寫對應方法改變指定的操作行為;

--Context 類: 該抽象類應用環境的全局信息接口, Android 提供了該抽象類的實現類, 該類用於訪問 應用的 資源 和 類 (作用一),返回 應用的 Actiity, 廣播, Intent 等操作的執行結果(作用二);

--ComponentCallbacks2 接口: 該接口繼承了 ComponentCallbacks, 用於更細粒度的內存管理;

--ComponentCallbacks 接口:應用組件的回調接口, 所有的組件都要實現這個接口;

2. CompnentCallbacks 接口

部分源碼: 省略了注釋部分, 代碼完整;

package android.content;import android.content.res.Configuration;public interface ComponentCallbacks {void onConfigurationChanged(Configuration newConfig);void onLowMemory();}

(1)onConfigurationChanged() 方法介紹

方法介紹: 該方法回調後需要重新加載新配置對應的資源, 如果Activity 對應配置改變需要 重啟組件, 其它組件不用重啟;

--方法全稱:void onConfigurationChanged(Configuration newConfig);

--回調時機: 在組件運行時, 如果發生了設備的配置改變, 就會回調該接口的方法;

--重新加載資源: 當配置改變, 該方法回調後, 需要更新資源, 以找到與新配置匹配的資源, 例如屏幕方向改變了, 需要找 drawable-land (橫屏) 或者 drawable-port (豎屏資源);

--Activity 組件配置改變: 當 Activity 運行的時候, 如果配置發生改變, 需要進行重新啟動, 例如 橫屏 切換 豎屏;

--其它組件配置改變: 在 Service 等組件運行時, 配置發生改變, 不需要重新啟動;

(2)onLowMemory() 方法介紹

方法介紹:

--方法全稱:void onLowMemory();

--回調時機: 當系統剩余內存比較低的時候, 並且系統想要清理內存以獲取更多內存時回調該方法;

--時間點不確定: 不能確定方法回調准確的時間點, 大概在所有的後台進行被殺死的時間點 左右回調該方法, 這個時間點在服務進程被殺死之前;

--避免殺死前台進程:UI 進程在清理內存時, 是應該避免被殺死的, 這類進程盡量保存;

--方法中的建議操作: 組件實現該方法, 在該方法中建議進行釋放緩存或者釋放不需要持有的資源, 執行該方法後, 系統會執行 GC 垃圾回收;

3. ComponentCallbacks2 接口

源碼示例: 一部份源碼, 省略了注釋 和 一部份的 常量;

package android.content;public interface ComponentCallbacks2 extends ComponentCallbacks {static final int TRIM_MEMORY_COMPLETE = 80;static final int TRIM_MEMORY_MODERATE = 60;... ...void onTrimMemory(int level);}

(1) onTrimMemory() 方法介紹

方法介紹:

--方法全稱:void onTrimMemory(int level);

--回調時機: 當 系統決定要清理一個進程不必要的內存時回調該方法;

--清理內存時機: 後台進程運行時, 當沒有足夠的內存去保持這些後台進程運行時, 就會進行內存清理;

--內存等級: 每個等級都有一個對應的內存值, 但是這個內存等級的精確值是無法獲取的, 因為隨時都有新的中間值會累加上去;

(2) 內存等級常量介紹

LRU list 概念: 全稱 Least Recently Used, 即最近最少使用算法, 用於內存管理;

常量TRIM_MEMORY_COMPLETE:

--全稱:static final int TRIM_MEMORY_COMPLETE = 80;

--作用: 表示 後台進程中的LRU (最近最少使用) 隊列的尾部, 如果需要更多內存, 這些進程將被殺死;

常量TRIM_MEMORY_MODERATE:

--全稱:static final int TRIM_MEMORY_MODERATE = 60;

-- 作用 : 表示 LRU 進程隊列的 中間部分, 釋放隊列中間及後面進程的內存, 會提高手機性能;

常量用法: 其中定義了很多類似的常量, 代表一部份進程, 將該常量傳入onTrimMemory(int level) 可以殺死指定集合的進程;

4. Application 類分析

(1)ComponentCallbacks 集合列表

列表定義:

--定義方式:private ArrayList mComponentCallbacks =new ArrayList();

--使用位置: 在onConfigurationChanged(),onLowMemory(),onTrimMemory()方法中使用了 該列表;

--執行內容: ComponentCallbacks 子類 即組件, 都實現了上面的三種方法, 在 Application 中的對應方法中分別遍歷組件調用組件本身的對應方法;

注冊 和 刪除組件: 每創建一個組件都將這個組件注冊, 組件銷毀時 從列表中刪除組件;

public void registerComponentCallbacks(ComponentCallbacks callback) {		synchronized (mComponentCallbacks) {			mComponentCallbacks.add(callback);		}	}	public void unregisterComponentCallbacks(ComponentCallbacks callback) {		synchronized (mComponentCallbacks) {			mComponentCallbacks.remove(callback);		}	}

(2)ActivityLifecycleCallbacks 接口介紹

ActivityLifecycleCallbacks 接口介紹:

--接口作用: 該接口提供了一套監測 Activity 聲明周期的回調方法;

--注冊 Activity 聲明周期監聽方法:

public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {synchronized (mActivityLifecycleCallbacks) {mActivityLifecycleCallbacks.add(callback);}}
--取消監聽方法

:

public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {synchronized (mActivityLifecycleCallbacks) {mActivityLifecycleCallbacks.remove(callback);}}

--接口代碼:

public interface ActivityLifecycleCallbacks {	void onActivityCreated(Activity activity, Bundle savedInstanceState);	void onActivityStarted(Activity activity);	void onActivityResumed(Activity activity);	void onActivityPaused(Activity activity);	void onActivityStopped(Activity activity);	void onActivitySaveInstanceState(Activity activity, Bundle outState);	void onActivityDestroyed(Activity activity);}

三. Application 相關示例

1. 自定義 Application 基本使用

(1) 創建 自定義 Application

創建 Application: 創建一個類, 繼承android.app.Application 類, 實現最基本的 onCreate() 方法即可;

--示例:

package cn.org.octopus.application;import android.app.Application;public class MyApplication extends Application {	@Override	public void onCreate() {		super.onCreate();	}	}

(2) 注冊 Application

在 Manifest.xml 中注冊 Application: 在 標簽中添加 android:name 屬性, 屬性值就是 自定義 MyApplication 路徑;

--示例:


2. 保存崩潰日志到文件

(1)UncaughtExceptionHandler 簡介

UncaughtExceptionHandler 未捕獲異常處理類簡介:

--線程相關: 每個線程都有一個未捕獲異常處理類;

使用自定義UncaughtExceptionHandler 類代替 線程默認的UncaughtExceptionHandler 類:

/*		 * Android 中每個線程都有其指定的 未捕獲異常處理類 UncaughtExceptionHandler		 * 這裡我們將該線程的異常處理類獲取, 將其賦予本類中的成員變量, 將本類設置為線程默認的 未捕獲異常處理類		 * 這樣就相當與在 UncaughtExceptionHandler 的外層包裝了一層, 我們可以對未捕獲的異常信息進行任何操作		 */				//獲取系統默認的UncaughtException處理器		mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();		//設置該CrashHandler為程序的默認處理器		Thread.setDefaultUncaughtExceptionHandler(this);

函數驅動動力:

--回調方法: 當出現了未捕獲異常時, 在崩潰前會回調uncaughtException() 方法, 該方法驅動其它方法運行;

--詳細方法:public void uncaughtException(Thread thread, Throwable ex);

--重寫方法: 在方法中使用 用戶自行處理 Throwable ex 拋出的異常, 如果用戶沒有處理, 使用默認的異常處理器;

if (!handleException(ex) && mDefaultHandler != null) {			//如果用戶沒有處理則讓系統默認的異常處理器來處理			mDefaultHandler.uncaughtException(thread, ex);		}

(2) 收集相關參數信息

獲取設備信息, 異常信息:Field[] fields = Build.class.getDeclaredFields();

--將獲取的信息轉為字符串:

/*		 * 該字段封裝了很多信息		 * 包括 : 設備信息 異常信息等		 */		Field[] fields = Build.class.getDeclaredFields();		for (Field field : fields) {			try {				field.setAccessible(true);				infos.put(field.getName(), field.get(null).toString());				Log.d(TAG, field.getName() + " : " + field.get(null));			} catch (Exception e) {				Log.e(TAG, "an error occured when collect crash info", e);			}		}

(3) 在 Application 中注冊該類

Application 中注冊: 具體內容請詳看代碼;

//注冊異常日志處理類		CrashHandler crashHandler = CrashHandler.getInstance();		//初始化異常日志處理類		crashHandler.init(getApplicationContext());
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved