1. 請描述下Activity的生命週期。
必調用的三個方法:onCreate() --> onStart() --> onResume(),用AAA表示
(1)父Activity啟動子Activity,子Actvity退出,父Activity調用順序如下
AAA --> onFreeze() --> onPause() --> onStop() --> onRestart() --> onStart(),onResume() …
(2)使用者點擊Home,Actvity調用順序如下
AAA --> onFreeze() --> onPause() --> onStop() -- Maybe --> onDestroy() – Maybe
(3)調用finish(), Activity調用順序如下 AAA --> onPause() --> onStop() --> onDestroy()
(4)在Activity上顯示dialog, Activity調用順序如下 AAA
(5)在父Activity上顯示透明的或非全屏的activity,Activity調用順序如下 AAA --> onFreeze() --> onPause()
(6)裝置進入睡眠狀態,Activity調用順序如下 AAA --> onFreeze() --> onPause()
Activity有三個狀態: 當它在螢幕前台時(位於當前任務堆棧的頂部),它是啟用或運行狀態。它就是響應使用者操作的Activity。當它上面有另外一個Activity,使它失去了焦點但仍然對使用者可見時(如右圖),它處於暫停狀態。 在它之上的Activity沒有完全覆蓋螢幕,或者是透明的,被暫停Activity仍然對使用者可見,並且是存活狀態(它保留著所有的狀態和成員資訊並保持和視窗管理器的串連)。如果系統處於記憶體不足時會殺死這個Activity。當它完全被另一個Activity覆蓋時則處於停止狀態。它仍然保留所有的狀態和成員資訊。然而對使用者是不可見的,所以它的視窗將被隱藏,如果其它地方需要記憶體,則系統經常會殺死這個Activity。當Activity從一種狀態轉變到另一種狀態時,會調用以下保護方法來通知這種變化:
void onCreate(Bundle savedInstanceState)、void onStart()、void onRestart()、void onResume()、void onPause()、void onStop()、void onDestroy() 這七個方法定義了Activity的完整生命週期。實現這些方法可以協助我們監視其中的三個嵌套生命週期迴圈:
Activity的完整生命週期自第一次調用onCreate()開始,直至調用onDestroy()為止。Activity在onCreate()中設定所有“全域”狀態以完成初始化,而在onDestroy()中釋放所有系統資源。例如,如果Activity有一個線程在後台運行從網路下載資料,它會在onCreate()建立線程,而在 onDestroy() 銷毀線程。Activity的可視生命週期自onStart()調用開始直到相應的onStop()調用結束。在此期間,使用者可以在螢幕上看到Activity,儘管它也許並不是位於前台或者也不與使用者進行互動。在這兩個方法之間,我們可以保留用來向使用者顯示這個Activity所需的資源。例如,當使用者不再看見我們顯示的內容時,我們可以在onStart()中註冊一個 BroadcastReceiver來監控會影響UI的變化,而在onStop()中來注消。onStart() 和 onStop() 方法可以隨著應用程式是否為使用者可見而被多次調用。 Activity的前台生命週期自onResume()調用起,至相應的onPause()調用為止。在此期間,Activity位於前台最上面並與使用者進行互動。Activity會經常在暫停和恢複之間進行狀態轉換——例如當裝置轉入休眠狀態或者有新的Activity啟動時,將調用onPause() 方法。當Activity獲得結果或者接收到新的Intent時會調用onResume() 方法。關於前台生命週期迴圈的例子請見PPT下方備忘欄。
應用程式啟動的過程:
onCreate()->onStart()->onResume()
當有一個新的Activity開啟(完全覆蓋):onPause()->onStop()
當有一個新的Activity開啟(不完全覆蓋):onPause()/<重新啟動>onResume()
從新返回前面一個Activity(完全覆蓋):onRestart()->onStart()->onResume()
摧毀的生命週期: onPause()->onStop()->onDestroy()
Activity的onSaveInstanceState()和 onRestoreInstanceState()方法當應用遇到意外情況(如:記憶體不足、使用者直接按Home鍵)由系統銷毀一個Activity時,onSaveInstanceState()會被調用。但是當使用者主動去銷毀一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。因為在這種情況下,使用者的行為決定了不需要儲存Activity的狀態。通常onSaveInstanceState()只適合用於儲存一些臨時性的狀態,而onPause()適合用於資料的持久化儲存。另外,當螢幕的方向發生了改變, Activity會被摧毀並且被重新建立,如果你想在Activity被摧毀前緩衝一些資料,並且在Activity被重新建立後恢複緩衝的資料。可以重寫Activity的 onSaveInstanceState() 和onRestoreInstanceState()方法.
2. 如果背景Activity由於某原因被系統回收了,如何在被系統回收之前儲存目前狀態?
onSaveInstanceState()
當你的程式中某一個Activity A在運行時,主動或被動地運行另一個新的Activity B,這個時候A會執行onSaveInstanceState()。B完成以後又會來找A,這個時候就有兩種情況:一是A被回收,二是A沒有被回收,被回收的A就要重新調用onCreate()方法,不同於直接啟動的是這回onCreate()裡是帶上了參數savedInstanceState;而沒被收回的就直接執行onResume(),跳過onCreate()了。
3. 如何將一個Activity設定成視窗的樣式。
在AndroidManifest.xml 中定義Activity的地方一句話android:theme="@android:style/Theme.Dialog"或android:theme="@android:style/Theme.Translucent"就變成半透明的
4. 如何退出Activity?如何安全退出已調用多個Activity的Application?
對於單一Activity的應用來說,退出很簡單,直接finish()即可。
當然,也可以用killProcess()和System.exit()這樣的方法。
5. 請介紹下Android中常用的五種布局。
FrameLayout(架構布局),LinearLayout (線性布局),AbsoluteLayout(絕對布局),RelativeLayout(相對布局),TableLayout(表格版面配置)
6. 請介紹下Android的資料存放區方式。
一.SharedPreferences方式
二.檔案儲存體方式
三.SQLite資料庫方式
四.內容提供器(Content provider)方式
五. 網路儲存方式
7. 請介紹下ContentProvider是如何?資料共用的。
建立一個屬於你自己的Content provider或者將你的資料添加到一個已經存在的Content provider中,前提是有相同資料類型並且有寫入Content provider的許可權。
8. 如何啟用Service,如何停用Service。
採用Context.startService()方法啟動服務有關的生命週期方法onCreate()->onStart()->onDestroy()
onCreate()該方法在服務被建立時調用,該方法只會調用一次,無論調用多少次
startService()或binService()方法,服務也只被建立一次.
採用Context.bindService()方法啟動服務有關的生命週期方法 onCreate()->onBind() -> onUnbind() -> onDestroy()
9. 註冊廣播有幾種方式,這些方式有何優缺點?請談談Android引入廣播機制的用意。
在android下,要想接受廣播資訊,那麼這個廣播接收器就得我們自己來實現了,我們可以繼承BroadcastReceiver,就可以有一個廣播接受器了。有個接受器還不夠,我們還得重寫BroadcastReceiver裡面的onReceiver方法,當來廣播的時候我們要幹什麼,這就要我們自己來實現,不過我們可以搞一個資訊防火牆。具體的代碼:
public class SmsBroadCastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Object[] object = (Object[])bundle.get("pdus"); SmsMessage sms[]=new SmsMessage[object.length]; for(int i=0;i<object.length;i++) { sms[0] = SmsMessage.createFromPdu((byte[])object[i]); Toast.makeText(context, "來自"+sms[i].getDisplayOriginatingAddress()+" 的訊息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show(); } //終止廣播,在這裡我們可以稍微處理,根據使用者輸入的號碼可以實現簡訊防火牆。 abortBroadcast(); } }
當實現了廣播接收器,還要設定廣播接收器接收廣播資訊的類型,這裡是資訊:android.provider.Telephony.SMS_RECEIVED
我們就可以把廣播接收器註冊到系統裡面,可以讓系統知道我們有個廣播接收器。這裡有兩種,一種是代碼動態註冊:
//產生廣播處理
smsBroadCastReceiver = new SmsBroadCastReceiver();
//執行個體化過濾器並設定要過濾的廣播
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
//註冊廣播
BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter);
一種是在AndroidManifest.xml中配置廣播
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="spl.broadCastReceiver" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".BroadCastReceiverActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--廣播註冊--> <receiver android:name=".SmsBroadCastReceiver"> <intent-filter android:priority="20"> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> </application> <uses-sdk android:minSdkVersion="7" /> <!-- 許可權申請 --> <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> </manifest>
兩種註冊類型的區別是:
1)第一種不是常駐型廣播,也就是說廣播跟隨程式的生命週期。
2)第二種是常駐型,也就是說當應用程式關閉後,如果有資訊廣播來,程式也會被系統調用自動運行。
10. 請解釋下在單執行緒模式中Message、Handler、Message Queue、Looper之間的關係。
使用Handler在子線程中如何更新UI控制項的顯示(核心重點)如果在主線程裡面執行一項比較耗時的工作,會使得主線程因為繁忙而無法處理使用者的輸入事件.如果使用者的輸入事件如果沒能在5s內得到響應,程式就會報應用無響應錯誤對話方塊.
開啟一條線程,new Thread(new DownLoadTask(path,saveDir)).start();讓子線程去執行操作...
private final class DownLoadTask implements Runnable....
主線程負責UI控制項的重繪,在子線程裡對UI控制項的值進行更新,更新後的值死無法重繪在螢幕上的.
private Handler handler = new Handler();
使用者建立Handler對象所在的線程的訊息佇列裡發送訊息.
然後在子線程的onDownLoadSize(int size)發送訊息
Message msg = new Message(); msg.getData().putInt(size,size); handler.sendMessage(msg);
訊息處理器--專門處理本線程所綁定的訊息佇列裡面的訊息. 如果訊息佇列裡面沒有訊息,訊息處理器會處於等待狀態.
當有訊息進入到訊息佇列裡面,就會喚醒訊息處理器就會從訊息佇列中擷取訊息.
運行在主線程裡面
Message msg = getTopMessage(); Handler handler = msg.target; handler.handleMessage(msg);
所以應該重寫Handle類中的handleMessage()方法android 系統提供的 Service類(local) 與 Thread類什麼區別啊,我怎麼感覺Thread類完全可以做到啊?很簡單的區別 Service類 是可以供其他應用程式來調用這個Service的而Thread只是在本類中在使用 如果本類關閉 那麼這個thread也就下崗了而Service類則不會 你可以百度一個簡單的 開機提示的例子 你就明白了 當開機以後 Service實際上已經就在運行了 而Thread則必須你來調用他 。