編輯:關於Android編程
Application 概念: Application 屬於組件范疇;
--本質: Application 與 四大組件 一樣也屬於 Android 中的組件;
--作用: 用於存儲系統 和 用戶定義的全局信息;
--Application 創建: 應用開始運行時創建 Application 對象, 可以自定義, 也可以讓系統自動創建;
--Application 單例性: 每個應用只創建一個 Application 對象, 該類屬於單例模式;
--Application 生命周期: Application 生命周期 從應用啟動開始 到 應用退出結束,與應用的生命周期是相同的;
--Application 作用: 在任何組件中調用 getApplication() 或者通過 Context 對象調用 getApplicationContext() 方法獲取的 Application 對象都是相同的, 因此可以使用 Application 進行數據共享, 數據緩存操作;
Application 與 全局變量:
--基本作用: Application 在 Android 中是為了保存全局變量而設計的類;
--Android 全局變量定義: 在 Android 中可以不使用 public static 定義全局變量, 定義在 Application 中的普通變量在Android應用中可以當作全局變量使用;
Application 使用方法:
--自定義 Application: 自定義一個 class 類, 繼承android.app.Application類;
--配置 Application: 在 AndroidManifest.xml 中配置 Application;
--獲取 Application: 在組件類(Activity, Service 等)中直接調用 getApplication() 方法即可, 在普通類中調用 Context 的 getApplicationContext() 方法;
onCreate() 方法簡介: 該方法是 Android 程序的入口;
--執行時機: 該方法在應用創建時自動回調;
--注意: 在父類 Application 中, onCreate() 方法方法體是空的, 這裡可以不用執行 super.onCreate()方法;
關於程序入口:
--Android 程序入口: Android 程序入口是 Application, 並不是 Activity, 因為有的 應用是沒有 Activity 的;
--Java 和 C 程序入口: 這兩種語言的程序入口是工程中的 main() 函數;
onLowMemory() 方法簡介:
--調用時機: 在內存不足時會回調該方法;
--重寫方法: 重寫時需要執行父類方法 super.onLowMemory(), 同時根據本應用特點, 釋放掉一些不必要的數據;
onTerminate() 方法簡介:
--調用時機: 只有在模擬器中終止程序時才會回調該方法, 在 Android 真機中是不會回調該方法的;
--注意: Application 的 onTerminate() 方法體是空的, 這裡不許要執行父類的方法 super.onTerminate();
onConfigurationChanged() 方法簡介:
--調用時機: 配置改變時回調這個方法;
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; i3. 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 MaptransferMap; /** 用於緩存數據的 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());
吹在前面的話:ListView下刷新刷功能相信從事Android開發的猿友們並不陌生,包括現在Google親兒子SwipeRefreshLayout實現效果在一些APP上
0.基礎知識Glide中有一部分單詞,我不知道用什麼中文可以確切的表達出含義,用英文單詞可能在行文中更加合適,還有一些詞在Glide中有特別的含義,我理解的可能也不深入,
昨天想要實現一個下拉刷新的效果,本來想應該比較簡單,因為之前在慕課網看見過類似的實現,記得是在listView裡面添加footView或是添加headView,監聽手指的
1,基本環境准備:安裝JDK1.5以上,Eclipse3.3以上版本.(MyEclipse也可以),筆者安裝了JDK1.6和MyEclipse 8.6。JDK1.6MyE