Android面試

面試題總結(jié)

通用

  • 安卓學習途徑, 尋找資料學習的博客網(wǎng)站
  • AndroidStudio使用, 插件使用
  • 安卓和蘋果的區(qū)別

初級(基礎(chǔ)1年左右)

  • 四大組件
  • 五大存儲方式
  • Layout布局有哪幾種 FrameLayout什么時候用
  • ListView的優(yōu)化
  • 點擊事件設(shè)置監(jiān)聽的幾種方式
  • 安卓主線程和子線程的關(guān)系
  • Activity生命周期 onStart onResume區(qū)別
  • Fragment生命周期 Activity和Fragment區(qū)別
  • 頁面之間如何傳遞數(shù)據(jù), 如果傳遞一個對象如何處理, 如何傳遞集合
  • dp px sp的區(qū)別
  • gravity和layout_gravity的區(qū)別
  • margin和padding的區(qū)別
  • weight的作用
  • Handler機制
  • 什么的ANR, 如何避免
  • 顯式意圖和隱式意圖區(qū)別,隱式意圖的使用
  • 廣播幾種接收方式, 廣播有幾種類型, 區(qū)別
  • 開啟Service的幾種方式, 區(qū)別, Service和Activity之間如何傳遞數(shù)據(jù)
  • Service中如果要start一個Activity要如何特殊處理,為什么
    ...
    還有很多,都是網(wǎng)上常見面試題, 百度搜看看, 背下來即可

中級(2~3年, 也問部分基礎(chǔ)問題)

  • 自定義控件
  • 常用開源框架的使用
  • 動畫類型
  • 任務(wù)棧,頁面啟動方式
  • Material Design / 新控件RecyclerView CardView等使用
  • 圖片壓縮和雙緩存原理
  • 多層View的onTouch事件分發(fā)
    ...
    簡單了解記下來, 最好自己寫個demo試驗下

高級(3年+, 也問部分中級問題)

  • Android繪制原理 onMeasure onLayout onDraw作用
  • MeasureSpec的集中類型區(qū)別和作用
  • 自定義控件
  • 什么是MVC MVP,區(qū)別
  • 響應(yīng)式編程
  • 常見開源框架源碼
  • 單元測試常用框架和實際使用 場景
    ...
    需要閱讀源碼和項目編碼練習

其他

多媒體

  • 音頻的環(huán)繞聲和混響等如何處理
  • 音頻錄制播放
  • 視頻的錄制和播放
  • 播放使用的常用框架
  • Android原生支持格式
  • 軟解碼硬解碼的區(qū)別
  • 如果要做一個按住屏幕右側(cè)滑動調(diào)整聲音功能如何處理
    ...
    特殊公司做這方面相關(guān)的會問的多

四大組件

Android四大組件分別為activity、service、content provider、broadcast receiver。
常見AndRoid面試題第一篇:四大組件

1、activity

(1)一個Activity通常就是一個單獨的屏幕(窗口)。
(2)Activity之間通過Intent進行通信。
(3)android應(yīng)用中每一個Activity都必須要在AndroidManifest.xml配置文件中聲明,否則系統(tǒng)將不識別也不執(zhí)行該Activity。

2、service

(1)service用于在后臺完成用戶指定的操作。service分為兩種:

(a)started(啟動):當應(yīng)用程序組件(如activity)調(diào)用startService()方法啟動服務(wù)時,服務(wù)處于started狀態(tài)。

(b)bound(綁定):當應(yīng)用程序組件調(diào)用bindService()方法綁定到服務(wù)時,服務(wù)處于bound狀態(tài)。

(2)startService()與bindService()區(qū)別:

(a)started service(啟動服務(wù))是由其他組件調(diào)用startService()方法啟動的,這導致服務(wù)的onStartCommand()方法被調(diào)用。當服務(wù)是started狀態(tài)時,其生命周期與啟動它的組件無關(guān),并且可以在后臺無限期運行,即使啟動服務(wù)的組件已經(jīng)被銷毀。因此,服務(wù)需要在完成任務(wù)后調(diào)用stopSelf()方法停止,或者由其他組件調(diào)用stopService()方法停止。

(b)使用bindService()方法啟用服務(wù),調(diào)用者與服務(wù)綁定在了一起,調(diào)用者一旦退出,服務(wù)也就終止,大有“不求同時生,必須同時死”的特點。

(3)開發(fā)人員需要在應(yīng)用程序配置文件中聲明全部的service,使用<service></service>標簽。

(4)Service通常位于后臺運行,它一般不需要與用戶交互,因此Service組件沒有圖形用戶界面。Service組件需要繼承Service基類。Service組件通常用于為其他組件提供后臺服務(wù)或監(jiān)控其他組件的運行狀態(tài)。

3、content provider

(1)android平臺提供了Content Provider使一個應(yīng)用程序的指定數(shù)據(jù)集提供給其他應(yīng)用程序。其他應(yīng)用可以通過ContentResolver類從該內(nèi)容提供者中獲取或存入數(shù)據(jù)。

(2)只有需要在多個應(yīng)用程序間共享數(shù)據(jù)是才需要內(nèi)容提供者。例如,通訊錄數(shù)據(jù)被多個應(yīng)用程序使用,且必須存儲在一個內(nèi)容提供者中。它的好處是統(tǒng)一數(shù)據(jù)訪問方式。

(3)ContentProvider實現(xiàn)數(shù)據(jù)共享。ContentProvider用于保存和獲取數(shù)據(jù),并使其對所有應(yīng)用程序可見。這是不同應(yīng)用程序間共享數(shù)據(jù)的唯一方式,因為android沒有提供所有應(yīng)用共同訪問的公共存儲區(qū)。

(4)開發(fā)人員不會直接使用ContentProvider類的對象,大多數(shù)是通過ContentResolver對象實現(xiàn)對ContentProvider的操作。

(5)ContentProvider使用URI來唯一標識其數(shù)據(jù)集,這里的URI以content://作為前綴,表示該數(shù)據(jù)由ContentProvider來管理。

4、broadcast receiver

(1)你的應(yīng)用可以使用它對外部事件進行過濾,只對感興趣的外部事件(如當電話呼入時,或者數(shù)據(jù)網(wǎng)絡(luò)可用時)進行接收并做出響應(yīng)。廣播接收器沒有用戶界面。然而,它們可以啟動一個activity或serice來響應(yīng)它們收到的信息,或者用NotificationManager來通知用戶。通知可以用很多種方式來吸引用戶的注意力,例如閃動背燈、震動、播放聲音等。一般來說是在狀態(tài)欄上放一個持久的圖標,用戶可以打開它并獲取消息。

(2)廣播接收者的注冊有兩種方法,分別是程序動態(tài)注冊和AndroidManifest文件中進行靜態(tài)注冊。

(3)動態(tài)注冊廣播接收器特點是當用來注冊的Activity關(guān)掉后,廣播也就失效了。靜態(tài)注冊無需擔憂廣播接收器是否被關(guān)閉,只要設(shè)備是開啟狀態(tài),廣播接收器也是打開著的。也就是說哪怕app本身未啟動,該app訂閱的廣播在觸發(fā)時也會對它起作用。

總結(jié)

(1)4大組件的注冊

4大基本組件都需要注冊才能使用,每個Activity、service、Content Provider都需要在AndroidManifest文件中進行配置。AndroidManifest文件中未進行聲明的activity、服務(wù)以及內(nèi)容提供者將不為系統(tǒng)所見,從而也就不可用。而broadcast receiver廣播接收者的注冊分靜態(tài)注冊(在AndroidManifest文件中進行配置)和通過代碼動態(tài)創(chuàng)建并以調(diào)用Context.registerReceiver()的方式注冊至系統(tǒng)。需要注意的是在AndroidManifest文件中進行配置的廣播接收者會隨系統(tǒng)的啟動而一直處于活躍狀態(tài),只要接收到感興趣的廣播就會觸發(fā)(即使程序未運行)。

(2)4大組件的激活

內(nèi)容提供者的激活:當接收到ContentResolver發(fā)出的請求后,內(nèi)容提供者被激活。而其它三種組件activity、服務(wù)和廣播接收器被一種叫做intent的異步消息所激活。

(3)4大組件的關(guān)閉

內(nèi)容提供者僅在響應(yīng)ContentResolver提出請求的時候激活。而一個廣播接收器僅在響應(yīng)廣播信息的時候激活。所以,沒有必要去顯式的關(guān)閉這些組件。
Activity關(guān)閉:可以通過調(diào)用它的finish()方法來關(guān)閉一個activity。
服務(wù)關(guān)閉:對于通過startService()方法啟動的服務(wù)要調(diào)用Context.stopService()方法關(guān)閉服務(wù),使用bindService()方法啟動的服務(wù)要調(diào)用Contex.unbindService()方法關(guān)閉服務(wù)。

(4)android中的任務(wù)(activity棧)

(a)任務(wù)其實就是activity的棧,它由一個或多個Activity組成,共同完成一個完整的用戶體驗。棧底的是啟動整個任務(wù)的Activity,棧頂?shù)氖钱斍斑\行的用戶可以交互的Activity,當一個activity啟動另外一個的時候,新的activity就被壓入棧,并成為當前運行的activity。而前一個activity仍保持在棧之中。當用戶按下BACK鍵的時候,當前activity出棧,而前一個恢復為當前運行的activity。棧中保存的其實是對象,棧中的Activity永遠不會重排,只會壓入或彈出。

(b)任務(wù)中的所有activity是作為一個整體進行移動的。整個的任務(wù)(即activity棧)可以移到前臺,或退至后臺。

(c)Android系統(tǒng)是一個多任務(wù)(Multi-Task)的操作系統(tǒng),可以在用手機聽音樂的同時,也執(zhí)行其他多個程序。每多執(zhí)行一個應(yīng)用程序,就會多耗費一些系統(tǒng)內(nèi)存,當同時執(zhí)行的程序過多,或是關(guān)閉的程序沒有正確釋放掉內(nèi)存,系統(tǒng)就會覺得越來越慢,甚至不穩(wěn)定。為了解決這個問題,Android引入了一個新的機制,即生命周期(Life Cycle)。原文鏈接


五大存儲方式

Android平臺中實現(xiàn)數(shù)據(jù)存儲的5種方式

數(shù)據(jù)存儲在開發(fā)中是使用最頻繁的,在這里主要介紹Android平臺中實現(xiàn)數(shù)據(jù)存儲的5種方式,分別是:

1 使用SharedPreferences存儲數(shù)據(jù)

2 文件存儲數(shù)據(jù)

3 SQLite數(shù)據(jù)庫存儲數(shù)據(jù)

4 使用ContentProvider存儲數(shù)據(jù)

5 網(wǎng)絡(luò)存儲數(shù)據(jù)

第一種:使用SharedPreferences存儲數(shù)據(jù)

SharedPreferences是Android平臺上一個輕量級的存儲類,主要是保存一些常用的配置比如窗口狀態(tài),一般在Activity中 重載窗口狀態(tài)onSaveInstanceState保存一般使用SharedPreferences完成,它提供了Android平臺常規(guī)的Long長 整形、Int整形、String字符串型的保存。

它是什么樣的處理方式呢? SharedPreferences類似過去Windows系統(tǒng)上的ini配置文件,但是它分為多種權(quán)限,可以全局共享訪問,android123提示最終是以xml方式來保存,整體效率來看不是特別的高,對于常規(guī)的輕量級而言比SQLite要好不少,如果真的存儲量不大可以考慮自己定義文件格式。xml 處理時Dalvik會通過自帶底層的本地XML Parser解析,比如XMLpull方式,這樣對于內(nèi)存資源占用比較好。

它的本質(zhì)是基于XML文件存儲key-value鍵值對數(shù)據(jù),通常用來存儲一些簡單的配置信息。

其存儲位置在/data/data/<包名>/shared_prefs目錄下。

SharedPreferences對象本身只能獲取數(shù)據(jù)而不支持存儲和修改,存儲修改是通過Editor對象實現(xiàn)。

實現(xiàn)SharedPreferences存儲的步驟如下:

1)、根據(jù)Context獲取SharedPreferences對象

2)、利用edit()方法獲取Editor對象。

3)、通過Editor對象存儲key-value鍵值對數(shù)據(jù)。

4)、通過commit()方法提交數(shù)據(jù)。

public class MainActivity extends Activity {'
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
  
 //獲取SharedPreferences對象
 Context ctx = MainActivity.this; 
 SharedPreferences sp = ctx.getSharedPreferences("SP", MODE_PRIVATE);
 //存入數(shù)據(jù)
 Editor editor = sp.edit();
 editor.putString("STRING_KEY", "string");
 editor.putInt("INT_KEY", 0);
 editor.putBoolean("BOOLEAN_KEY", true);
 editor.commit();
  
 //返回STRING_KEY的值
 Log.d("SP", sp.getString("STRING_KEY", "none"));
 //如果NOT_EXIST不存在,則返回值為"none"
 Log.d("SP", sp.getString("NOT_EXIST", "none"));
 }
}

這段代碼執(zhí)行過后,即在/data/data/com.test/shared_prefs目錄下生成了一個SP.xml文件,一個應(yīng)用可以創(chuàng)建多個這樣的xml文件。

SharedPreferences對象與SQLite數(shù)據(jù)庫相比,免去了創(chuàng)建數(shù)據(jù)庫,創(chuàng)建表,寫SQL語句等諸多操作,相對而言更加方便,簡潔。但是SharedPreferences也有其自身缺陷,比如其職能存儲boolean,int,float,long和String五種簡單的數(shù)據(jù)類型,比如其無法進行條件查詢等。所以不論SharedPreferences的數(shù)據(jù)存儲操作是如何簡單,它也只能是存儲方式的一種補充,而無法完全替代如SQLite數(shù)據(jù)庫這樣的其他數(shù)據(jù)存儲方式。

第二種:文件存儲數(shù)據(jù)
關(guān)于文件存儲,Activity提供了openFileOutput()方法可以用于把數(shù)據(jù)輸出到文件中,具體的實現(xiàn)過程與在J2SE環(huán)境中保存數(shù)據(jù)到文件中是一樣的。

文件可用來存放大量數(shù)據(jù),如文本、圖片、音頻等。

默認位置:/data/data/<包>/files/.

public void save()
{
 
try {
FileOutputStream outStream=this.openFileOutput("a.txt",Context.MODE_WORLD_READABLE);
outStream.write(text.getText().toString().getBytes());
outStream.close();
Toast.makeText(MyActivity.this,"Saved",Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
return;
}
catch (IOException e){
return ;
}
} 

openFileOutput()方法的第一參數(shù)用于指定文件名稱,不能包含路徑分隔符“/” ,如果文件不存在,Android 會自動創(chuàng)建它。

創(chuàng)建的文件保存在/data/data/<package name>/files目錄,如: /data/data/cn.itcast.action/files/itcast.txt ,通過點擊Eclipse菜單“Window”-“Show View”-“Other”,在對話窗口中展開android文件夾,選擇下面的File Explorer視圖,然后在File Explorer視圖中展開/data/data/<package name>/files目錄就可以看到該文件。

openFileOutput()方法的第二參數(shù)用于指定操作模式,有四種模式,分別為:

Context.MODE_PRIVATE = 0

Context.MODE_APPEND = 32768

Context.MODE_WORLD_READABLE = 1

Context.MODE_WORLD_WRITEABLE = 2

Context.MODE_PRIVATE:為默認操作模式,代表該文件是私有數(shù)據(jù),只能被應(yīng)用本身訪問,在該模式下,寫入的內(nèi)容會覆蓋原文件的內(nèi)容,如果想把新寫入的內(nèi)容追加到原文件中。可以使用Context.MODE_APPEND

Context.MODE_APPEND:模式會檢查文件是否存在,存在就往文件追加內(nèi)容,否則就創(chuàng)建新文件。

Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用來控制其他應(yīng)用是否有權(quán)限讀寫該文件。

MODE_WORLD_READABLE:表示當前文件可以被其他應(yīng)用讀取;

MODE_WORLD_WRITEABLE:表示當前文件可以被其他應(yīng)用寫入。

如果希望文件被其他應(yīng)用讀和寫,可以傳入: openFileOutput("itcast.txt", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); android有一套自己的安全模型,當應(yīng)用程序(.apk)在安裝時系統(tǒng)就會分配給他一個userid,當該應(yīng)用要去訪問其他資源比如文件的時候,就需要userid匹配。默認情況下,任何應(yīng)用創(chuàng)建的文件,sharedpreferences,數(shù)據(jù)庫都應(yīng)該是私有的(位于/data/data/<package name>/files),其他程序無法訪問。

除非在創(chuàng)建時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE ,只有這樣其他程序才能正確訪問。
讀取文件示例:

public void load()
{
 try {
 FileInputStream inStream=this.openFileInput("a.txt");
 ByteArrayOutputStream stream=new ByteArrayOutputStream();
 byte[] buffer=new byte[1024];
 int length=-1;
 while((length=inStream.read(buffer))!=-1) {
 stream.write(buffer,0,length);
 }
 
 
 stream.close();
 inStream.close();
 text.setText(stream.toString());
 Toast.makeText(MyActivity.this,"Loaded",Toast.LENGTH_LONG).show();
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 }
 catch (IOException e){
 return ;
 }
 
} 

對于私有文件只能被創(chuàng)建該文件的應(yīng)用訪問,如果希望文件能被其他應(yīng)用讀和寫,可以在創(chuàng)建文件時,指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE權(quán)限。

Activity還提供了getCacheDir()和getFilesDir()方法: getCacheDir()方法用于獲取/data/data/<package name>/cache目錄 getFilesDir()方法用于獲取/data/data/<package name>/files目錄。

把文件存入SDCard:

使用Activity的openFileOutput()方法保存文件,文件是存放在手機空間上,一般手機的存儲空間不是很大,存放些小文件還行,如果要存放像視頻這樣的大文件,是不可行的。對于像視頻這樣的大文件,我們可以把它存放在SDCard。

SDCard是干什么的?你可以把它看作是移動硬盤或U盤。 在模擬器中使用SDCard,你需要先創(chuàng)建一張SDCard卡(當然不是真的SDCard,只是鏡像文件)。

創(chuàng)建SDCard可以在Eclipse創(chuàng)建模擬器時隨同創(chuàng)建,也可以使用DOS命令進行創(chuàng)建,如下: 在Dos窗口中進入android SDK安裝路徑的tools目錄,輸入以下命令創(chuàng)建一張容量為2G的SDCard,文件后綴可以隨便取,建議使用.img: mksdcard 2048M D:\AndroidTool\sdcard.img 在程序中訪問SDCard,你需要申請訪問SDCard的權(quán)限。

在AndroidManifest.xml中加入訪問SDCard的權(quán)限如下:

<!-- 在SDCard中創(chuàng)建與刪除文件權(quán)限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
 
<!-- 往SDCard寫入數(shù)據(jù)權(quán)限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
 

要往SDCard存放文件,程序必須先判斷手機是否裝有SDCard,并且可以進行讀寫。
注意:訪問SDCard必須在AndroidManifest.xml中加入訪問SDCard的權(quán)限。

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ 
 File sdCardDir = Environment.getExternalStorageDirectory();//獲取SDCard目錄 
 
 File saveFile = new File(sdCardDir, “a.txt”);
 FileOutputStream outStream = new FileOutputStream(saveFile);
 outStream.write("test".getBytes());
 outStream.close();
}

Environment.getExternalStorageState()方法用于獲取SDCard的狀態(tài),如果手機裝有SDCard,并且可以進行讀寫,那么方法返回的狀態(tài)等于Environment.MEDIA_MOUNTED。

Environment.getExternalStorageDirectory()方法用于獲取SDCard的目錄,當然要獲取SDCard的目錄,你也可以這樣寫:

File sdCardDir = new File("/sdcard"); //獲取SDCard目錄
File saveFile = new File(sdCardDir, "itcast.txt");
//上面兩句代碼可以合成一句:
File saveFile = new File("/sdcard/a.txt");
FileOutputStream outStream = new FileOutputStream(saveFile);
outStream.write("test".getBytes());
outStream.close(); 

第三種SQLite數(shù)據(jù)庫存儲數(shù)據(jù)

SQLite是輕量級嵌入式數(shù)據(jù)庫引擎,它支持 SQL 語言,并且只利用很少的內(nèi)存就有很好的性能。此外它還是開源的,任何人都可以使用它。許多開源項目((Mozilla, PHP, Python)都使用了 SQLite.SQLite 由以下幾個組件組成:SQL 編譯器、內(nèi)核、后端以及附件。SQLite 通過利用虛擬機和虛擬數(shù)據(jù)庫引擎(VDBE),使調(diào)試、修改和擴展 SQLite 的內(nèi)核變得更加方便。
特點:

  • 面向資源有限的設(shè)備;
  • 沒有服務(wù)器進程;
  • 所有數(shù)據(jù)存放在同一文件中跨平臺;
  • 可自由復制。
    第四種:使用ContentProvider存儲數(shù)據(jù)
    Android這個系統(tǒng)和其他的操作系統(tǒng)還不太一樣,我們需要記住的是,數(shù)據(jù)在Android當中是私有的,當然這些數(shù)據(jù)包括文件數(shù)據(jù)和數(shù)據(jù)庫數(shù)據(jù)以及一些其他類型的數(shù)據(jù)。那這個時候有讀者就會提出問題,難道兩個程序之間就沒有辦法對于數(shù)據(jù)進行交換?Android這么優(yōu)秀的系統(tǒng)不會讓這種情況發(fā)生的。解決這個問題主要靠ContentProvider。一個Content Provider類實現(xiàn)了一組標準的方法接口,從而能夠讓其他的應(yīng)用保存或讀取此Content Provider的各種數(shù)據(jù)類型。也就是說,一個程序可以通過實現(xiàn)一個Content Provider的抽象接口將自己的數(shù)據(jù)暴露出去。外界根本看不到,也不用看到這個應(yīng)用暴露的數(shù)據(jù)在應(yīng)用當中是如何存儲的,或者是用數(shù)據(jù)庫存儲還是用文件存儲,還是通過網(wǎng)上獲得,這些一切都不重要,重要的是外界可以通過這一套標準及統(tǒng)一的接口和程序里的數(shù)據(jù)打交道,可以讀取程序的數(shù)據(jù),也可以刪除程序的數(shù)據(jù),當然,中間也會涉及一些權(quán)限的問題。

一個程序可以通過實現(xiàn)一個ContentProvider的抽象接口將自己的數(shù)據(jù)完全暴露出去,而且ContentProviders是以類似數(shù)據(jù)庫中表的方式將數(shù)據(jù)暴露,也就是說ContentProvider就像一個“數(shù)據(jù)庫”。那么外界獲取其提供的數(shù)據(jù),也就應(yīng)該與從數(shù)據(jù)庫中獲取數(shù)據(jù)的操作基本一樣,只不過是采用URI來表示外界需要訪問的“數(shù)據(jù)庫”。

Content Provider提供了一種多應(yīng)用間數(shù)據(jù)共享的方式,比如:聯(lián)系人信息可以被多個應(yīng)用程序訪問。

Content Provider是個實現(xiàn)了一組用于提供其他應(yīng)用程序存取數(shù)據(jù)的標準方法的類。 應(yīng)用程序可以在Content Provider中執(zhí)行如下操作: 查詢數(shù)據(jù) 修改數(shù)據(jù) 添加數(shù)據(jù) 刪除數(shù)據(jù)

標準的Content Provider: Android提供了一些已經(jīng)在系統(tǒng)中實現(xiàn)的標準Content Provider,比如聯(lián)系人信息,圖片庫等等,你可以用這些Content Provider來訪問設(shè)備上存儲的聯(lián)系人信息,圖片等等。

第五種:網(wǎng)絡(luò)存儲數(shù)據(jù)
前面介紹的幾種存儲都是將數(shù)據(jù)存儲在本地設(shè)備上,除此之外,還有一種存儲(獲取)數(shù)據(jù)的方式,通過網(wǎng)絡(luò)來實現(xiàn)數(shù)據(jù)的存儲和獲取。

我們可以調(diào)用WebService返回的數(shù)據(jù)或是解析HTTP協(xié)議實現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)交互。

具體需要熟悉java.net.,Android.net.這兩個包的內(nèi)容,在這就不贅述了,請大家參閱相關(guān)文檔。


Layout布局有哪幾種 FrameLayout什么時候用

Android五大布局介紹&屬性設(shè)置大全

在Android中,共有五種布局方式,分別是:

  • FrameLayout(框架布局)
  • LinearLayout(線性布局)
  • AbsoluteLayout(絕對布局)
  • RelativeLayout(相對布局)
  • TableLayout(表格布局)

1. FrameLayout框架布局
布局特點:放入其中的所有元素都被放置在最左上的區(qū)域,而且無法為這些元素指定一個確切的位置,下一個子元素會重疊覆蓋上一個子元素
應(yīng)用場景:適合瀏覽單張圖片。

2. LinearLayout線性布局
布局特點:放主要提供控件水平或者垂直排列的模型,每個子組件都是以垂直或水平的方式來線性排布.(默認是垂直)
應(yīng)用場景:最常用的布局方式linearLayout中有一個重要的屬性 android:layout_weight="1",這個weight在垂直布局時,代表行距;水平的時候代表列寬;weight值越大就越大。

3. AbsoluteLayout絕對定位布局
布局特點:采用坐標軸的方式定位組件,左上角是(0,0)點,往右x軸遞增,往下Y軸遞增,組件定位屬性為android:layout_x和 android:layout_y來確定坐標。
應(yīng)用場景:準確定位空間位置由于Android手機的屏幕尺寸、分辨率存在較大差異,使用AbsoluteLayout無法兼顧適配問題,所以該布局已經(jīng)過時

4. RelativeLayout相對布局
布局特點:為某一個組件為參照物,來定位下一個組件的位置的布局方式。
應(yīng)用場景:控件之間存在相應(yīng)關(guān)系(適配神器,推薦使用)

5. TableLayout表格布局
布局特點:類似Html里的Table.使用TableRow來布局,其中TableRow代表一行,TableRow的每一個視圖組件代表一個單元格。
應(yīng)用場景:控件之間存在相應(yīng)關(guān)系。


ListView的優(yōu)化

Android中ListView常見優(yōu)化方案

  • 一、復用convertView,減少findViewById的次數(shù)
  • 二、緩存item條目的引用——ViewHolder
    ViewHolder模式 充分利用了視圖的緩存機制 避免了每次調(diào)用getView()時候都去通過findViewById實例化控件
  • 三、給listView設(shè)置滾動監(jiān)聽器 根據(jù)不同狀態(tài) 不同處理數(shù)據(jù) 分批分頁加載 根據(jù)listView的狀態(tài)去操作
  • 四、listview每個item層級結(jié)構(gòu)不要太復雜
  • 五、如果listview每個item要加載圖片 一定要對圖片的加載進行優(yōu)化。
  • 六、避免在listview適配器中使用線程
  • 七、ScrollView 和listview 會有沖突
  • 八、避免在getView方法中做耗時操作

點擊事件設(shè)置監(jiān)聽的幾種方式

方法一:寫一個內(nèi)部類,在類中實現(xiàn)點擊事件

bt_dail.setOnClickListener(new MyButtonListener());
private class MyButtonListener implements OnClickListener{
/**
 * 當按鈕被點擊的時候調(diào)用
 */
@Override
public void onClick(View v) {
     callPhone();
}
}

方法二:匿名內(nèi)部類

bt_dail.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
   callPhone();
}
});

方法三:讓activity實現(xiàn)點擊接口

public class MainActivity extends Activity implements OnClickListener 
//調(diào)用點擊事件方法
bt_dail.setOnClickListener(this);
//實現(xiàn)接口
@Override
public void onClick(View v) {
        switch (v.getId()) {
                   case R.id.bt_dail:
                            callPhone();
                            break;
                 default:
                 break;
        }
}

方法四:在layout文件中定義button點擊時調(diào)用的方法

<Button        
android:id="@+id/bt_dail" 
android:layout_width="wrap_content"
android:layout_height="wrap_content"        
android:onClick="dailPhone"        
android:text="撥打此號碼" />
定義方法:
public void dailPhone(View view){  
    callPhone();  
} 

方法五:外部內(nèi)做事件監(jiān)聽
就是另外創(chuàng)建一個處理事件的Java文件,這種形式用的比較少!因為外部類不能直接訪問用戶界面類中的組件,要通過構(gòu)造方法將組件傳入使用;這樣導致的結(jié)果就是代碼不夠簡潔!


安卓主線程和子線程的關(guān)系

  • 主線程:也叫UI線程,或稱ActivityThread,用于運行四大組件和處理他們用戶的交互。 ActivityThread管理應(yīng)用進程的主線程的執(zhí)行(相當于普通Java程序的main入口函數(shù)),在Android系統(tǒng)中,在默認情況下,一個應(yīng)用程序內(nèi)的各個組件(如Activity、BroadcastReceiver、Service)都會在同一個進程(Process)里執(zhí)行,且由此進程的主線程負責執(zhí)行。ActivityThread既要處理Activity組件的UI事件,又要處理Service后臺服務(wù)工作,通常會忙不過來。為了解決此問題,主線程可以創(chuàng)建多個子線程來處理后臺服務(wù)工作,而本身專心處理UI畫面的事件。
  • 子線程: 用于執(zhí)行耗時操作,比如 I/O操作和網(wǎng)絡(luò)請求等。(安卓3.0以后要求耗訪問網(wǎng)絡(luò)必須在子線程種執(zhí)行)更新UI的工作必須交給主線程,子線程在安卓里是不允許更新UI的。

Android是單線程模型,我們創(chuàng)建的Service、Activity以及Broadcast均是在一個主線程處理,這里我們可以理解為UI線程。
但是在操作一些耗時操作時,比如I/O讀寫的大文件讀寫,數(shù)據(jù)庫操作以及網(wǎng)絡(luò)下載需要很長時間,為了不阻塞用戶界面,出現(xiàn)ANR的響應(yīng)提示窗口,這個時候我們考慮使用Thread線程來解決。

  1. 任何耗時的處理過程都會降低用戶界面的響應(yīng)速度,甚至導致用戶界面失去響應(yīng),當用戶界面失去響應(yīng)超過5秒鐘,Android系統(tǒng)會允許用戶強行關(guān)閉應(yīng)用程序。


  2. 較好的解決方法是將耗時的處理過程轉(zhuǎn)移到子線程上,這樣可以避免負責界面更新的主線程無法處理界面事件,從而避免用戶界面長時間失去響應(yīng)。

  3. 線程是獨立的程序單元,多個線程可以并行工作。

  4. 在多處理器系統(tǒng)中,每個中央處理器(CPU)單獨運行一個線程,因此線程是并行工作的。

  5. 在單處理器系統(tǒng)中,處理器會給每個線程一小段時間,在這個時間內(nèi)線程是被執(zhí)行的,然后處理器執(zhí)行下一個線程,這樣就產(chǎn)生了線程并行運行的假象。

  6. 無論線程是否真的并行工作,在宏觀上可以認為子線程是獨立于主線程,且能與主線程并行工作的程序單元。

  7. Android中的線程是基于Java定義的線程,其內(nèi)部結(jié)構(gòu)如圖所示:


  8. 一個應(yīng)用程序中可能會包含多個線程(Thread),每個線程中都有一個run()方法,run()方法內(nèi)部的程序執(zhí)行完畢后,所在的線程就自動結(jié)束。

  9. 每個線程都有一個消息隊列,用于不同的線程之間傳遞消息。在run()方法內(nèi)部,如果不主動去讀取消息隊列中的消息,這些消息就是一些無用的消息,因為它們沒有被處理。

  10. 在Android系統(tǒng)中,讀取消息和處理消息是兩個步驟,并由兩個不同的部分完成,先讀取消息,然后才能處理消息。

  11. 無論是本線程的還是其它線程,都不能直接處理消息隊列中的消息,而是需要通過在線程內(nèi)部定義一個Handler類對象來處理消息隊列。一個Thread只能包含一個Handler對象。在實際應(yīng)用中,讀取消息隊列一般需要循環(huán)執(zhí)行,即不斷地從消息隊列中獲取消息并進行相應(yīng)處理,這就又需要一個Looper對象。

  12. Looper對象用于循環(huán)讀取消息隊列的值,并回調(diào)Handler對象中定義的消息處理函數(shù),同時,Looper對象還可以將讀取的消息從隊列中移除,執(zhí)行完一次消息處理后,再循環(huán)從消息隊列中讀取下一個消息,直到Looper對象調(diào)用stop()方法退出循環(huán)。如果消息隊列中沒有消息,Looper對象則會等待,線程不會退出。

  13. 為了更方便地從線程中使用Looper功能,Android又定義了一個HandlerThread類,該類基于Thread,并且內(nèi)部已經(jīng)添加了Looper功能,使用者只需重寫其onLooperPrepared ()方法,添加具體應(yīng)用代碼即可。Android中一個Activity就是一個線程,多個Activity之間的切換是在同一個線程中。
    文/SingleoD(簡書作者)原文鏈接


Activity生命周期 onStart onResume區(qū)別

首先了解Activity的四種狀態(tài)
Running狀態(tài):一個新的Activity啟動入棧后,它在屏幕最前端,處于棧的最頂端,此時它處于可見并可和用戶交互的激活狀態(tài)。Paused狀態(tài):當Activity被另一個透明或者Dialog樣式的Activity覆蓋時的狀態(tài)。此時它依然與窗口管理器保持連接,系統(tǒng)繼續(xù)維護其內(nèi)部狀態(tài),它仍然可見,但它已經(jīng)失去了焦點,故不可與用戶交互。Stopped狀態(tài):當Activity不可見時,Activity處于Stopped狀態(tài)。當Activity處于此狀態(tài)時,一定要保存當前數(shù)據(jù)和當前的UI狀態(tài),否則一旦Activity退出或關(guān)閉時,當前的數(shù)據(jù)和UI狀態(tài)就丟失了。Killed狀態(tài):Activity被殺掉以后或者被啟動以前,處于Killed狀態(tài)。這是Activity已從Activity堆棧中移除,需要重新啟動才可以顯示和使用。
4種狀態(tài)中,Running狀態(tài)和Paused狀態(tài)是可見的,Stopped狀態(tài)和Killed狀態(tài)時不可見的。

onStart()和onResume()的區(qū)別

onStart()是activity界面被顯示出來的時候執(zhí)行的,用戶可見,包括有一個activity在他上面,但沒有將它完全覆蓋,用戶可以看到部分activity但不能與它交互
onResume()是當該activity與用戶能進行交互時被執(zhí)行,用戶可以獲得activity的焦點,能夠與用戶交互。

onStart()通常就是onStop()(也就是用戶按下了home鍵,activity變?yōu)楹笈_后),之后用戶再切換回這個activity就會調(diào)用onRestart()而后調(diào)用onStart()
onResume()是onPause()(通常是當前的acitivty被暫停了,比如被另一個透明或者Dialog樣式的Activity覆蓋了),之后dialog取消,activity回到可交互狀態(tài),調(diào)用onResume()。

Paste_Image.png

引申:經(jīng)測試,onPause()方法在彈出Dialog時不會被調(diào)用,而在被另一個透明或者Dialog樣式的Activity覆蓋時才會被調(diào)用。
附activity生命周期:

Paste_Image.png

Fragment生命周期 Activity和Fragment區(qū)別

Activity生命周期圖:

onStart():可見時調(diào)用
onResume():獲取焦點時用
onPause():失去焦點時調(diào)用
onStop():不可見時調(diào)用
onRestart():重啟時調(diào)用
onDestory():銷毀時調(diào)用```

![activity.png](http://upload-images.jianshu.io/upload_images/2314135-57591e25232d1410.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**Fragment生命周期:**

onAttach():和宿主Activity建立關(guān)聯(lián)時調(diào)用
onCreate():創(chuàng)建時調(diào)用
onCreateView():加載Fragment的布局時調(diào)用
onActivityCreated():宿主Activity創(chuàng)建完畢時調(diào)用
onStart():可見時調(diào)用
onResume():獲取焦點時用
onPause():失去焦點時調(diào)用
onStop():不可見時調(diào)用
onDestoryView():移除Fragment的布局時調(diào)用
onDestory():銷毀時調(diào)用
onDetach():與宿主Activity解除關(guān)聯(lián)時調(diào)用

![Fragment.png](http://upload-images.jianshu.io/upload_images/2314135-156a9aaa667b4ab5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**Fragment與Activity生命周期對比圖:**

![Paste_Image.png](http://upload-images.jianshu.io/upload_images/2314135-bae480de789f439c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**Fragment生命周期分析:**
1. 當一個fragment被創(chuàng)建的時候,它會經(jīng)歷以下狀態(tài).
onAttach()
onCreate()
onCreateView()
onActivityCreated()

2. 當這個fragment對用戶可見的時候,它會經(jīng)歷以下狀態(tài)。
onStart()
onResume()

3. 當這個fragment進入“后臺模式”的時候,它會經(jīng)歷以下狀態(tài)。
onPause()
onStop()

4. 當這個fragment被銷毀了(或者持有它的activity被銷毀了),它會經(jīng)歷以下狀態(tài)。
onPause()
onStop()
onDestroyView()
onDestroy() // 本來漏掉類這個回調(diào),感謝xiangxue336提出。
onDetach()

5. 就像activitie一樣,在以下的狀態(tài)中,可以使用Bundle對象保存一個fragment的對象。
onCreate()
onCreateView()
onActivityCreated()

6. fragments的大部分狀態(tài)都和activitie很相似,但fragment有一些新的狀態(tài)。
onAttached() —— 當fragment被加入到activity時調(diào)用(在這個方法中可以獲得所在的activity)。
onCreateView() —— 當activity要得到fragment的layout時,調(diào)用此方法,fragment在其中創(chuàng)建自己的layout(界面)。
onActivityCreated() —— 當activity的onCreated()方法返回后調(diào)用此方法
onDestroyView() —— 當fragment中的視圖被移除的時候,調(diào)用這個方法。
onDetach() —— 當fragment和activity分離的時候,調(diào)用這個方法。

一旦activity進入resumed狀態(tài)(也就是running狀態(tài)),你就可以自由地添加和刪除fragment了。因此,只有當activity在resumed狀態(tài)時,fragment的生命周期才能獨立的運轉(zhuǎn),其它時候是依賴于activity的生命周期變化的。

**Activity生命周期分析:**
上面7個生命周期方法分別在4個階段按著一定的順序進行調(diào)用,這4個階段如下:
 開始Activity:在這個階段依次執(zhí)行3個生命周期方法:onCreate、onStart和onResume。
 Activity失去焦點:如果在Activity獲得焦點的情況下進入其他的Activity或應(yīng)用程序,這時當前的Activity會失去焦點。在這一階段,會依次執(zhí)行onPause和onStop方法。
Activity重新獲得焦點:如果Activity重新獲得焦點,會依次執(zhí)行3個生命周期方法:onRestart、onStart和onResume。
 關(guān)閉Activity:當Activity被關(guān)閉時系統(tǒng)會依次執(zhí)行3個生命周期方法:onPause、onStop和onDestroy。

 如果在這4個階段執(zhí)行生命周期方法的過程中不發(fā)生狀態(tài)的改變,那么系統(tǒng)會按著上面的描述依次執(zhí)行這4個階段中的生命周期方法,但如果在執(zhí)行的過程中改變了狀態(tài),系統(tǒng)會按著更復雜的方式調(diào)用生命周期方法。

在執(zhí)行的過程中可以改變系統(tǒng)的執(zhí)行軌跡的生命周期方法是onPause和onStop。如果在執(zhí)行onPause方法的過程中Activity重新獲得了焦點,然后又失去了焦點。系統(tǒng)將不會再執(zhí)行onStop方法,而是按著如下的順序執(zhí)行相應(yīng)的生命周期方法:onPause -> onResume-> onPause

如果在執(zhí)行onStop方法的過程中Activity重新獲得了焦點,然后又失去了焦點。系統(tǒng)將不會執(zhí)行onDestroy方法,而是按著如下的順序執(zhí)行相應(yīng)的生命周期方法:
onStop -> onRestart -> onStart -> onResume -> onPause -> onStop

 在圖Activity生命周期里可以看出,系統(tǒng)在終止應(yīng)用程序進程時會調(diào)用onPause、onStop和onDesktroy方法。而onPause方法排在了最前面,也就是說,Activity在失去焦點時就可能被終止進程,而onStop和onDestroy方法可能沒有機會執(zhí)行。因此,應(yīng)該在onPause方法中保存當前Activity狀態(tài),這樣才能保證在任何時候終止進程時都可以執(zhí)行保存Activity狀態(tài)的代碼.

---
###頁面之間如何傳遞數(shù)據(jù), 如果傳遞一個對象如何處理, 如何傳遞集合
* 1.簡單數(shù)據(jù)
   通過intent.putExtra("key","value")方法,在第二個界面中用getIntent()方法獲取啟動當前activity的intent,然后調(diào)用intent的getStringExtra()方法來獲取傳的數(shù)據(jù),如果傳遞的是整型,則用getIntExtra()方法來獲取,如果傳的是布爾型,則用getBooleanExtra()方法,以此類推。
通過Bundle,bundle.putString("key","value"),intnet.putExtras(bundle),
在第二個activity中獲取bundle:getIntent().getExtras();
接收參數(shù)s=bundle.getString("key")
* 2.集合

bundle.putParcelableArrayList("list",bundlelist);
//接收參數(shù)
list = bundle.getParcelableArrayList("list");

* 3.對象
*1.通過實現(xiàn)Serializable接口 *
      bundleSerializable.putSerializable("serializable", map2)
      //接收參數(shù)
      bundle.getSerializable("serializable");
*2.通過實現(xiàn)Parcelable接口*
這個是通過實現(xiàn)Parcelable接口,把要傳的數(shù)據(jù)打包在里面,然后在接收端自己分解出來。這個是Android獨有的,在其本身的源碼中也用得很多,效率要比Serializable相對要好。
1、復寫兩個方法,分別是describeContents和writeToParcel
2、實例化靜態(tài)內(nèi)部對象CREATOR,實現(xiàn)接口Parcelable.Creator 。 以上這兩步系統(tǒng)都已經(jīng)幫我們自動做好了
3、自己寫寫我們所需要的構(gòu)造方法,變量的get和set
        Intent putExtra(String name, Parcelable value)
      //接收參數(shù)
       intent.getParcelableExtra("key");
**對比**
android上應(yīng)該盡量采用Parcelable,效率至上
編碼上:
Serializable代碼量少,寫起來方便
Parcelable代碼多一些
效率上:
Parcelable的速度比高十倍以上

serializable的迷人之處在于你只需要對某個類以及它的屬性實現(xiàn)Serializable 接口即可。Serializable 接口是一種標識接口(marker interface),這意味著無需實現(xiàn)方法,Java便會對這個對象進行高效的序列化操作。  

 這種方法的缺點是使用了反射,序列化的過程較慢。這種機制會在序列化的時候創(chuàng)建許多的臨時對象,容易觸發(fā)垃圾回收。

Parcelable方式的實現(xiàn)原理是將一個完整的對象進行分解,而分解后的每一部分都是Intent所支持的數(shù)據(jù)類型,這樣也就實現(xiàn)傳遞對象的功能了

---
###dp px sp的區(qū)別
* dp:就是dip(device independent pixels)設(shè)備獨立像素,與密度無關(guān)的像素。一種基于屏幕密度的抽象單位。在每英寸160點(屏幕密度為160)的顯示器上,1dp=1px;
* px:屏幕的實際像素。一般不用它作為單位,因為它會在不同的設(shè)備顯示相同的效果。
* sp:與刻度無關(guān)的像素。主要用于定義字體的大小,而從來不再layout上使用。與dp相似,但是可以根據(jù)用戶的字體大小首選項進行縮放,即sp除了與密度無關(guān)外,還與scale(縮放)無關(guān)。當屏幕密度為160時,1dp=1sp=1px;
---

###gravity和layout_gravity的區(qū)別

* android:gravity:view里面的內(nèi)容在這個view中的位置
* android:layout_gravity:這個view相對于它父view的位置
**注意**
1.  對于horizontal的LinearLayout,把android:layout_gravity設(shè)為top、center、bottom、center_vertical才有意義;
2. 對于vertical 的LinearLayout,把android:layout_gravity設(shè)為left、center、right、center_horizontal才有意義;
3. RelativeLayout對android:layout_gravity不起作用
4. center已經(jīng)包含了center_vertical和center_horizontal兩種意義了,用的時候不要忘了
---
###margin和padding的區(qū)別
- margin是外邊距
- padding是內(nèi)邊距

舉個栗子:
一個LinearLayout中有一個ImageView,設(shè)置ImageView的padding和margin的屬性,那么

padding指的是ImageView中圖片距離圖片框的距離
margin指的是整一個ImageView距離LinearLayout邊界的距離
That's all.

---

###weight的作用
* android:layout_weight
表明該控件可以在父控件中占據(jù)的“剩余”空間。默認的weight是0。

---
###Handler機制
>[handler機制原理](http://blog.csdn.net/itachi85/article/details/8035333)

* Handler的定義:
   Handler主要用于接收子線程發(fā)送過來的數(shù)據(jù), 并用此數(shù)據(jù)配合主線程進行UI的更新。   當應(yīng)用程序啟動時,[Android](http://lib.csdn.net/base/15)首先會開啟一個主線程 (UI線程),主線程主要為管理界面中的UI控件,進行事件的分發(fā),好比如,你要點擊一個 Button控件,Android就會通過此Buttond的監(jiān)聽器分發(fā)事件到此Button上,以此來響應(yīng)你的操作。如果此時是一個需要耗時長的操作,例如:聯(lián)網(wǎng)讀取數(shù)據(jù),或者讀取本地較大的一個文件的時候,就不能把這些操作放在主線程當中了,如果被放在主線程中的話,界面會出現(xiàn)假死現(xiàn)象,如果5秒鐘還沒有完成的話,會收到Android系統(tǒng)的一個錯誤提示“強制關(guān)閉”。這個時候就需要把這些耗時的操作,放在一個子線程當中了,因為子線程可能會涉及到UI的更新,當新線程中有涉及到操作UI的操作時,就會對主線程產(chǎn)生危險,因此,Android提供了Handler作為主線程和子線程的紐帶。也就是說,更新UI只能在主線程當中進行更新,在子線程中操作是危險的。
   由于Handler是運行在主線程當中(UI線程中),它與子線程主要是通過Message對象來傳遞數(shù)據(jù),這個時候,Handler就承擔著接收子線程傳過來的(子線程用sedMessage()方法傳遞)Message對象(里面包含數(shù)據(jù)),把這些消息放入主線程隊列中,配合主線程進行更新UI。
   注意:Handler 對象初始化后,就默認與對它初始化的進程的消息隊列綁定,因此可以利用Handler所包含的消息隊列,制定一些操作的順序。
* Handler的主要作用
1.傳遞Message,用于接收子線程發(fā)送過來的數(shù)據(jù), 并用此數(shù)據(jù)配合主線程更新UI。
    在Android中,對于UI的操作通常需要放在主線程中進行操作。如果在子線程中有關(guān)于UI的操作,那么就需要把數(shù)據(jù)消息作為一個Message對象發(fā)送到消息隊列中,然后,由Handler中的handlerMessge()方法處理傳過來的數(shù)據(jù)信息,并操作UI。當然,Handler對象是在主線程中初始化的,它需要綁定在主線程的消息隊列中。
    類[sendMessage](file:///D:/android/android-sdk-windows/docs/reference/android/os/Handler.html#sendMessage(android.os.Message))([Message](file:///D:/android/android-sdk-windows/docs/reference/android/os/Message.html) msg)方法實現(xiàn)發(fā)送消息的操作。在初始化Handler對象時重寫的handleMessage()方法是用來來接收Messgae并進行相關(guān)操作的。
2.傳遞Runnable對象,用于通過Handler綁定的消息隊列,安排不同操作的執(zhí)行順序。
    Handler對象在進行初始化的時候,會默認的自動綁定消息隊列。利用類post方法,可以將Runnable對象發(fā)送到消息隊列中,按照隊列的機制按順序執(zhí)行不同的Runnable對象中的run方法。
---
###什么的ANR, 如何避免
**ANR的定義**:在Android上,如果你的應(yīng)用程序有一段時間響應(yīng)不夠靈敏,系統(tǒng)會向用戶顯示一個對話框,這個對話框稱作**應(yīng)用程序無響應(yīng)**(ANR:ApplicationNotResponding)對話框。用戶可以選擇讓程序繼續(xù)運行,但是,他們在使用你的應(yīng)用程序時,并不希望每次都要處理這個對話框。因此,在程序里對響應(yīng)性能的設(shè)計很重要,這樣,系統(tǒng)不會顯示ANR給用戶。

 **如何避免:**
* UI線程盡量只做跟UI相關(guān)的工作
* 耗時的操作(比如數(shù)據(jù)庫操作,I/O,連接網(wǎng)絡(luò)或者別的有可能阻塞UI線程的操作)把它放在單獨的線程處理
* 盡量用Handler來處理UIThread和別的Thread之間的交互
* BroadcastReceiver要執(zhí)行耗時操作時應(yīng)啟動一個service,將耗時操作交給service來完成

** ANR排錯一般有三種類型:**
KeyDispatchTimeout(5 seconds) --主要是類型按鍵或觸摸事件在特定時間內(nèi)無響應(yīng)
BroadcastTimeout(10 seconds) --BroadcastReceiver在特定時間內(nèi)無法處理完成
ServiceTimeout(20 secends) --小概率事件 Service在特定的時間內(nèi)無法處理完成

---
###顯式意圖和隱式意圖區(qū)別,隱式意圖的使用
* 一、顯示調(diào)用Intent

Intent intent=new Intent(this,SecondActivity.class);
startActivity(intent);

* 二、隱式啟動Intent

Intent intent=new Intent("com.xu.mytest");
startActivity(intent);
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.xu.mytest"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>

我們在這里給Activity設(shè)置了一個IntentFilter,但是值得注意的是,一個組件可以有多個IntentFilter,在過濾的時候只要有一個符合要求的,就會被視為過濾通過。
那我們就看看是怎樣過濾的吧,首先我們應(yīng)該明白一個大的思路:當我們隱式的啟動一個組件的時候,就會一個一個的去過濾對應(yīng)組件的全部,(比如你是隱式的啟動一個Activity,就會一個一個的在全部Activity中篩選),然后根據(jù)Intent的所設(shè)置的action、category、data去比較IntentFilter所設(shè)置的這三個屬性,相同的話就過濾留下來了。


* **區(qū)別**
** 顯式啟動**:直接指定要跳轉(zhuǎn)的Activity類名,不用過濾,效率高,適用于同一個應(yīng)用中的不同Activity跳轉(zhuǎn)
** 隱式啟動**:需要過濾,相對耗時,但可以找到所有之匹配的應(yīng)用。適用于不同應(yīng)用之間的Activity跳轉(zhuǎn)。

---
###廣播幾種接收方式, 廣播有幾種類型, 區(qū)別
* #####接收方式
注冊廣播的方式一般有兩種,在代碼中注冊稱為動態(tài)注冊;在AndroidManifest.xml中注冊稱為靜態(tài)注冊。
*** 動態(tài)注冊:***
定義一個類繼承自BroadcastReceiver,并復寫父類的onReceive()方法,在activity中實例化自定義廣播,使用Context的**registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)**方法注冊廣播
**需要注意的是:**動態(tài)注冊廣播接收器一定都要取消注冊。在onDestroy()方法中調(diào)用**unregisterReceiver()**方法就可以實現(xiàn)取消注冊了。
**靜態(tài)注冊:**
* 首先新建一個BootCompleteReceiver類繼承BroadcastReceiver

public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Boot Complete",Toast.LENGTH_LONG).show();
}
}

* 接下來需要在AndroidManifest.xml聲明BootCompleteReceiver這個類,BroadcastReceiver是安卓的四大組件之一,所以以下代碼需要寫在<application>標簽內(nèi)

<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

這樣就可以實現(xiàn)廣播的靜態(tài)注冊了。
** 區(qū)別:**
第一種不是常駐型廣播,也就是說廣播跟隨程序的生命周期。
第二種是常駐型,也就是說當應(yīng)用程序關(guān)閉后,如果有信息廣播來,程序也會被系統(tǒng)調(diào)用自動運行。

* #####廣播的類型
**1.標準廣播**標準廣播是一種完全異步執(zhí)行的廣播,在廣播發(fā)出之后,所有的廣播接收器幾乎會同時接收到這條廣播消息。此類廣播效率較高而且不能截斷。

通過mContext.sendBroadcast(Intent)
或mContext.sendBroadcast(Intent, String)
發(fā)送的是無序廣播(后者加了權(quán)限);

![](http://upload-images.jianshu.io/upload_images/2314135-f4e397ebbf5e2fcb.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

**2.有序廣播**有序廣播是一種同步執(zhí)行的廣播,廣播發(fā)出之后,優(yōu)先級高的廣播接收器就可以先接收到廣播消息,執(zhí)行完該廣播接收器的邏輯后,可以選擇截斷正在傳遞的廣播或者繼續(xù)傳遞,如果廣播消息被截斷,之后的廣播接收器則無法收到廣播消息。

通過mContext.sendOrderedBroadcast(Intent, String, BroadCastReceiver, Handler, int, String, Bundle)
發(fā)送的是有序廣播。
//第一個參數(shù):intent
//第二個參數(shù):String類型的接收者權(quán)限
//第三個參數(shù):BroadcastReceiver 指定的接收者
//第四個參數(shù):Handler scheduler
//第五個參數(shù):int 此次廣播的標記
//第六個參數(shù):String 初始數(shù)據(jù)
//第七個參數(shù):Bundle 往Intent中添加的額外數(shù)據(jù)

<receiver android:name=".MyReceiver1" >

<intent-filter android:priority="1000">

<action android:name="com.example.broadcast"/>
</intent-filter>
</receiver>

![](http://upload-images.jianshu.io/upload_images/2314135-eb2a70372c3fb0b2.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
[**參考**](http://www.lxweimin.com/p/ea5e233d9f43)
* **區(qū)別**:
無序廣播:所有的接收者都會接收事件,不可以被攔截,不可以被修改。
有序廣播:按照優(yōu)先級,一級一級的向下傳遞,接收者可以修改廣播數(shù)據(jù),也可以終止廣播事件。

---

###開啟Service的幾種方式, 區(qū)別, Service和Activity之間如何傳遞數(shù)據(jù)
***開啟Service的兩種方式***:
* 1. **startService(Intent serviceIntent)** 一個組件可以通過startService的方式來開啟Service服務(wù)。這種方式開啟的Service可以調(diào)用**stopSelf()**來停止服務(wù),也可以通過在其他組件中調(diào)用stopService()方法來停止。
* 2.**bindService(Intent service ,ServiceConnection conn ,Int flags)** 參數(shù)service是指要綁定的Service,conn是ServiceConnection對象,這個對象不能為null,flags為binding的類型,可以為0。 這種方式開啟的Service會一直運行,直到?jīng)]有組件綁定這個Service的時候系統(tǒng)才會停止Service。一般情況下,一個組件在不需要Service服務(wù)后要調(diào)用**unBindService(ServiceConnection conn)**來解綁Service。

**區(qū)別:**
* startService:生命周期與調(diào)用者不同,啟動后若調(diào)用者未調(diào)用stopService而直接退出,Service仍會運行
* bindService:生命周期與調(diào)用者綁定(Service的生命周期依附于Context),調(diào)用者一旦全部退出,Service就會調(diào)用unBind->onDestroy
---
###Service中如果要start一個Activity要如何特殊處理,為什么
Intent intent = new Intent(Service.this,TestActivity.class);
**intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);**
startActivity(intent);

在service里面啟動Activity的話,必須添加FLAG_ACTIVITY_NEW_TASK flag
為什么Android在Service 里面啟動Activity要強制規(guī)定使用參數(shù)FLAG_ACTIVITY_NEW_TASK呢?我們可以來做這樣一個假設(shè),我們有這樣一個需求:我們在電話本里面啟動一個Service,然后它執(zhí)行5分鐘后,啟動一個Activity那么很有可能用戶在5分鐘后已經(jīng)不在電話本程序里面操作了,有可能去上網(wǎng),打開瀏覽器程序了。5分鐘后,此時當前的Task是瀏覽器的task,那么彈出Activity,如果這個Activity在當前Task的話,也就是瀏覽器的Task;那么用戶就會覺得莫名其妙;因為彈出的Activity和瀏覽器在一個Task,本來這個Activity應(yīng)該屬于電話本的。所以,對于Service而言,干脆強制定義啟動的Activity要創(chuàng)建一個新的Task.這種設(shè)計,我覺得還是比較合理的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,749評論 25 708
  • 1.什么是Activity?問的不太多,說點有深度的 四大組件之一,一般的,一個用戶交互界面對應(yīng)一個activit...
    JoonyLee閱讀 5,754評論 2 51
  • 窗外的雨一直淅淅瀝瀝,好幾年了,南方的天氣一直那么善變,雨也是說下就下,一下就是好幾天。我在這里生活的時間...
    沐柯閱讀 287評論 0 0
  • 權(quán)限 權(quán)限一般分為:讀,寫,執(zhí)行。每個文件都有權(quán)限,都有所屬的用戶,所屬的組。每個進程都是以用戶的身份運行,進程的...
    瀟涵quant閱讀 363評論 0 0
  • 在遇見她的時候,我們也很驚訝,因為她竟然快60歲了,還可以做到每天三千字。而這無疑是自律的一種表現(xiàn)和體現(xiàn),那么究竟...
    王立登閱讀 2,477評論 9 47