編輯:關於Android編程
Activity
幾乎是每個應用必有的組件,所以任何安卓應用的開發幾乎都是從Activity
開始的。
比如,你希望設計一個計算器應用,要呈現這個計算器的功能(顯示出計算器的樣子,實現計算的能力)一定會在這個應用中創建一個Activity
,讓這個Activity
展示的界面就是計算器。
所以使用Android Studio創建工程以後,會默認為我們創建一個Activity
組件,它繼承自Android SDK的Activity
類。
class CalulatorActivity extends Activity
{
......
}
新創建的Activity—CalulatorActivity作為安卓的四大組件之一,一定要在這個應用的配置文件manifest.xml中聲明自己的存在,否則系統會不認識這個組件,當你啟動它的時候就會報錯。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.anddle.calculator"> <application android:icon="@mipmap/ic_launcher" android:label="@string/app_name"> <activity android:name=".CalulatorActivity"> ...... </activity> </application> </manifest>
每一個Activity都有它的生命周期,體現了它從誕生到消亡的各個階段。
下圖為我們展示了Activity整個生命的過程,這是安卓官方提供的Activity生命周期圖。
Activity每進入到一個生命的階段,就會調用這些狀態對應的函數。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onRestart() {
super.onRestart();
}
如果我們在代碼中繼承了Activity類,並覆蓋了這些函數,我們就能感知到Actvity生命狀態的轉換,並在這個轉換的時刻讓Activity做對應的處理。
比如在Activity創建的時候,讓它調用我們的代碼,完成界面的布局;在Activity銷毀的時候,讓它調用我們的代碼,完成界面資源的釋放。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//進行界面的布局
setContentView(R.layout.activity_main);
......
}
@Override
protected void onDestroy() {
super.onDestroy();
//釋放一些界面可能占用的資源
......
}
接下來,我們詳細介紹下Acivity的各個階段。這些階段都是成對出現的。根據不同的標准,我們將它們分成三類:
全生命周期:這是Activity的從創建到銷毀的整個階段,從onCreate()
開始到onDestroy()
結束。
可見生命周期:這是Activity能被用戶看到的整個階段,這裡說的能被看到包括了“雖然被顯示但是不能與用戶交互”的情況,例如你正在微信聊天,突然系統彈出來一個對話框類型的Activity,提示你電量不足,這時微信界面被擋在後面,不能和用戶交互了,但是你還能看到。從onStart()
開始到onStop()
結束。
前台生命周期:這是Activity可以和用戶進行交互的階段。從onResume()
開始到onPause()
結束。
從一個Activity創建出來,到顯示,再到用戶按返回鍵主動退出銷毀這個Activity,它將經歷:
onCreate()
->
onStart()
->
onResume()
->
用戶可以與Activity交互,用戶按返回鍵主動退出->
onPause()
->
onStop()
->
onDestroy()
;
Activity A創建出來,並顯示;然後Activity A啟動另一個Activity B,B創建出來,並顯示,它將經歷:
Activity A onCreate()
->
Activity A onStart()
->
Activity A onResume()
->
用戶可以與Activity A交互,然後Activity A啟動另一個Activity B,
Activity A onPause()
->
Activity B onCreate()
->
Activity B onStart()
->
Activity B onResume()
->
Activity A onSaveInstanceState()
->
Activity A onStop()
->
Activity A被隱藏,用戶可以與Activity B交互;
如果一個Activity從創建出來,到顯示,然後旋轉,那麼它將經歷:
onCreate()
->
onStart()
->
onResume()
->
用戶可以與Activity交互,此時屏幕進行旋轉,從豎屏變橫屏->
onPause()
->
onSaveInstanceState()
->
onStop()
->
onDestroy()
->
onCreate()
->
onStart()
->
onRestoreInstanceState()
->
onResume()
->
用戶可以與Activity交互;
在周期變化的過程當中,加入了onSaveInstanceState()
和onRestoreInstanceState()
。雖然它們不是Activity
周期的一部分,但是對它們對回調在Activity
的各種切換扮演了非常重要的角色--提供了保存Activity
數據的時機。
在Activity生命的周期中,安卓系統可能直接回收Activity。系統回收Activity有兩種常見的情況,
系統資源緊張; 屏幕的旋轉;當系統資源緊張的時候,例如你打開了很多應用,系統中的可用內存很少了。這是安卓系統會采用一個策略來回收系統中的資源。
對於那些沒有顯示或者雖然顯示了、但卻沒有和用戶做交互的Activity們,系統會優先回收那些沒有顯示的Activity(例如在onStop()狀態下的Activity);如果回收那些資源以後,發現資源還是不夠用,就會回收雖然顯示了、但卻沒有和用戶做交互的Activity(例如在onPause()狀態下的)。
這裡會遇到一個問題:假如Activity A啟動了Activity B之後,系統發現內存不足,在回收了其它所有資源後,它不得不繼續回收Activity A。
此時與Acitity B正在交互的用戶,點擊了“返回”按鈕,按照道理,應該顯示Activity A才對,但是系統已經回收了Activity A。這時該怎麼辦呢?
系統遇到這種情況就會重新創建Activity A,重新調用它的onCreate()。
不過這裡又會遇到另一個很現實的問題:如果之前的Activity A上面用戶正輸入了一些東西,例如他的名字和郵箱地址,或者是已經編輯了很長一大段的文字,如果系統onCreate的話,這些輸入的東西就會被清除掉了。這可怎麼辦呢?
安卓系統為我們提供了一個這種情況下數據的重建機制:在Activity被放到後台運行的時候使用onSaveInstanceState()
回調函數來保存這些數據,
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
//將要保存的數據,例如撰寫的文檔的字符串,保存到savedInstanceState變量當中
}
在Activity被重建的時候,使用onRestoreInstanceState()
回調函數來恢復這些數據
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//將需要恢復的數據,例如文檔字符串,從savedInstanceState變量中取出,設置到界面上
}
需要注意的是,onSaveInstanceState()
與onRestoreInstanceState()
在Activity周期切換過程中並不一定會被調用,只是在這種Activity異常流程處理時(Activity被系統回收、config信息變化等情況),才會被調用到。
屏幕旋轉時,Activity的生命周期也將發生變化。
如果一個Activity從創建出來,到顯示,然後旋轉,那麼它將經歷:
onCreate()
->
onStart()
->
onResume()
->
用戶可以與Activity交互,此時屏幕進行旋轉,從豎屏變橫屏->
onPause()
->
onSaveInstanceState()
->
onStop()
->
onDestroy()
->
onCreate()
->
onStart()
->
onRestoreInstanceState()
->
onResume()
->
用戶可以與Activity交互;
可以看到,旋轉的時候onCreate()
函數會被再次調用。在這裡,如果擁有橫屏布局文件,onCreate()
中的setContentView()
將會使用橫屏的布局,如果沒有,依然使用默認的布局文件。
如果Activity從豎屏變成橫屏,那麼會先執行onDestroy()
,再進行一次onCreate()
創建的過程。這意味著之前界面上顯示的數據需要重新刷新一次。
假如之前刷新這些數據需要花費很長的時間,那就有必要認真的思考如何避免數據的再次刷新。
解決屏幕旋轉時Activity被create兩次的方法有兩種。
用onSaveInstanceState()
和onRestoreInstanceState()
可用用來保存和還原這些數據;
在AndroidManifest.xml
文件中,給這個Activity組件加上android:screenOrientation="orientation|screenSize"
的屬性就可以了;
......
這種Activity從創建出來,到顯示,然後旋轉,那麼它將經歷:
onCreate()
->
onStart()
->
onResume()
->
用戶可以與Activity交互,此時屏幕進行旋轉,從豎屏變橫屏->
onConfigurationChanged()
;
如此一來,這個Activity在旋轉時就不會重走銷毀、創建的過程了,而只是在旋轉後經歷一個onConfigurationChanged()
。這種情況下,如果存在它對應的橫屏布局文件,那麼這個布局也不會被使用到,因為onCreate()
並沒有被調用到。
當設備的系統設置發生變化時,例如橫豎屏切換、語言變化,可以被Activity感知到。
系統設置發生變化可以通知到Activity,
在AndroidManifest.xml
文件當中,給對應的Activity標簽,添加android:configChanges
屬性,例如
android:configChanges="screenSize|orientation">
在需要在實現Activity的代碼中做出相應的修改:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
//從newConfig中獲取感興趣的系統配置變化事件,例如屏幕方向是否變化,系統語言是否變化等等
if(Configuration.ORIENTATION_PORTRAIT ==
newConfig.orientation) {
}
}
在manifest中指定關注的是screenSize
和orientation
,那麼當手機從橫屏變化成豎屏(或者豎屏變化成橫屏)的時候,這個函數就會被調用,就可以在這裡添加我們需要的代碼。
系統變化的種類很多,除了screenSize
和orientation
還有:keyboardHidden
locale
fontScale
等等。
我們可以用兩種方法處理設備的旋轉,
讓Activity不跟隨設備方向的旋轉而旋轉,它只有豎屏(或只有橫屏)的界面。要做到這一點很容易,在AndroidManifest.xml
文件中,給這個Activity組件加上android:screenOrientation="portrait"
(保持豎屏)或者android:screenOrientation="landscape"
(保持橫屏)的屬性就可以了;
<code class="language-xml hljs "><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.anddle.anddleplayer"> <application ......=""> <activity android:name=".VideoListActivity" android:screenorientation="landscape"> </activity> ...... </application> </manifest></code>
讓Activity跟隨設備方向的旋轉而旋轉。
采用章節3.2中介紹的方法。
Location Strategies注:本指南中描述的策略適用於平台定位API中android.location。該谷歌位置服務API,谷歌Play的一部分服務,提供了
開發之前大約從去年開始吧, 也可能是前年 Html5好像火得不得了, 不得了...總能從網上聽說到 XXX混合開發, 為了緊跟潮流(雖然有點兒晚了), 咱們也看看Andr
把github上的PagerSlidingTabStrip稍作修改: tab的文字顏色選中變色(原版文字不變色) 栗子:http://download.csdn.ne
BroadcastReceiver除了接收用戶所發送的廣播消息之外,還有一個重要的用途:接收系統廣播。如果應用需要在系統特定時刻執行某些操作,就