編輯:關於Android編程
首先,Activity是Android系統中的四大組件之一,可以用於顯示View。Activity是一個與用記交互的系統模塊,幾乎所有的 Activity都是和用戶進行交互的,但是如果這樣就能說Activity主要是用來顯示View就不太正確了。它不僅顯示數據,也傳輸數據,很多程序中使用到MVC模式,
M(Model 模型):Model是應用程序的主體部分,所有的業務邏輯都應該寫在這裡,在Android中Model層與JavaEE中的變化不大,如:對數據庫的操 作,對網絡等的操作都放在該層(但不是說它們都放在同一個包中,可以分開放,但它們統稱為Model層)。
V(View 視圖):是應用程序中負責生成用戶界面的部分,也是在整個MVC架構中用戶唯一可以看到的一層,接收用戶輸入,顯示處理結果;在Android應用中一般 采用XML文件裡德界面的描述,使用的時候可以非常方便的引入,當然也可以使用JavaScript+Html等方式作為View。
C(Controller控制層)android的控制層的重任就要落在眾多的activity的肩上了,所以在這裡就要建議大家不要在activity中寫太多的代碼,盡量能過activity交割Model業務邏輯層處理。
在Android中Activity主要是用來做控制的,它可以選擇要 顯示的View,也可以從View中獲取數據然後把數據傳給Model層進行處理,最後再來顯示出處理結果。
也有一種新的MVP模式:
模型(Model):負責處理數據的加載或者存儲,比如從網絡或本地數據庫獲取數據等;
視圖(View):負責界面數據的展示,與用戶進行交互;
主持人(Presenter):相當於協調者,是模型與視圖之間的橋梁,將模型與視圖分離開來。
其中的主要內容這裡不介紹,這裡告訴大家,不僅僅需要學習MVC模式,也需要學習MVP模式,這裡特別不建議大家這樣寫:將所有的事情都交給Activity來完成,比如網絡請求,業務邏輯處理,這樣造成了Activity特別臃腫,一個大的Activity,在後期很難維護。MVC如果用不好,就會將所有的信息都放在Activity上。protected void onCreate(Bundle icicle);
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy();
要想了解Activity,那麼就必須要清楚Activity的生命周期,圖片是最生動的,如下圖:
上面一張圖有可能有些模糊,那請看下面這張圖():
整個Activity周期,activity創建時調用Oncreate(),這個時候調用setContentView(View)函數,加載xml布局文件。調用OnStart()方法,Activity顯示在屏幕上,這個時候還不能與用戶交互,調用OnResume()方法,用戶與Activity進行交互,當前Activity被切換的時候,這個時候調用OnPause()方法,在該方法中保存一些持久數據和釋放占用的資源,這個時候,屏幕還是可見,調用onStop()方法,Activity切換到後台,用戶不可見。onDestroy()activity終止。
Activity的響應時間
當前Activity所在的線程為主線程,它的響應時間為5秒,如果在當前運行的Activity中進行耗時的操作且響應時間起過5秒,那麼程序就會報ANR錯誤。所以,這也是不建議在Activity中寫太多復雜代碼的原因之一。
當然,有些代碼只能寫在Activity中,不然就運行不了(它們不是生命周期方法),比如你想要獲得android系統或者硬件一的些信息,就必須在Activity中寫出來,如果單獨寫一個工具類獲得不了。
Activity棧
Activity棧保存了已經啟動並且還沒有終止的所有的Activity,並且我們知道棧是遵從“後進先出”的規則,那麼Activity棧同樣也遵從這樣的規則。
Activity 的狀態與其在Activity棧的位置有著密切的關系。不僅如此,Android系統在資源不足時,也是通過Activity棧來選擇哪些 Activity是可以被終止的,一般來講,Activity系統會優先選擇終止處於目前是停止狀態並且比較靠近Activity棧底的 Activity。
1. Activity的4種狀態
Activity的生命周期指Activity從啟動到銷毀的過程,Activity有4種狀態:
(1)活動(Active)狀態:這時候Activity處於棧頂,且是可見的,有焦點的,能夠接收用戶輸入前 景Activity。Runtime將試圖不惜一切代價保持它活著,甚至殺死其他Activity以確保它有它所需的資源。當另一個Activity變成Active時,當前 的將變成Paused狀態。
(2)暫停(Paused)狀態:在 某些情況下,你的Activity是可見的,但沒有焦 點,在這時候,Actvity處於Paused狀態。例如,如果有一個透明或非全屏幕上的Activity在你的Actvity上面,你的 Activity將。當處於Paused狀態時,該Actvity仍被認為是Active的,但是它不接受用戶輸入事件。在極端情況下,Runtime將 殺死Paused Activity,以進一步回收資源。當一個Actvity完全被遮住時,它將進入Stopped狀態。
(3)停止(Stopped)狀態:當Activity是不可見的時,Activity處於Stopped狀態。Activity將繼續保留在內存中保持當前的所有狀態和成員信息,假 設系統別的地方需要內存的話,這時它是被回收對象的主要候選。當Activity處於Stopped狀態時,一定要保存當前數據和當前的UI狀態,否則一 旦Activity退出或關閉時,當前的數據和UI狀態就丟失了。
(4)非活動(Inactive)狀態:Activity被殺掉以後或者被啟動以前,處於Inactive狀態。這時Activity已被移除從Activity堆棧中,需要重新啟動才可以顯示和使用。
一些調用實例
1) 啟動Activity:onCreate()->onStart()->onResume()->Activityis running
2) 按back鍵返回:onPause()->onStop()->onDestroy() 再次啟動時:onCreate()->onStart()->onResume()->Activityis running
3). 按home鍵返回:onPause()->onStop() 再次啟動時:onRestart()->onStart()->onResume()->Activity isrunning
4) 切換到別的Activity(當前Activity不finish),或者采用這個,啟動程序進入Activity,按Home鍵進入桌面,然後長按Home建點擊該應用重新進入Activity:onPause()->onStop() 再次啟動時:onRestart()->onStart()->onResume()->Activityis running
5) 切換到別的Activity(當前Activity finish):onPause()->onStop()->onDestroy() 再次啟動時:onCreate()->onStart()->onResume()->Activity isrunning
6)然後按掛機鍵,進入鎖屏界面,然後從鎖屏界面返回Activity:onPause()->onResume()
7)切換到另一個Activity對話框界面,然後按返回鍵返回原來的Activity:onPause()->onResume()
8)啟動本Activity中創建的對話框(彈出Toast和AlertDialog),按返回鍵從Dialog返回:Activity的狀態始終未變
9)無論現在是onPause狀態還是onStop狀態,當系統的內存不足時,都會將該Activity殺死,當再次進入該Activity重新創建。這意味著,如果發生這種情況,可能我們的onDestroy(如果在停止狀態被殺死),甚至是onStop都沒有得到執行(如果在暫停狀態被殺死),因此,一些重要的數據和狀態,需要在這種情況下也得到保存,Google為我們專門提供了一個回調函數,就是onSaveInstanceState(Bundle),通過該函數,可以將這些重要的數據在銷毀前進行保存,然後再onCreate時重新讀
10)橫豎屏切換時候activity的生命周期:
1、不設置Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次
2、設置Activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命周期,切橫、豎屏時只會執行一次
3、設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命周期,只會執行onConfigurationChanged方法
11)當在MainActivity中按back鍵,退出時,或者在代碼中調用finish(),finishActivity()方法,最終就會走到onDestory()。
tips:
在多數情況下,你是不需要顯式地調用finish…()方法去銷毀一個activity。在將要討論到的activity生命周期裡,你可以知道,Android系統會為你管理activity的生命周期,所以你並不需要顯式銷毀activity(即調用finish類方法)。顯式地調用finish類方法,會對用戶的體驗產生不利的影響,除非你確實是不希望用戶返回到此activity(界面),才去顯式調用finish類方法。
特殊函數
1. startActivityForResult / onActivityResult / setResult 函數組合
提到這類函數組合,相信只要有過一段時間Android開發的來說都很熟悉了,此函數組合主要用於如下場景:用戶在A Activity上點擊某個按鈕,跳轉到B Activity,然後用戶在B Activity上進行一些具體的操作,待操作完成後返回到A Activity,同時常常將B Activity中操作的一些數據返回到A Activity中。
再如上場景中,A -> B 需要通過startActivityForResult()方式打開。具體方式如下:
1 button.setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View v) { 4 Intent intent = new Intent(AActivity.this, BActivity.class); 5 startActivityForResult(intent, 1); 6 } 7 });
其中,startActivityForResult第一個參數為Intent,因此,對於需要傳遞額外參數時,可以通過Intent直接傳遞。其中Bundle為可選參數。第二個參數為requestCode,即業務請求碼。
B Activity中,在處理完或相應完用戶操作後,自身結束前,需要通過setResult將數據回傳給A。
1 btnClose.setOnClickListener(new View.OnClickListener() { 2 public void onClick(View v) { 3 4 // 需要返回的數據存入到intent中 5 Intent intent = new Intent(); 6 intent.putExtra("name", "corn"); 7 8 //設置返回數據 9 setResult(RESULT_OK, intent); 10 11 //關閉Activity 12 finish(); 13 } 14 });
接下來A接手B回傳的數據。
1 @Override 2 protected void onActivityResult(int requestCode, int resultCode, Intent intent) { 3 String name; 4 // 取得B回傳的數據 5 if(resultCode == RESULT_OK ){ 6 name = intent.getStringExtra("name"); 7 } else if(resultCode == RESULT_CANCELED){ 8 // ... 9 } 10 }
此函數組合中,需要注意如下問題:
1.根據項目的實際需要進行定義,特別需要注意的是,requestCode必須 >= 0,否則此類效果失效,其效果將變成startActivity()效果;
2.resultCode表示B中處理後的結果狀態,系統內部定義了RESULT_OK、RESULT_CANCELED和RESULT_FIRST_USER三種狀態。當然,自己可以定義成任何int型標識狀態。
3.有時在復雜的業務邏輯中,可能存在A startActivityForResult 到B,同時C也startActivityForResult 到B,且requestCode可能相同(以表示同意業務請求),這時可能需要在B中針對性的判斷此請求來源(來自於A還是C)。此時,可以通過intent傳參形式。相信大家都比較熟悉,其實Activity類中也提供了相應的函數可以獲取到來源Activity的類型函數:getCallingActivity()。但需要注意此函數僅針對startActivityForResult有效,返回的結果中包含完成包名。
4.A中回調函數調用時機需要注意,其調用發生在B的onPause之後,A的onRestart之前(如果B完成遮住了A),且必然在onResume之前。
5.此函數組合針對B的啟動模式為singleTask或singInstance將會失效。此時,onActivityResult將在A的onpause之後直接回調,且resultCode為RESULT_CANCELED。
2.moveTaskToBack
如《Android總結篇系列:Activity生命周期》一文中有提到的,模擬現在的主流應用最後按Back鍵時不是強制退出應用或直接結束根Activity,而是采取類Home鍵效果,此時可以直接通過此函數實現,非常實用。
1 @Override 2 public void onBackPressed() { 3 moveTaskToBack(true); 4 }
此方法直接將當前Activity所在的Task移到後台,同時保留activity順序和狀態。
3.onNewIntent調用時機
onNewIntent只有在以下場景才會回調:當前通過Intent方式啟動的Activity不是重新完整新建實例,而是復用之前已經存在的實例(如被設置了singleTop啟動模式,或FLAG_ACTIVITY_SINGLE_TOP intent flags或設置了Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP等,以此類推,被設置了singleTask或single。此時都會執行到onNewIntent)。onNewIntent調用後,將繼續回調onRestart,onResume...
4.onSaveInstanceState /onRestoreInstanceState調用時機
onSaveInstanceState調用時機:當Activity變得“容易”被系統銷毀時,onSaveInstanceState即被回調,除非該activity是被用戶主動銷毀的,例如當用戶按BACK鍵的時候。
注意上面的雙引號,何為“容易”?言下之意就是該activity還沒有被銷毀,而僅僅是一種可能性。這種可能性有哪些?
1.當用戶按下HOME鍵時;
2.長按HOME鍵,選擇運行其他的程序時;
3.按下電源按鍵(關閉屏幕顯示)時;
4.從activity A中啟動一個新的activity時;
5.屏幕方向切換時,例如從豎屏切換到橫屏時。
onRestoreInstanceState調用時機,activity A“確實”被系統銷毀了,而如果僅僅是停留在有這種可能性的情況下,則該方法不會被調用。另外,onRestoreInstanceState的bundle參數也會傳遞到onCreate方法中,也可以選擇在onCreate方法中做數據還原。
1 @Override 2 protected void onRestoreInstanceState(Bundle savedInstanceState) { 4 super.onRestoreInstanceState(savedInstanceState); 5 savedInstanceState.getString("name", ""); 7 } 9 @Override 10 public void onSaveInstanceState(Bundle savedInstanceState) { 11 super.onSaveInstanceState(savedInstanceState); 12 savedInstanceState.putString("name", "corn"); 13 }
或在onCreate中:
1 public class AActivity extends ActionBarActivity { 2 3 private String name; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.a); 9 10 if (savedInstanceState != null) { 11 name = savedInstanceState.getString("name"); 12 } 13 14 } 15 16 }
需要注意的是,onSaveInstanceState被調用時,其調用發生在Activity生命周期中具體的位置。以A->B為例,A中onSaveInstanceState調用發生在A:onPause -> B:onCreate -> B:onResume -> A:onSaveInstanceState -> A:onStop。
onSaveInstanceState常常用於存儲應用程序中當前Activity中重要的狀態數據,以免Activity被系統意外殺掉的情況下當用戶再次回來時不能找到之前的狀態。如同一個Activity中使用多個fragment實現菜單功能時,最好需要在此函數中記錄下當前菜單對應的fragment id等。
Android 背景圖片的縮放 ONE Goal ,ONE Passion !我們看到一些效果,控件中的背景圖片會慢慢變大,但是控件不會隨著圖片的放大而變大.效
Unity本身沒有自帶Toast.makeText()的接口方法,但是這個小功能又是我們做手游開發的時候經常需要用到的。這時候我們可以利用Android Studio或者
首先推薦一下鴻洋大大的打造個性的圖片預覽與多點觸控視頻教程,這套教程教我們一步一步實現了多點觸控實現對圖片的平移和縮放的功能,這篇文章我將在鴻洋大大的基礎之上做了一些擴展
簡介看段Android官方的簡介Class OverviewDisplays text to the user and optionally allows them to