2. 橫豎屏切換時候 activity 的生命周期
1. 不設(shè)置 Activity 的 android:configChanges 時 , 切屏?xí)匦抡{(diào)用各個生命周期 , 切橫屏?xí)r會執(zhí)行一次 , 切豎屏?xí)r會執(zhí)行兩次 .
2. 設(shè)置 Activity 的 android:configChanges=”orientation” 時 , 切屏還是會重新調(diào)用各個生命周期 , 切橫、豎屏?xí)r只會執(zhí)行一次 .
3. 設(shè)置 Activity 的 android:configChanges=”orientation|keyboardHidden” 時 , 切屏不會重新調(diào)用各個生命周期 , 只會執(zhí)行 onConfigurationChanged 方法 .
3.android 中的動畫有哪幾類,它們的特點(diǎn)和區(qū)別是什么 ?
兩種,一種是 Tween 動畫、還有一種是 Frame 動畫。 Tween 動畫,這種實(shí)現(xiàn)方式可以使視圖組件移動、放大、縮小以及產(chǎn)生透明度的變化 ; 另一種 Frame 動畫,傳統(tǒng)的動畫方法,通過順序的播放排列好的圖片來實(shí)現(xiàn),類似電影。
4. 一條最長的短信息約占多少 byte?
中文70( 包括標(biāo)點(diǎn)) ,英文160 ,160 個字節(jié)。
5.handler 機(jī)制的原理
andriod 提供了 Handler 和 Looper 來滿足線程間的通信。 Handler 先進(jìn)先出原則。 Looper 類用來管理特定線程內(nèi)對象之間的消息交換 (Message Exchange) 。
1)Looper: 一個線程可以產(chǎn)生一個 Looper 對象,由它來管理此線程里的 Message Queue( 消息隊(duì)列 ) 。
2)Handler: 你可以構(gòu)造 Handler 對象來與 Looper 溝通,以便 push 新消息到 Message Queue 里; 或者接收 Looper 從 Message Queue 取出 ) 所送來的消息。
3) Message Queue( 消息隊(duì)列 ): 用來存放線程放入的消息。
4) 線程: UI thread 通常就是 main thread ,而 Android 啟動程序時會替它建立一個 Message Queue 。
6. 什么是嵌入式實(shí)時操作系統(tǒng) , Android 操作系統(tǒng)屬于實(shí)時操作系統(tǒng)嗎 ?
嵌入式實(shí)時操作系統(tǒng)是指當(dāng)外界事件或數(shù)據(jù)產(chǎn)生時,能夠接受并以足夠快的速度予以處理,其處理的結(jié)果又能在規(guī)定的時間之內(nèi)來控制生產(chǎn)過程或?qū)μ幚硐到y(tǒng)作出快速響應(yīng),并控制所有實(shí)時任務(wù)協(xié)調(diào)一致運(yùn)行的嵌入式操作系統(tǒng)。主要用于工業(yè)控制、 軍事設(shè)備、 航空航天等領(lǐng)域?qū)ο到y(tǒng)的響應(yīng)時間有苛刻的要求,這就需要使用實(shí)時系統(tǒng)。又可分為軟實(shí)時和硬實(shí)時兩種,而 android 是基于linux 內(nèi)核的,因此屬于軟實(shí)時。
7.android 中線程與線程,進(jìn)程與進(jìn)程之間如何通信
1 、一個 Android 程序開始運(yùn)行時,會單獨(dú)啟動一個 Process 。
默認(rèn)情況下,所有這個程序中的 Activity 或者 Service 都會跑在這個 Process 。
默認(rèn)情況下,一個 Android 程序也只有一個 Process ,但一個 Process 下卻可以有許多個 Thread。
2 、一個 Android 程序開始運(yùn)行時,就有一個主線程 Main Thread 被創(chuàng)建。該線程主要負(fù)責(zé) UI 界面的顯示、更新和控件交互,所以又叫 UI Thread 。
一個 Android 程序創(chuàng)建之初,一個 Process 呈現(xiàn)的是單線程模型 — 即 Main Thread ,所有的任務(wù)都在一個線程中運(yùn)行。所以, Main Thread 所調(diào)用的每一個函數(shù),其耗時應(yīng)該越短越好。而對于比較費(fèi)時的工作,應(yīng)該設(shè)法交給子線程去做,以避免阻塞主線程(主線程被阻塞,會導(dǎo)致程序假死 現(xiàn)象)。
3 、 Android 單線程模型: Android UI 操作并不是線程安全的并且這些操作必須在 UI 線程中執(zhí)行。如果在子線程中直接修改 UI ,會導(dǎo)致異常。
8.Android dvm 的進(jìn)程和 Linux 的進(jìn)程 , 應(yīng)用程序的進(jìn)程是否為同一個概念
DVM 指 dalivk 的虛擬機(jī)。每一個 Android 應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,都擁有一個獨(dú)立的 Dalvik 虛擬機(jī)實(shí)例。而每一個 DVM 都是在 Linux 中的一個進(jìn)程,所以說可以認(rèn)為是同一個概念。
9.sim 卡的 EF 文件有何作用
sim 卡的文件系統(tǒng)有自己規(guī)范,主要是為了和手機(jī)通訊, sim 本 身可以有自己的操作系統(tǒng),EF 就是作存儲并和手機(jī)通訊用的
10.android 中的動畫有哪幾類,它們的特點(diǎn)和區(qū)別是什么 ?
兩種,一種是 Tween 動畫、還有一種是 Frame 動畫。 Tween 動畫,這種實(shí)現(xiàn)方式可以使視圖組件移動、放大、縮小以及產(chǎn)生透明度的變化 ; 另一種 Frame 動畫,傳統(tǒng)的動畫方法,通過順序的播放排列好的圖片來實(shí)現(xiàn),類似電影。
11. 讓 Activity 變成一個窗口: Activity 屬性設(shè)定
講點(diǎn)輕松的吧 , 可能有人希望做出來的應(yīng)用程序是一個漂浮在手機(jī)主界面的東西,那么很 簡單你只需要設(shè)置 一下 Activity 的主題就可以了在 AndroidManifest.xml 中定義 Activity 的 地方一句話:
Xml 代碼
1. android :theme=”@android:style/Theme.Dialog”
這就使你的應(yīng)用程序變成對話框的形式彈出來了,或者
Xml 代碼
1. android:theme=”@android:style/Theme.Translucent”
就變成半透明的, [ 友情提示 -.-] 類似的這種 activity 的屬性可以在 android.R.styleable 類的AndroidManifestActivity 方法中看到, AndroidManifest.xml 中所有元素的屬性的介紹都可以參考這個類 android.R.styleable
上面說的是屬性名稱,具體有什么值是在 android.R.style 中 可以看到,比如這個”@android:style/Theme.Dialog” 就對應(yīng)于 android.R.style.Theme_Dialog ,(‘_’ 換成 ‘.’ < — 注意:這個是文章內(nèi)容不是笑臉 ) 就可以用在描述文件 中了 , 找找類定義和描述文件中的對應(yīng)關(guān)系就都明白了。
12. 如何將 SQLite 數(shù)據(jù)庫 (dictionary.db 文件 ) 與 apk 文件一起發(fā)布 ?
解答:可以將 dictionary.db 文件復(fù)制到 Eclipse Android 工程中的 res aw 目錄中。所有在 res aw 目錄中的文件不會被壓縮,這樣可以直接提取該目錄中的文件?梢詫 dictionary.db 文件復(fù)制到 res aw 目錄中
13. 如何將打開 res aw 目錄中的數(shù)據(jù)庫文件 ?
解答:在 Android 中不能直接打開 res aw 目錄中的數(shù)據(jù)庫文件,而需要在程序第一次啟動時將該文件復(fù)制到手機(jī)內(nèi)存或 SD 卡的某個目錄中,然后再打開該數(shù)據(jù)庫文件。復(fù)制的基本方法是使用getResources().openRawResource 方法獲得 res aw 目錄中資源的 InputStream 對象,然后將該InputStream 對象中的數(shù)據(jù)寫入其他的目錄中相應(yīng)文件中。在 Android SDK 中可以使用SQLiteDatabase.openOrCreateDatabase 方法來打開任意目錄中的 SQLite 數(shù)據(jù)庫文件。
14. 在 android 中 mvc 的具體體現(xiàn)
MVC 是 Model,View,Controller 的縮寫,從上圖可以看出 MVC 包含三個部分:
.. 模型( Model )對象:是應(yīng)用程序的主體部分,所有的業(yè)務(wù)邏輯都應(yīng)該寫在該
層。
.. 視圖( View )對象:是應(yīng)用程序中負(fù)責(zé)生成用戶界面的部分。也是在整個
MVC 架構(gòu)中用戶唯一可以看到的一層,接收用戶的輸入,顯示處理結(jié)果。
.. 控制器( Control )對象:是根據(jù)用戶的輸入,控制用戶界面數(shù)據(jù)顯示及更新
Model 對象狀態(tài)的部分,控制器更重要的一種導(dǎo)航功能,想用用戶出發(fā)的相
關(guān)事件,交給 M 哦得了處理。
Android 鼓勵弱耦合和組件的重用,在 Android 中 MVC 的具體體現(xiàn)如下
1) 視圖層( view ) :一般采用 xml 文件進(jìn)行界面的描述,使用的時候可以非常方便的引入,當(dāng)然,如何你對 android 了解的比較的多了話,就一定可 以想到在 android 中也可以使用javascript+html 等的方式作為 view 層,當(dāng)然這里需要進(jìn)行 java 和 javascript 之間的通 信,幸運(yùn)的是, android 提供了它們之間非常方便的通信實(shí)現(xiàn)。
2) 控制層( controller ): android 的控制層的重 任通常落在了眾多的 acitvity 的肩上,這句話也就暗含了不要在 acitivity 中寫代碼,要通過 activity 交割 model 業(yè)務(wù)邏輯層處理, 這樣做的另外一個原因是 android 中的 acitivity 的響應(yīng)時間是 5s ,如果耗時的操作放在這里,程序就很容易被回收掉。
3) 模型層( model ): 對數(shù)據(jù)庫的操作、對網(wǎng)絡(luò)等的操作都應(yīng)該在 model 里面處理,當(dāng)然對業(yè)務(wù)計算等操作也是必須放在的該層的。
15.Android 系統(tǒng)的架構(gòu)
android 的系統(tǒng)架構(gòu)和其操作系統(tǒng)一樣,采用了分層的架構(gòu)。從架構(gòu)圖看, android 分為四個層,從高層到低層分別是應(yīng)用程序?qū)印?yīng)用程序框架層、系統(tǒng)運(yùn)行庫層和 linux 核心層。
1. 應(yīng)用程序
Android 會同一系列核心應(yīng)用程序包一起發(fā)布,該應(yīng)用程序包包括 email 客戶端, SMS 短消息程序,日歷,地圖,瀏覽器,聯(lián)系人管理程序等。所有的應(yīng)用程序都是使用 JAVA 語言編寫的。
2. 應(yīng)用程序框架
開發(fā)人員也可以完全訪問核心應(yīng)用程序所使用的 API 框架。該應(yīng)用程序的架構(gòu)設(shè)計簡化了組件的重用 ; 任何一個應(yīng)用程序都可以發(fā)布它的功能塊并且任何其它的應(yīng)用程序都可以使用其所發(fā)布的功能塊 ( 不過得遵循框架的安全性限制 ) 。同樣,該應(yīng)用程序重用機(jī)制也使用戶可以方便的替換程序組件。
隱藏在每個應(yīng)用后面的是一系列的服務(wù)和系統(tǒng) , 其中包括 ;
* 豐富而又可擴(kuò)展的視圖 (Views) ,可以用來構(gòu)建應(yīng)用程序, 它包括列表 (lists) ,網(wǎng)格 (grids),文本框 (text boxes) ,按鈕 (buttons) , 甚至可嵌入的 web 瀏覽器。
* 內(nèi)容提供器 (Content Providers) 使得應(yīng)用程序可以訪問另一個應(yīng)用程序的數(shù)據(jù) ( 如聯(lián)系人數(shù)據(jù)庫 ) , 或者共享它們自己的數(shù)據(jù)
* 資源管理器 (Resource Manager) 提供 非代碼資源的訪問,如本地字符串,圖形,和布局文件 ( layout files ) 。
* 通知管理器 (Notification Manager) 使得應(yīng)用程序可以在狀態(tài)欄中顯示自定義的提示信息。
* 活動管理器 ( Activity Manager) 用來管理應(yīng)用程序生命周期并提供常用的導(dǎo)航回退功能。
有關(guān)更多的細(xì)節(jié)和怎樣從頭寫一個應(yīng)用程序,請參考 如何編寫一個 Android 應(yīng)用程序 .
3. 系統(tǒng)運(yùn)行庫
1) 程序庫
Android 包含一些 C/C++ 庫,這些庫能被 Android 系統(tǒng)中不同的組件使用。它們通過 Android應(yīng)用程序框架為開發(fā)者提供服務(wù)。以下是一些核心庫:
* 系統(tǒng) C 庫 – 一個從 BSD 繼承來的標(biāo)準(zhǔn) C 系統(tǒng)函數(shù)庫 ( libc ) , 它是專門為基于 embedded linux 的設(shè)備定制的。
* 媒體庫 – 基于 PacketVideo OpenCORE; 該庫支持多種常用的音頻、視頻格式回放和錄制,同時支持靜態(tài)圖像文件。編碼格式包括 MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 。
* Surface Manager – 對顯示子系統(tǒng)的管理,并且為多個應(yīng)用程序提 供了 2D 和 3D 圖層的無縫融合。
* LibWebCore – 一個最新的 web 瀏覽器引擎用,支持 Android 瀏覽器和一個可嵌入的 web 視圖。
* SGL – 底層的 2D 圖形引擎
* 3D libraries – 基于 OpenGL ES 1.0 APIs 實(shí)現(xiàn) ; 該庫可以使用硬件 3D 加速 ( 如果可用 ) 或者使用高度優(yōu)化的 3D 軟加速。
* FreeType – 位圖 (bitmap) 和矢量 (vector) 字體顯示。
* SQLite – 一個對于所有應(yīng)用程序可用,功能強(qiáng)勁的輕型關(guān)系型數(shù)據(jù)庫引擎。
2)Android 運(yùn)行庫
Android 包括了一個核心庫,該核心庫提供了 JAVA 編程語言核心庫的大多數(shù)功能。
每一個 Android 應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,都擁有一個獨(dú)立的 Dalvik 虛擬機(jī)實(shí)例。Dalvik 被設(shè)計成一個設(shè)備可以同時高效地運(yùn)行多個虛擬系統(tǒng)。 Dalvik 虛擬機(jī)執(zhí)行 (.dex) 的 Dalvik 可執(zhí)行文件,該格式文件針對小內(nèi)存使用做了優(yōu)化。同時虛擬機(jī)是基于寄存器的,所有的類都經(jīng)由JAVA 編譯器編譯,然后通過 SDK 中 的 “ dx ” 工具轉(zhuǎn)化成 .dex 格式由虛擬機(jī)執(zhí)行。
Dalvik 虛擬機(jī)依賴于 linux 內(nèi)核的一些功能,比如線程機(jī)制和底層內(nèi)存管理機(jī)制。
4.Linux 內(nèi)核
Android 的核心系統(tǒng)服務(wù)依賴于 Linux 2.6 內(nèi)核,如安全性,內(nèi)存管理,進(jìn)程管理, 網(wǎng)絡(luò)協(xié)議棧和驅(qū)動模型。 Linux 內(nèi)核也同時作為硬件和軟件棧之間的抽象層。
16.Android 常用控件的信息
單選框 (RadioButton 與 RadioGroup) :
RadioGroup 用于對單選框進(jìn)行分組,相同組內(nèi)的單選框只有一個單選框被選中。
事件: setOnCheckedChangeListener() ,處理單選框被選擇事件。把RadioGroup.OnCheckedChangeListener 實(shí)例作為參數(shù)傳入。
多選框 (CheckBox):
每個多選框都是獨(dú)立的,可以通過迭代所有的多選框,然后根據(jù)其狀態(tài)是否被選中在獲取其值。
事件: setOnCheckChangeListener() 處理多選框被選擇事件。把CompoundButton.OnCheckedChangeListener 實(shí)例作為參數(shù)傳入
下拉列表框 (Spring) :
Spinner.getItemAtPosition(Spinner.getSelectedItemPosition()); 獲取下拉列表框的值。
事件: setOnItemSelectedListener(), 處理下拉列表框被選擇事件把AdapterView.OnItemSelectedListener 實(shí)例作為參數(shù)傳入;
拖動條 (SeekBar) :
SeekBar.getProgress() 獲取拖動條當(dāng)前值
事件 :setOnSeekBarChangeListener() ,處理拖動條值變化事件,把SeekBar.OnSeekBarChangeListener 實(shí)例作為參數(shù)傳入。
菜單 (Menu):
重寫 Activity 的 onCreatOptionMenu(Menu menu) 方法,該方法用于創(chuàng)建選項(xiàng)菜單,咋用戶按下手機(jī)的 “Menu” 按鈕時就會顯示創(chuàng)建好的菜單,在 onCreatOptionMenu(Menu Menu) 方法內(nèi)部可以調(diào)用 Menu.add() 方法實(shí)現(xiàn)菜單的添加。
重寫 Activity 的 onMenuItemSelected() 方法,該方法用于處理菜單被選擇事件。
進(jìn)度對話框 (ProgressDialog) :
創(chuàng)建并顯示一個進(jìn)度對話框: ProgressDialog.show(ProgressDialogActivity.this,” 請稍等 ” , “數(shù)據(jù)正在加載中 ….” , true) ;
設(shè)置對話框的風(fēng)格: setProgressStyle()
ProgressDialog.STYLE_SPINNER 旋轉(zhuǎn)進(jìn)度條風(fēng)格 ( 為默認(rèn)風(fēng)格 )
ProgressDialog.STYLE_HORIZONTAL 橫向進(jìn)度條風(fēng)格
17. 請介紹下 Android 中常用的五種布局
Android 布局是應(yīng)用界面開發(fā)的重要一環(huán),在 Android 中,共有五種布局方式,分別是:FrameLayout (框架布局), LinearLayout (線性布局),
AbsoluteLayout (絕對布局), RelativeLayout (相對布局), TableLayout (表格布局)。
1.FrameLayout
這個布局可以看成是墻腳堆東西,有一個四方的矩形的左上角墻腳,我們放了第一個東西,要再放一個,那就在放在原來放的位置的上面,這樣依次的放,會蓋住原來的東西。這個布局比較簡單,也只能放一點(diǎn)比較簡單的東西。
2.LinearLayout
線性布局,這個東西,從外框上可以理解為一個 div ,他首先是一個一個從上往下羅列在屏幕上。每一個 LinearLayout 里面又可分為垂直布局 ( android:orientation=”vertical” )和水平布局(android:orientation=”horizontal” )。當(dāng)垂直布局時,每一行就只有一個元素,多個元素依次垂直往下;水平布局時,只有一行,每一個元素依次向右排列。
linearLayout 中有一個重要的屬性 android:layout_weight=”1″ ,這個 weight 在垂直布局時,代表行距;水平的時候代表列寬; weight 值越大就越大。
3.AbsoluteLayout
絕對布局猶如 div 指定了 absolute 屬性,用 X,Y 坐標(biāo)來指定元素的位置 android:layout_x=”20px” android:layout_y=”12px” 這種布局方式也比較簡單,但是在垂直隨便切換時,往往會出問題,而且多個元素的時候,計算比較麻煩。
4.RelativeLayout
相對布局可以理解為某一個元素為參照物,來定位的布局方式。主要屬性有:
相對于某一個元素
android:layout_below=”@id/aaa” 該元素在 id 為 aaa 的下面
android:layout_toLeftOf=”@id/bbb” 改元素的左邊是 bbb
相對于父元素的地方
android:layout_alignParentLeft=”true” 在父元素左對齊
android:layout_alignParentRight=”true” 在父元素右對齊
還可以指定邊距等,具體詳見 API
5.TableLayout
表格布局類似 Html 里面的 Table 。每一個 TableLayout 里面有表格行 TableRow , TableRow 里面可以具體定義每一個元素,設(shè)定他的對齊方式 android:gravity=”" 。
每一個布局都有自己適合的方式,另外,這五個布局元素可以相互嵌套應(yīng)用,做出美觀的界面。
18. 如何啟用 Service ,如何停用 Service
Android 中的服務(wù)和 windows 中的服務(wù)是類似的東西,服務(wù)一般沒有用戶操作界面,它運(yùn)行于系統(tǒng)中不容易被用戶發(fā)覺,可以使用它開發(fā)如監(jiān)控之類的程序。服務(wù)的開發(fā)比較簡單,如下:
第一步:繼承 Service 類
public class SMSService extends Service {
}
第二步:在 AndroidManifest.xml 文件中的
服務(wù)不能自己運(yùn)行,需要通過調(diào)用 Context.startService() 或 Context.bindService() 方法啟動服務(wù)。這兩個方法都可以啟動 Service ,但是它們的使用場合有所不同。使用 startService() 方法啟用服務(wù),調(diào)用者與服務(wù)之間沒有關(guān)連,即使調(diào)用者退出了,服務(wù)仍然運(yùn)行。使用 bindService() 方法啟用服務(wù),調(diào)用者與服務(wù)綁定在了一起,調(diào)用者一旦退出,服務(wù)也就終止,大有“不求同時生,必須同時死”的特點(diǎn)。
如果打算采用 Context.startService() 方法啟動服務(wù),在服務(wù)未被創(chuàng)建時,系統(tǒng)會先調(diào)用服務(wù)的onCreate() 方法,接著調(diào)用 onStart() 方法。如果調(diào)用 startService() 方法前服務(wù)已經(jīng)被創(chuàng)建,多次調(diào)用 startService() 方法并不會導(dǎo)致多次創(chuàng)建服務(wù),但會導(dǎo)致多次調(diào)用 onStart() 方法。采用startService() 方法啟動的服務(wù),只能調(diào)用 Context.stopService() 方法結(jié)束服務(wù),服務(wù)結(jié)束時會調(diào)用onDestroy() 方法。
如果打算采用 Context.bindService() 方法啟動服務(wù),在服務(wù)未被創(chuàng)建時,系統(tǒng)會先調(diào)用服務(wù)的onCreate() 方法,接著調(diào)用 onBind() 方法。這個時候調(diào)用者和服務(wù)綁定在一起,調(diào)用者退出了,系統(tǒng)就會先調(diào)用服務(wù)的 onUnbind() 方法,接著調(diào)用 onDestroy() 方法。如果調(diào)用 bindService() 方法前服務(wù)已經(jīng)被綁定,多次調(diào)用 bindService() 方法并不會導(dǎo)致多次創(chuàng)建服務(wù)及綁定 ( 也就是說onCreate() 和 onBind() 方法并不會被多次調(diào)用 ) 。如果調(diào)用者希望與正在綁定的服務(wù)解除綁定,可以調(diào)用 unbindService() 方法,調(diào)用該方法也會導(dǎo)致系統(tǒng)調(diào)用服務(wù)的 onUnbind()–>onDestroy() 方法。
服務(wù)常用生命周期回調(diào)方法如下:
onCreate() 該方法在服務(wù)被創(chuàng)建時調(diào)用,該方法只會被調(diào)用一次,無論調(diào)用多少次 startService() 或bindService() 方法,服務(wù)也只被創(chuàng)建一次。
onDestroy() 該方法在服務(wù)被終止時調(diào)用。
與采用 Context.startService() 方法啟動服務(wù)有關(guān)的生命周期方法
onStart() 只有采用 Context.startService() 方法啟動服務(wù)時才會回調(diào)該方法。該方法在服務(wù)開始運(yùn)行時被調(diào)用。多次調(diào)用 startService() 方法盡管不會多次創(chuàng)建服務(wù),但 onStart() 方法會被多次調(diào)用。
與采用 Context.bindService() 方法啟動服務(wù)有關(guān)的生命周期方法
onBind() 只有采用 Context.bindService() 方法啟動服務(wù)時才會回調(diào)該方法。該方法在調(diào)用者與服務(wù)綁定時被調(diào)用,當(dāng)調(diào)用者與服務(wù)已經(jīng)綁定,多次調(diào)用 Context.bindService() 方法并不會導(dǎo)致該方法被多次調(diào)用。
onUnbind() 只有采用 Context.bindService() 方法啟動服務(wù)時才會回調(diào)該方法。該方法在調(diào)用者與服務(wù)解除綁定時被調(diào)用
采用 Context.startService() 方法啟動服務(wù)的代碼如下:
public class HelloActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
……
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
startService(intent);
}});
}
}
采用 Context. bindService() 方法啟動服務(wù)的代碼如下:
public class HelloActivity extends Activity {
ServiceConnection conn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
}
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
//unbindService(conn);// 解除綁定
}});
}
}
19.ListView 優(yōu)化
工作原理 :
ListView 針對 List 中每個 item ,要求 adapter “ 給我一個視圖 ” (getView) 。
一個新的視圖被返回并顯示
如果我們有上億個項(xiàng)目要顯示怎么辦?為每個項(xiàng)目創(chuàng)建一個新視圖? NO! 這不可能!
實(shí)際上 Android 為你緩存了視圖。
Android 中有個叫做 Recycler 的構(gòu)件,下圖是他的工作原理:
如果你有 10 億個項(xiàng)目 (item) ,其中只有可見的項(xiàng)目存在內(nèi)存中,其他的在 Recycler 中。
1. ListView 先請求一個 type1 視圖 (getView) 然后請求其他可見的項(xiàng)目。 convertView 在 getView 中是空 (null) 的 。
2. 當(dāng) item1 滾出屏幕,并且一個新的項(xiàng)目從屏幕低端上來時, ListView 再請求一個 type1 視圖。convertView 此時不是空值了,它的值是 item1 。你只需設(shè)定新的數(shù)據(jù)然后返回 convertView,不必重新創(chuàng)建一個視圖。
20 廣播接收者生命周期
一個廣播接收者有一個回調(diào)方法: void onReceive(Context curContext , Intent broadcastMsg )。當(dāng)一個廣播消息到達(dá)接收者是, Android 調(diào)用它的 onReceive() 方法并傳遞給它包含消息的 Intent對象。廣播接收者被認(rèn)為僅當(dāng)它執(zhí)行這個方法時是活躍的。當(dāng) onReceive() 返回后,它是不活躍的。
有一個活躍的廣播接收者的進(jìn)程是受保護(hù)的,不會被殺死。但是系統(tǒng)可以在任何時候殺死僅有不活躍組件的進(jìn)程,當(dāng)占用的內(nèi)存別的進(jìn)程需要時。
這帶來一個問題,當(dāng)一個廣播消息的響應(yīng)時費(fèi)時的,因此應(yīng)該在獨(dú)立的線程中做這些事,遠(yuǎn)離用戶界面其它組件運(yùn)行的主線程。如果 onReceive() 衍生線程然后返回,整個進(jìn)程,包括新的線程,被判定為不活躍的(除非進(jìn)程中的其它應(yīng)用程序組件是活躍的),將使它處于被殺的危機(jī)。解決這個問題的方法是 onReceive() 啟動一個服務(wù),及時服務(wù)做這個工作,因此系統(tǒng)知道進(jìn)程中有活躍的工作在做。
21. 設(shè)計模式和 IoC( 控制反轉(zhuǎn) )
Android 框架魅力的源泉在于 IoC ,在開發(fā) Android 的過程中你會時刻感受到 IoC 帶來
的巨大方便,就拿 Activity 來說,下面的函數(shù)是框架調(diào)用自動調(diào)用的:
protected void onCreate(Bundle savedInstanceState) ;
不是程序編寫者主動去調(diào)用,反而是用戶寫的代碼被框架調(diào)用,這也就反轉(zhuǎn)
了!當(dāng)然 IoC 本身的內(nèi)涵遠(yuǎn)遠(yuǎn)不止這些,但是從這個例子中也可以窺視出 IoC
帶來的巨大好處。此類的例子在 Android 隨處可見,例如說數(shù)據(jù)庫的管理類,
例如說 Android 中 SAX 的 Handler 的調(diào)用等。有時候,您甚至需要自己編寫簡
單的 IoC 實(shí)現(xiàn),上面展示的多線程現(xiàn)在就是一個說明。
22.Android 中的長度單位詳解
現(xiàn)在這里介紹一下 dp 和 sp 。 dp 也就是 dip 。這個和 sp 基本類似。如果設(shè)置表示長度、高度等屬性時可以使用 dp 或 sp 。但如果設(shè)置字體,需要使用 sp 。 dp 是與密度無關(guān), sp 除了與密度無關(guān)外,還與 scale 無關(guān)。如果屏幕密度為 160 ,這時 dp 和 sp 和 px 是一樣的。 1dp=1sp=1px ,但如果使用 px 作單位,如果屏幕大小不變(假設(shè)還是 3.2 寸),而屏幕密度變成了 320 。那么原來TextView 的寬度設(shè)成 160px ,在密度為 320 的 3.2 寸屏幕里看要比在密度為 160 的 3.2 寸屏幕上看短了一半。但如果設(shè)置成 160dp 或 160sp 的話。系統(tǒng)會自動將 width 屬性值設(shè)置成 320px 的。也就是 160 * 320 / 160 。其中 320 / 160 可稱為密
度比例因子。也就是說,如果使用 dp 和 sp ,系統(tǒng)會根據(jù)屏幕密度的變化自動
進(jìn)行轉(zhuǎn)換。
下面看一下其他單位的含義
px :表示屏幕實(shí)際的象素。例如, 320*480 的屏幕在橫向有 320 個象素,
在縱向有 480 個象素。
in :表示英寸,是屏幕的物理尺寸。每英寸等于 2.54 厘米。例如,形容
手機(jī)屏幕大小,經(jīng)常說, 3.2 (英)寸、 3.5 (英)寸、 4 (英)寸就是指這個
單位。這些尺寸是屏幕的對角線長度。如果手機(jī)的屏幕是 3.2 英寸,表示手機(jī)
的屏幕(可視區(qū)域)對角線長度是 3.2*2.54 = 8.128 厘米。讀者可以去量
一量自己的手機(jī)屏幕,看和實(shí)際的尺寸是否一致。
23. 4 種 activity 的啟動模式
standard: 標(biāo)準(zhǔn)模式 ,一調(diào)用 startActivity() 方法就會產(chǎn)生一個新的實(shí)例。
singleTop : 如果已經(jīng)有一個實(shí)例位于 Activity 棧的頂部時,就不產(chǎn)生新的實(shí)例,而只是調(diào)用 Activity中的 newInstance() 方法。如果不位于棧頂,會產(chǎn)生一個新的實(shí)例。
singleTask : 會在一個新的 task 中產(chǎn)生這個實(shí)例,以后每次調(diào)用都會使用這個,不會去產(chǎn)生新的實(shí)例了。
singleInstance : 這個跟 singleTask 基本上是一樣,只有一個區(qū)別:在這個模式下的 Activity 實(shí)例所處的 task 中,只能有這個 activity 實(shí)例,不能有其他的實(shí)例。
24. 什么是 ANR 如何避免它 ?
ANR : Application Not Responding ,五秒
在 Android 中,活動管理器和窗口管理器這兩個系統(tǒng)服務(wù)負(fù)責(zé)監(jiān)視應(yīng)用程序的響應(yīng)。當(dāng)出現(xiàn)下列情況時, Android 就會顯示 ANR 對話框了:
對輸入事件 ( 如按鍵、觸摸屏事件 ) 的響應(yīng)超過 5 秒
意向接受器 (intentReceiver) 超過 10 秒鐘仍未執(zhí)行完畢
Android 應(yīng)用程序完全運(yùn)行在一個獨(dú)立的線程中 ( 例如 main) 。這就意味著,任何在主線程中運(yùn)行的,需要消耗大量時間的操作都會引發(fā) ANR 。因?yàn)榇藭r,你的應(yīng)用程序已經(jīng)沒有機(jī)會去響應(yīng)輸入事件和意向廣播 (Intent broadcast) 。
因此,任何運(yùn)行在主線程中的方法,都要盡可能的只做少量的工作。特別是活動生命周期中的重要方法如 onCreate() 和 onResume() 等更應(yīng)如此。潛在的比較耗時的操作,如訪問網(wǎng)絡(luò)和數(shù)據(jù)庫; 或者是開銷很大的計算,比如改變位圖的大小,需要在一個單獨(dú)的子線程中完成 ( 或者是使用異步請求,如數(shù)據(jù)庫操作 ) 。但這并不意味著你的主線程需要進(jìn)入阻塞狀態(tài)已等待子線程結(jié)束 — 也不需要調(diào)用 Therad.wait() 或者 Thread.sleep() 方法。取而代之的是,主線程為子線程提供一個句柄(Handler) ,讓子線程在即將結(jié)束的時候調(diào)用它 (xing: 可以參看 Snake 的例子,這種方法與以前我們所接觸的有所不同 ) 。使用這種方法涉及你的應(yīng)用程序,能夠保證你的程序?qū)斎氡3至己玫捻憫?yīng),從而避免因?yàn)檩斎胧录^ 5 秒鐘不被處理而產(chǎn)生的 ANR 。這種實(shí)踐需要應(yīng)用到所有顯示用戶界面的線程,因?yàn)樗麄兌济媾R著同樣的超時問題。
25.Android Intent 的使用
在一個 Android 應(yīng)用中,主要是由一些組件組成,( Activity,Service,ContentProvider,etc.) 在這些組件之間的通訊中,由 Intent 協(xié)助完成。
正如網(wǎng)上一些人解析所說, Intent 負(fù)責(zé)對應(yīng)用中一次操作的動作、動作涉及數(shù)據(jù)、附加數(shù)據(jù)進(jìn)行描述, Android 則根據(jù)此 Intent 的描述,負(fù)責(zé)找到對應(yīng)的組件,將 Intent 傳遞給調(diào)用的組件,并完成組件的調(diào)用。 Intent 在這里起著實(shí)現(xiàn)調(diào)用者與被調(diào)用者之間的解耦作用。
Intent 傳遞過程中,要找到目標(biāo)消費(fèi)者(另一個 Activity,IntentReceiver 或 Service ),也就是 Intent的響應(yīng)者,有兩種方法來匹配:
1 ,顯示匹配( Explicit) :
public TestB extents Activity
{
………
};
public class Test extends Activity
{
……
public void switchActivity()
{
Intent i = new Intent(Test.this, TestB.class);
this.startActivity(i);
}
}
代碼簡潔明了,執(zhí)行了 switchActivity() 函數(shù),就會馬上跳轉(zhuǎn)到名為 TestB 的 Activity 中。
2 ,隱式匹配 (Implicit):
隱式匹配,首先要匹配 Intent 的幾項(xiàng)值: Action, Category, Data/Type,Component
如果填寫了 Componet 就是上例中的 Test.class) 這就形成了顯示匹配。所以此部分只講前幾種匹配。匹配規(guī)則為最大匹配規(guī)則,
1 ,如果你填寫了 Action ,如果有一個程序的 Manifest.xml 中的某一個 Activity 的 IntentFilter 段中定義了包含了相同的 Action 那么這個 Intent 就與這個目標(biāo) Action 匹配,如果這個 Filter 段中沒有定義 Type,Category ,那么這個 Activity 就匹配了。但是如果手機(jī)中有兩個以上的程序匹配,那么就會彈出一個對話可框來提示說明。
Action 的值在 Android 中有很多預(yù)定義,如果你想直接轉(zhuǎn)到你自己定義的 Intent 接收者,你可以在接收者的 IntentFilter 中加入一個自定義的 Action 值(同時要設(shè)定 Category 值為”android.intent.category.DEFAULT” ),在你的 Intent 中設(shè)定該值為 Intent 的 Action, 就直接能跳轉(zhuǎn)到你自己的 Intent 接收者中。因?yàn)檫@個 Action 在系統(tǒng)中是唯一的。
2,data/type ,你可以用 Uri 來做為 data, 比如 Uri uri = Uri.parse(https://www.google.com );
Intent i = new Intent(Intent.ACTION_VIEW,uri); 手機(jī)的 Intent 分發(fā)過程中,會根據(jù)https://www.google.com 的 scheme 判斷出數(shù)據(jù)類型 type
手機(jī)的 Brower 則能匹配它,在 Brower 的 Manifest.xml 中的 IntenFilter 中首先有 ACTION_VIEW Action, 也能處理 http: 的 type ,
3 ,至于分類 Category ,一般不要去在 Intent 中設(shè)置它,如果你寫 Intent 的接收者,就在Manifest.xml 的 Activity 的 IntentFilter 中包含 android.category.DEFAULT, 這樣所有不設(shè)置 Category( Intent.addCategory(String c); )的 Intent 都會與這個 Category 匹配。
4,extras (附加信息),是其它所有附加信息的集合。使用 extras 可以為組件提供擴(kuò)展信息,比如,如果要執(zhí)行 “ 發(fā)送電子郵件 ” 這個動作,可以將電子郵件的標(biāo)題、正文等保存在 extras 里,傳給電子郵件發(fā)送組件。
相關(guān)導(dǎo)讀: