編輯:關於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 Map mStatusMap;
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 Map mStatusMap;
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();
List listMethods = 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⊙)…還能改字體
android自定義View實現圖片上傳進度顯示(仿手機QQ上傳效果)
首先看下我們想要實現的效果如下圖(qq聊天中發送圖片時的效果):再看一下我實現的效果: 1、效果已經看見了,下面我們來實現它。首先我創建一個android工程P
Android學習筆記——Menu介紹(一)
背景:Android3.0(API level 11)開始,Android設備不再需要專門的菜單鍵。隨著這種變化,Android app應該取消對傳統6項菜單的依賴。取而
學習Android之第五個小程序騰訊微博樣式(Listview的使用)
效果圖: public SimpleAdapter(Context context, List extends Map data, int resou
Android - 本地驗證碼的生成
android客戶端生成本地驗證碼主要用來限制用戶隨意按請求按鈕,其實該示例也是來對自定義view的練練手而已,先給出效果圖吧其中可定制:*干擾線數目*干擾點數目*背景顏