編輯:關於Android編程
昨天晚上我看了Google training裡面Manage the Activity Lifecycle這一節,看了以後學到很多以前看書,看視頻都沒有了解過的東西,Google關於如何恰當地使用這些方法來是我們的APP運行流暢,符合用戶的預期給出了很好的指導意見,比如Pause()裡面釋放不需要的系統資源,停止UI動畫等消耗內存的東西,不要進行密集CPU操作以影響Activity的過渡等等,還有SaveInstanceStates()作用及用法的詳細講解。。。。反正好多好多了。
於是,我就忍不住下載了官方示例,看看Google的實例APP是怎麼樣的。在Studio裡面運行一看,果然不一樣。一般的教程都是給你看看Log就好了吧,而且只運行一個Activity,讓你看看單個Activity的變化是怎麼樣的。瞬間差距就出來了。。。。。Google的示例不僅僅將Activity的數量范圍變大到3個,還用圖形化的方式更直觀的給我們展示了Activity生命周期的變化過程。
有圖為證:
看著確實是厲害了很多呢,如果只是從圖形化的角度去看看Activity的生命周期在各種情況下的變化,學習Activity生命周期的目的應該達到了,但我很好奇他是怎麼做出來,因為我是Android新手,所以就看了看源碼,下面是我從源碼裡面的學到東西的摘要。
如果大家對這個示例也感興趣,可以點擊這裡進行示例的下載.
第一個問題:
如何在多個Activity切換的時候,追蹤Activity的狀態變化信息,然後顯示出來?第一個回答:
首先在每個Activity使用一樣的布局,然後定義一個工具類A來存貯所有Activity變化的狀態信息,所有的Activity共用一個靜態工具類A變量,這保證了狀態信息的共享。然後定義一個工具類B,分別在每個Activity的不同狀態打印信息。好了,讓我們先看一下工具類A的代碼吧。
public class StatusTracker { private MapmStatusMap; private List mMethodList; private static StatusTracker ourInstance = new StatusTracker(); private static final String STATUS_SUFFIX = "ed"; public static StatusTracker getInstance() { return ourInstance; } private StatusTracker() { mStatusMap = new LinkedHashMap (); mMethodList = new ArrayList (); } public List getMethodList() { return mMethodList; } public void clear() { mMethodList.clear(); mStatusMap.clear(); } /** * Adds the status value for the given activityName into the Map. * * @param activityName * @param status */ public void setStatus(String activityName, String status) { mMethodList.add(activityName + "." + status + "()"); if (mStatusMap.containsKey(activityName)) mStatusMap.remove(activityName); mStatusMap.put(activityName, status); } /** * Gets the status value for the given activityName. * * @param activityName * @return */ public String getStatus(String activityName) { String status = mStatusMap.get(activityName); status = status.substring(2, status.length()); // String manipulation to ensure the status value is spelled correctly. if (status.endsWith("e")) { status = status.substring(0, status.length() - 1); } if (status.endsWith("p")) { status = status + "p"; } status = status + STATUS_SUFFIX; return status; } public Set keySet() { return mStatusMap.keySet(); } }
首先,我們看到 StatusTracker 這個類內部定義了一個靜態的自身變量和 getInstance() 方法,這樣我們只要在不同的地方直接調用這個靜態方法就能得到相同的 StatusTracker 變量了。
public class StatusTracker { private MapmStatusMap; private List mMethodList; private static StatusTracker ourInstance = new StatusTracker(); private static final String STATUS_SUFFIX = "ed"; public static StatusTracker getInstance() { return ourInstance; } 。。。。
然後我們再看它存貯狀態信息的代碼 它定義了一個 Map 用來存貯不同Activity狀態(最多3個),定義了一個List用來存貯所有Activity狀態變化的歷史信息。因為Map不能存貯重復的鍵值對,而List可以存儲重復的信息。
然後通過 setStatus 這個方法來更新Activity最新的狀態。
public void setStatus(String activityName, String status) { mMethodList.add(activityName + "." + status + "()"); if (mStatusMap.containsKey(activityName)) mStatusMap.remove(activityName); mStatusMap.put(activityName, status); }
只需要每次把Activity的名字和它對應的狀態作為參數放進去就好。
好了,現在讓我們看看示例是如何用這個相同的示例進行UI內容的更新的吧。也就是工具類B,我們先看看代碼:
public class Utils { private static StatusTracker mStatusTracker = StatusTracker.getInstance(); /** * Helper method to print out the lifecycle state of each Activity. Note this has * been wrapped in a Handler to delay the output due to overlaps in lifecycle state * changes as one Activity launches another. * @link http://developer.android.com/guide/topics/fundamentals/activities.html#CoordinatingActivities * @param viewMethods TextView to list out the lifecycle methods called * @param viewStatus TextView to list out the status of all Activity classes */ public static void printStatus(final TextView viewMethods, final TextView viewStatus) { Handler handler = new Handler(); handler.postDelayed(new Runnable() { public void run() { // Get the stack of Activity lifecycle methods called and print to TextView StringBuilder sbMethods = new StringBuilder(); ListlistMethods = mStatusTracker.getMethodList(); for (String method : listMethods) { sbMethods.insert(0, method + "\r\n"); } if(viewMethods != null) { viewMethods.setText(sbMethods.toString()); } // Get the status of all Activity classes and print to TextView StringBuilder sbStatus = new StringBuilder(); for (String key : mStatusTracker.keySet()) { sbStatus.insert(0,key + ": " + mStatusTracker.getStatus(key) + "\n"); } if(viewStatus != null) { viewStatus.setText(sbStatus.toString()); } } }, 750); } }
我們看到它只有一個成員變量,一個方法。
成員變量是和所有Activity相同的變量,這樣保證數據的一致性。方法只有打印打印狀態信息的方法,接受兩個TextView參數,這兩個參數分別是貼圖中的兩個TextView。
可以看到 Utils 類的方法是通過Handle來更新UI的,內容比較簡單就不說了。
好了這是代碼部分,最後貼一下ActivityA的內容,B,C代碼基本一致,只是少了onDestroy()方法裡面clear()函數的調用,因為A先啟動,結束的時候肯定也是A最後銷毀,在Destroy的時候我們應該釋放最後沒有釋放的資源,這裡是清理,而其他的時候應該保留。
public class ActivityA extends Activity { private String mActivityName; private TextView mStatusView; private TextView mStatusAllView; private StatusTracker mStatusTracker = StatusTracker.getInstance(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_a); mActivityName = getString(R.string.activity_a); mStatusView = (TextView)findViewById(R.id.status_view_a); mStatusAllView = (TextView)findViewById(R.id.status_view_all_a); mStatusTracker.setStatus(mActivityName, getString(R.string.on_create)); Utils.printStatus(mStatusView, mStatusAllView); } @Override protected void onStart() { super.onStart(); mStatusTracker.setStatus(mActivityName, getString(R.string.on_start)); Utils.printStatus(mStatusView, mStatusAllView); } @Override protected void onRestart() { super.onRestart(); mStatusTracker.setStatus(mActivityName, getString(R.string.on_restart)); Utils.printStatus(mStatusView, mStatusAllView); } @Override protected void onResume() { super.onResume(); mStatusTracker.setStatus(mActivityName, getString(R.string.on_resume)); Utils.printStatus(mStatusView, mStatusAllView); } @Override protected void onPause() { super.onPause(); mStatusTracker.setStatus(mActivityName, getString(R.string.on_pause)); Utils.printStatus(mStatusView, mStatusAllView); } @Override protected void onStop() { super.onStop(); mStatusTracker.setStatus(mActivityName, getString(R.string.on_stop)); } @Override protected void onDestroy() { super.onDestroy(); mStatusTracker.setStatus(mActivityName, getString(R.string.on_destroy)); mStatusTracker.clear(); } public void startDialog(View v) { Intent intent = new Intent(ActivityA.this, DialogActivity.class); startActivity(intent); } public void startActivityB(View v) { Intent intent = new Intent(ActivityA.this, ActivityB.class); startActivity(intent); } public void startActivityC(View v) { Intent intent = new Intent(ActivityA.this, ActivityC.class); startActivity(intent); } public void finishActivityA(View v) { ActivityA.this.finish(); } }
這就是代碼部分了。
在XML布局文件裡我可看了看,這裡簡單貼一下代碼
變量的命名規范,還有layout_toRightOf,這個方法我都沒怎麼用,以前一直都用的絕對大小,學習一下。
還有我在TextView裡面看到了,這個屬性 android:typeface=”monospace”,我之前沒怎麼見過,就搜了一下,找到了這麼個說法。
問:
How to change the font on the TextView? How to change the font in a TextView, as default it’s shown up as Arial? How to change it to Helvetica?答:
First, the default is not Arial. The default is Droid Sans.原來這是改變字體的屬性。。(⊙o⊙)…還能改字體
首先看下我們想要實現的效果如下圖(qq聊天中發送圖片時的效果):再看一下我實現的效果: 1、效果已經看見了,下面我們來實現它。首先我創建一個android工程P
背景:Android3.0(API level 11)開始,Android設備不再需要專門的菜單鍵。隨著這種變化,Android app應該取消對傳統6項菜單的依賴。取而
效果圖: public SimpleAdapter(Context context, List extends Map data, int resou
android客戶端生成本地驗證碼主要用來限制用戶隨意按請求按鈕,其實該示例也是來對自定義view的練練手而已,先給出效果圖吧其中可定制:*干擾線數目*干擾點數目*背景顏