前一篇文章因為是晚上寫的,最後寫的不完善
今天把自己學習Activity的過程和經驗記錄一下,希望能協助到有心看這篇文章的朋友。本人水平低陋,還望指教
首先看代碼:
package com.zph;import android.app.Activity;import android.os.Bundle;public class FirstActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }}
要想建立一個Activity,必須覆寫onCreate()方法,在Android編程我發現一個現象:凡是覆寫的方法,在方法體中的第一行代碼一定是super.xxx()。一定先要調用父類裡的相應方法做必要的事情,再根據需求寫其他代碼。
第二行:setContentView(R.layout.main);
設定布局,到哪去找呢?開啟Eclipse左邊的視圖:
在res目錄下的layout檔案夾下有一個main.xml
代開R.java
在R.java裡有一個值public static final int main=0x7f030000 對應main.xml檔案,在 setContentView(R.layout.main)尋找到了main.xml,然後讀取其中的布局配置
這個程式就不示範了
言歸正傳,什麼是Activity?
這裡我沒翻譯,Google翻譯的是活動,但感覺不太好,乾脆就不翻譯了,我也沒聽說過誰翻譯過他
開啟android的開發文檔,兩種方法:1,android的安裝路徑下有個doc檔案夾,開啟找到index.html
2,http://developer.android.com/index.html
我建議是用下載好的文檔,這樣開啟的速度快一點
先大致瀏覽一下:
我們主要用到的是 Dev Guide 和 Reference
Reference是API
Dev Guide是開發嚮導,開啟
找到Activities,第一句:
An Activity is an application component that provides a screen with which users can interact in order to do something, such as dial the phone, take a photo, send an email, or view a map. Each activity is given a window in which to draw its user interface. The window typically fills the screen, but may be smaller than the screen and float on top of other windows.
簡單的說就是一個Activity就是一個螢幕,使用者可以點擊、觸摸。一個應用程式可能不止一個Activity。Activity的尺寸也不一定就是和手機螢幕的尺寸一樣大,有可能要小。很簡單的一個例子:我們在用手機的時候突然來了個電話,顯示來電的那個Activity就沒有全部覆蓋螢幕。
接著往下看:
Creating an ActivityTo create an activity, you must create a subclass of Activity (or an existing subclass of it). In your subclass, you need to implement callback methods that the system calls when the activity transitions between various states of its lifecycle, such as when the activity is being created, stopped, resumed, or destroyed. The two most important callback methods are:onCreate()You must implement this method. The system calls this when creating your activity. Within your implementation, you should initialize the essential components of your activity. Most importantly, this is where you must call setContentView() to define the layout for the activity's user interface.onPause()The system calls this method as the first indication that the user is leaving your activity (though it does not always mean the activity is being destroyed). This is usually where you should commit any changes that should be persisted beyond the current user session (because the user might not come back).There are several other lifecycle callback methods that you should use in order to provide a fluid user experience between activities and handle unexpected interuptions that cause your activity to be stopped and even destroyed. All of the lifecycle callback methods are discussed later, in the section about Managing the Activity Lifecycle.
這裡介紹了要建立一個自己的Activity首先要extends繼承Activity,在子類中需要實現系統的回調方法,每個方法代表每種狀態。比如說先前的onCreate()方法表示建立時的方法,onStart()表示開始時方法,onPause()表示暫停時的方法,onStop()表示停止時的方法等等,文檔後面會詳細說明,在方法體中我們可以根據需要做某些事情,比如說在onPause()方法中我們需要儲存一些重要的資料以防丟失,在下次onResume()或onStart()是可以恢複。
之前的例子我們只是覆寫了onCreate()方法,也可以加上其他的方法,但onCreate()是必須的,否則沒法建立
接下來:
Implementing a user interfaceThe user interface for an activity is provided by a hierarchy of views—objects derived from the View class. Each view controls a particular rectangular space within the activity's window and can respond to user interaction. For example, a view might be a button that initiates an action when the user touches it.Android provides a number of ready-made views that you can use to design and organize your layout. "Widgets" are views that provide a visual (and interactive) elements for the screen, such as a button, text field, checkbox, or just an image. "Layouts" are views derived from ViewGroup that provide a unique layout model for its child views, such as a linear layout, a grid layout, or relative layout. You can also subclass the View and ViewGroup classes (or existing subclasses) to create your own widgets and layouts and apply them to your activity layout.The most common way to define a layout using views is with an XML layout file saved in your application resources. This way, you can maintain the design of your user interface separately from the source code that defines the activity's behavior. You can set the layout as the UI for your activity with setContentView(), passing the resource ID for the layout.However, you can also create new Views in your activity code and build a view hierarchy by inserting new Views into a ViewGroup, then use that layout by passing the root ViewGroup to setContentView().
展現使用者介面,使用者介面就有很多,文檔裡稱之為:widgets,Google翻譯過來叫“組件”,像按鈕、文字框、複選框、下拉式功能表等等。開啟main.xml檔案,裡面都是配置,我們的widgets都配置在裡面,然後讓android自己去解析這個配置,從而顯示出來。這樣做的好處不言而喻,簡化的MVC模式(個人理解)。
總之以後這些布局、控制項都寫到設定檔裡,有幾個Activity就寫幾個布局檔案。
接下來需要開啟AndroidManifest.xml
讀xml檔案應該是一層一層讀,
<?xml version="1.0" encoding="utf-8"?>
這個xml的頭,不管他。
後面的直接從文檔裡拿過來:
<manifest ... > <application ... > <activity android:name=".ExampleActivity" /> ... </application ... > ...</manifest >
這就是他的基本結構,後面的一些元素也都都往裡面塞就可以了,比如說:
<intent-filter>
加到activity標籤裡就可以了:
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter></activity>
對於標籤的含義,有一種方法,在Eclipse中有有個代碼提示的功能(快速鍵:Alt+/),把滑鼠放在相應的位置上按下快速鍵會提示,這個快速鍵也是自動代碼補全的快速鍵。還有一種方法,看文檔,文檔裡都寫著呢。
接下來的內容牽扯到後面的一些概念,這裡先講一下,是Intent,意圖。意圖這個概念簡單講就是告訴程式我要幹什麼。意圖分為:explicit intent(顯式意圖) 和 implicit intent(隱式意圖),我們直接看代碼:
Intent intent = new Intent(this, SignInActivity.class);startActivity(intent);
這就是一個顯式意圖的調用
這裡首先New 了一個Intent,參數是this:調用者本身,SingInActivity.class:將要開始的一個Activity類,然後調用startActivity(intent)開始這個調用的開始
顯式意圖簡單的說就是我明確知道我要開始的Activity是誰!
自然隱式調用不知我要開始的Activity是哪個,看代碼:
Intent intent = new Intent(Intent.ACTION_SEND);intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);startActivity(intent);
很明顯,隱式意圖只需要告訴Android我要幹嘛就可以了,在這裡是告訴android我要發Email,當然還有很多其他的Intent,像打電話、發簡訊、web搜尋等等.
簡單寫了一下intent之後我都要暈了,都要忘了今天是學習Activity的。還是看上面的代碼的,我們建立了一個Intent,
然後要執行,調用的方法是:startActivity(intent),看名字就知道,開始一個Activity,說明我們的Activity還可以這樣建立。
要結束一個Activity,方法是:finish(),但文檔裡明確說了,除非有必要,不要自己去調用finish()方法,這個必要是什麼呢:
Calling these methods could adversely affect the expected user experience and should only be used when you absolutely do not want the user to return to this instance of the activity.
大多數情況,我們不用關閉Activity,系統會根據需要結束一些Activity。
看到這裡我自己覺得有一些亂了,前面東西比較雜,這裡扯一下那裡扯一下的。但是看完Activity的生命週期,相信前面的很多東西都能理解,或者理解更深。
Activity Lifecycle
看到這些先不要急,喝杯水,這些內容很重要。
一個Activity開始的時候首先調用onCreate()方法,在這個方法裡我們需要把程式的準備工作都做好,比如說建立視圖,綁定資料等等,這個方法傳入一個Bundle 對象,這個對象包含有Activity以前的狀態(前提是這個狀態被捕獲了)。
onCreate()後開始onStart(),文檔裡對onStart()方法沒有過多描述:
Called just before the activity becomes visible to the user.Followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden.
我個人覺得就是直接開始這個Activity,而且這個時候是Activity對使用者來說是可見的。
如果這個Activity是沒有被隱藏,調用的方法是:onResume(),這個方法是使用者可以捕捉到焦點時調用,而且此時這個Activity處在棧頂。
如果這個Activity被隱藏了,可能是一個優先順序更高的程式啟動了,總之就是隱藏了,這個時候調用onStop()。但我覺得onStart()和onResume()這兩個方法相隔的時間應該很短,所以多數情況下onStart()之後就直接是onResume()了。
onResume()之後就是onPause()
onPause()顧名思義,就是暫停了,原因是系統要恢複或啟動另一個Activity,這個方法執行的時間會儘可能的短,以便另一個Activity能儘早啟動,但是這個方法很重要,前面也提到過,在這個方法裡我們需要儲存些重要的資料,停止動畫,這個方法會佔用CPU(因為要做很多事),但是另一個啟動的Activity並沒有把全部的螢幕覆蓋,也就是說使用者還能看到我們這個暫停畫面。
看圖可以知道:onPause()後有三個去向:
1,被系統殺死了,這就是我們為什麼要儲存資料,為什麼會被系統殺死呢?可能是這個Activity太佔資源了導致資源不足,還有就是沒電了
2,返回到onStart(),又重新開始了這個Activity,而且這個Activity能顯示在螢幕上
3.,onStop(),停止了,原因在於這個Activity不可見,通俗的講就是看不到了。另一個Activity把螢幕都覆蓋了,文檔裡是這麼說的:
Called when the activity is no longer visible to the user. This may happen because it is being destroyed,or because another activity (either an existing one or a new one) has been resumed and is covering it.
onStop()也有三個去處:
1,被系統殺死了
2,onRestart()重新開始了,原因在於這個Activity又是可見的
3,到onDestory()方法以待被銷毀 ,為什麼會被銷毀呢?原因在於這個Activity已經完成了他的工作,要結束了,整個Activity生命週期要結束了。
整個Activity Lifecycle就是這樣的
這裡還有一點要說明:在onPause()方法上先前說要儲存一些資料,不是所有的都要我們自己手動儲存,有很大一部分是系統幫我們儲存的。在文檔裡是這麼說的:
However, even if you do nothing and do not implement onSaveInstanceState(), some of the activity state is restored by the Activity class's default implementation of onSaveInstanceState(). Specifically, the default implementation calls onSaveInstanceState() for every View in the layout, which allows each view to provide information about itself that should be saved. Almost every widget in the Android framework implements this method as appropriate, such that any visible changes to the UI are automatically saved and restored when your activity is recreated. For example, the EditText widget saves any text entered by the user and the CheckBox widget saves whether it's checked or not. The only work required by you is to provide a unique ID (with the android:id attribute) for each widget you want to save its state. If a widget does not have an ID, then it cannot save its state.
簡單的說是:凡是儲存的,都是有ID的。這也說明在寫這些布局、控制項的時候盡量加上ID
文檔還有兩張圖:
右圖把Activity狀態恢複的流程寫的很清楚,前提是有一個onSaveInstanceState()方法,有些時候需要自己覆寫onSaveInstanceState()方法,個人覺得不管父類有沒有覆寫,子類都要覆寫一下。還有就是文檔中十分強調了:持久化的資料不要放在onSaveInstanceState()方法裡,這個方法適合放UI的狀態資訊,持久化的資料儲存工作應該放在onPause()方法中:
Note: Because onSaveInstanceState() is not guaranteed to be called, you should use it only to record the transient state of the activity (the state of the UI)—you should never use it to store persistent data. Instead, you should use onPause() to store persistent data (such as data that should be saved to a database) when the user leaves the activity.
參考文獻:http://developer.android.com/guide/topics/fundamentals/activities.html