Activity生命周期?保存activity的一些信息在哪個生命周期方法中秕硝?
共有七個周期函數(shù):
void onCreate(Bundle savedInstanceState) 第一次創(chuàng)建時調(diào)用
void onStart() 被用戶可見時調(diào)用
void onResume() 當(dāng)獲得焦點即可與用戶交互時調(diào)用
void onPause() 當(dāng)失去焦點時調(diào)用
void onStop() 當(dāng)不可見時調(diào)用
void onRestart() 當(dāng)Activity處于stop狀態(tài)又被重新啟動時調(diào)用
void onDestroy() 當(dāng)銷毀時調(diào)用
onPause() 保存
說說Activity芥映,Intent,Service是什么關(guān)系
一個 Activity 通常是一個單獨的屏幕远豺,每一個Activity 都被實現(xiàn)為一個單獨的類奈偏,這些類都是從Activity 基類中繼承來的,Activity 類會顯示由視圖控件組成的用戶接口躯护,并對視圖控件的事件做出響應(yīng)惊来。
Intent 的調(diào)用是用戶進(jìn)行架構(gòu)屏幕之間的切換的,Intent 是描述應(yīng)用想要做什么棺滞。Intent 數(shù)據(jù)結(jié)構(gòu)中兩個最重要的部分是動作和動作對應(yīng)的數(shù)據(jù)裁蚁,一個動作對應(yīng)一個動作數(shù)據(jù)。
Android Service 是運行在后臺的代碼继准,不能與用戶交互枉证,可以運行在自己的進(jìn)程,也可以運行在其他應(yīng)用程序進(jìn)程的上下文里移必。需要通過某一個Activity 或者其他 Context 對象來調(diào)用.
Activity 跳轉(zhuǎn)到 Activity ,Activity 啟動Service ,Service 打開Activity都需要Intent 表時跳轉(zhuǎn)的意圖室谚,以及傳遞參數(shù),Intent 是這些組件間信號傳遞的承載者。
BroadcastReceive廣播接收器:你的應(yīng)用可以使用它 對外部事件進(jìn)行過濾只對感興趣的外部事件(如當(dāng)電話呼入時舞萄,或者數(shù)據(jù)網(wǎng)絡(luò)可用時)進(jìn)行接收并做出響應(yīng)眨补。
當(dāng)系統(tǒng)或用戶應(yīng)用程序發(fā)送了某廣播之后,符合條件的廣播接收者都將收到該條廣播倒脓。
什么是IntentService撑螺,有何優(yōu)點
IntentService使用隊列的方式將請求的Intent加入隊列,然后開啟一個worker thread(線程)來處理隊列中的Intent崎弃,對于異步的startService請求甘晤,IntentService會處理完成一個之后再處理第二個,每一個請求都會在一個單獨的worker thread中處理饲做,不會阻塞應(yīng)用程序的主線程线婚,這里就給我們提供了一個思路,如果有耗時的操作與其在Service里面開啟新線程還不如使用IntentService來處理耗時操作盆均。
android將進(jìn)程的優(yōu)先級分為5個層次塞弊,按照優(yōu)先級由高到低排列如下:
- 前臺進(jìn)程(Foreground process)。它表明用戶正在與該進(jìn)程進(jìn)行交互操作,android系統(tǒng)依據(jù)下面的條件來將一個進(jìn)程標(biāo)記為前臺進(jìn)程:
- 可見進(jìn)程(Visible process)。它表明雖然該進(jìn)程沒有持有任何前臺組件偶翅,但是它還是能夠影響到用戶看得到的界面肖方。android系統(tǒng)依據(jù)下面的條件將一個進(jìn)程標(biāo)記為可見進(jìn)程:
- 服務(wù)進(jìn)程(Service process)囤官。除了符合前臺進(jìn)程和可見進(jìn)程條件的Service,其它的Service都會被歸類為服務(wù)進(jìn)程。
- 后臺進(jìn)程(Background process)。持有不可見Activity(調(diào)用了onStop()方法)的進(jìn)程即為后臺進(jìn)程眯勾。通常情況下都會有很多后臺進(jìn)程,當(dāng)內(nèi)存不足的時候婆誓,在所有的后臺進(jìn)程里面吃环,會按照LRU(最近使用)規(guī)則,優(yōu)先回收最長時間沒有使用過的進(jìn)程洋幻。
- 空進(jìn)程(Empty process)郁轻。不持有任何活動組件的進(jìn)程。保持這種進(jìn)程只有一個目的鞋屈,就是為了緩存,以便下一次啟動該進(jìn)程中的組件時能夠更快響應(yīng)故觅。當(dāng)資源緊張的時候厂庇,系統(tǒng)會平衡進(jìn)程緩存和底層的內(nèi)核緩存情況進(jìn)行回收。
Android Jetpack
對于任何一個產(chǎn)品來說输吏,我們開發(fā)中都會面對哪些問題权旷?如:產(chǎn)品交互、用戶體驗、代碼結(jié)構(gòu)拄氯、數(shù)據(jù)獲取躲查、數(shù)據(jù)存儲、網(wǎng)絡(luò)優(yōu)化译柏、任務(wù)調(diào)度等等镣煮,雖然在現(xiàn)在的階段這些問題已經(jīng)有了很好的解決和優(yōu)化,也有很多大神的開源組件方便開發(fā)者去使用鄙麦,Android Jetpack就是Google給出的一個官方的處理方法(當(dāng)然知識處理其中基本問題)典唇,Android Jetpack組件的優(yōu)勢:
輕松管理應(yīng)用程序的生命周期
構(gòu)建可觀察的數(shù)據(jù)對象,以便在基礎(chǔ)數(shù)據(jù)庫更改時通知視圖
存儲在應(yīng)用程序輪換中未銷毀的UI相關(guān)數(shù)據(jù)胯府,在界面重建后恢復(fù)數(shù)據(jù)
輕松的實現(xiàn)SQLite數(shù)據(jù)庫
系統(tǒng)自動調(diào)度后臺任務(wù)的執(zhí)行介衔,優(yōu)化使用性能
Android Jetpack組件推薦的使用項目架構(gòu)
上面架構(gòu)組件的功能如下:
Activity和Fragment負(fù)責(zé)產(chǎn)品與用戶的交互
ViewModel作為數(shù)據(jù)的存儲和驅(qū)動
Resposity負(fù)責(zé)調(diào)度數(shù)據(jù)的獲取
Room儲存本地序列化的數(shù)據(jù)
Retrofit獲取遠(yuǎn)程數(shù)據(jù)的數(shù)據(jù)
SharedPreferences
/同步保存更改的方法/
boolean commit();
異步保存到磁盤,原子提交骂因,性能更高炎咖,不保證結(jié)果/
void apply();
- SharedPreferences 是線程安全的. 內(nèi)部由大量 synchronized 關(guān)鍵字保障
- SharedPreferences 不是進(jìn)程安全的
Service的詳解
Service生命周期可以從兩種啟動Service的模式開始講起,分別是context.startService()和context.bindService()寒波。
(1).startService的啟動模式下的生命周期:當(dāng)我們首次使用startService啟動一個服務(wù)時乘盼,系統(tǒng)會實例化一個Service實例,依次調(diào)用其onCreate和onStartCommand方法影所,然后進(jìn)入運行狀態(tài)蹦肴,此后,如果再使用startService啟動服務(wù)時猴娩,不再創(chuàng)建新的服務(wù)對象阴幌,系統(tǒng)會自動找到剛才創(chuàng)建的Service實例,調(diào)用其onStart方法卷中;如果我們想要停掉一個服務(wù)矛双,可使用stopService方法,此時onDestroy方法會被調(diào)用蟆豫,需要注意的是议忽,不管前面使用了多個次startService,只需一次stopService十减,即可停掉服務(wù)栈幸。
(2).bindService啟動模式下的生命周期:在這種模式下,當(dāng)調(diào)用者首次使用bindService綁定一個服務(wù)時帮辟,系統(tǒng)會實例化一個Service實例速址,并一次調(diào)用其onCreate方法和onBind方法,然后調(diào)用者就可以和服務(wù)進(jìn)行交互了由驹,此后芍锚,如果再次使用bindService綁定服務(wù),系統(tǒng)不會創(chuàng)建新的Service實例,也不會再調(diào)用onBind方法并炮;如果我們需要解除與這個服務(wù)的綁定默刚,可使用unbindService方法,此時onUnbind方法和onDestroy方法會被調(diào)用逃魄。
兩種模式有以下幾點不同之處:startService模式下調(diào)用者與服務(wù)無必然聯(lián)系荤西,即使調(diào)用者結(jié)束了自己的生命周期,只要沒有使用stopService方法停止這個服務(wù)嗅钻,服務(wù)仍會運行皂冰;通常情況下,bindService模式下服務(wù)是與調(diào)用者生死與共的养篓,在綁定結(jié)束之后秃流,一旦調(diào)用者被銷毀,服務(wù)也就立即終止
Service 進(jìn)程內(nèi)與服務(wù)通信
進(jìn)程內(nèi)與服務(wù)通信實際上就是通過bindService的方式與服務(wù)綁定柳弄,獲取到通信中介Binder實例舶胀,然后通過調(diào)用這個實例的方法,完成對服務(wù)的各種操作碧注。
應(yīng)用組件(客戶端)可以調(diào)用bindService()綁定到一個service.Android系統(tǒng)之后調(diào)用service的onBind()方法嚣伐,它返回一個用來與service交互的IBinder.
綁定是異步的.bindService()會立即返回,它不會返回IBinder給客戶端.要接收IBinder萍丐,客戶端必須創(chuàng)建一個ServiceConnection的實例并傳給bindService().ServiceConnection包含一個回調(diào)方法轩端,系統(tǒng)調(diào)用這個方法來傳遞要返回的IBinder.
IBinder是接口,你看前面有個I逝变,理解為接口基茵,他的實現(xiàn)類必須自己編寫代碼邏輯來實現(xiàn)功能。
Binder是實現(xiàn)了IBinder的具體實現(xiàn)類壳影,他具有具體的功能拱层,繼承了Binder的類就是IBinder對象了。
服務(wù)端
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind called.");
return new MyBinder();
}
/**
* 綁定對象
*
* @author user
*/
public class MyBinder extends Binder {
//Activity調(diào)用
public void greet(String name) {
Log.i(TAG, "hello, " + name);
}
}
Activity里面 的代碼宴咧。
bindService(intent, conn, Context.BIND_AUTO_CREATE);
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//connected
binder = (MyService.MyBinder) service; //獲取其實例Service里面的MyBinder
binder.greet("scott"); //調(diào)用其方法
Log.i("MyService", "onServiceConnected called.");
}
/**
* Called when a connection to the Service has been lost.
* This typically happens when the process hosting the service has crashed or been killed.
* This does not remove the ServiceConnection itself.
* this binding to the service will remain active,
* and you will receive a call to onServiceConnected when the Service is next running.
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
AIDL實現(xiàn)跨進(jìn)程通訊
服務(wù)端
新建AIDL接口 編譯器會自動生成一個和AIDL名字相同的JAVA類根灯,這個 .java 文件才是與我們的跨進(jìn)程通信密切相關(guān)的東西。
在服務(wù)端實現(xiàn)AIDL中定義的方法接口的具體邏輯掺栅,然后在客戶端調(diào)用這些方法接口烙肺,AIDL接口相當(dāng)于暴露出去可以給其他應(yīng)用調(diào)用
寫服務(wù)端代碼的時候,第一塊是初始化氧卧。在 onCreate() 方法里面我進(jìn)行了一些數(shù)據(jù)的初始化操作桃笙。第二塊是重寫 BookManager.Stub 中的方法。在這里面提供AIDL里面定義的方法接口的具體實現(xiàn)邏輯假抄。第三塊是重寫 onBind() 方法怎栽。在里面返回寫好的 BookManager.Stub 。
客戶端和服務(wù)端AIDL的包名必須完全一致宿饱。
客戶端:
客戶端我們要完成的工作主要是調(diào)用服務(wù)端的方法熏瞄,但是在那之前,我們首先要連接上服務(wù)端谬以,
首先bindService()建立連接强饮,然后在 ServiceConnection 里面獲取 服務(wù)端的AIDL接口 對象,(方法返回我們的接口的引用为黎。接著客戶端就可以通過它來對服務(wù)端發(fā)送請求了)
兩種AIDL文件:在我的理解里邮丰,所有的AIDL文件大致可以
分為兩類。一類是用來定義parcelable對象铭乾,以供其他AIDL文件使用AIDL中非默認(rèn)支持的數(shù)據(jù)類型的剪廉。一類是用來定義方法接口,以供系統(tǒng)使用來完成跨進(jìn)程通信的
AIDL可用數(shù)據(jù)類型
Java中的八種基本數(shù)據(jù)類型炕檩,包括 byte斗蒋,short,int笛质,long泉沾,float,double妇押,boolean跷究,char。
String 類型敲霍。
CharSequence類型俊马。
List類型:List中的所有元素必須是AIDL支持的類型之一,或者是一個其他AIDL生成的接口色冀,或者是定義的parcelable潭袱。List可以使用泛型
Map類型 Map中的所有元素必須是AIDL支持的類型之一,或者是一個其他AIDL生成的接口锋恬,或者是定義的parcelable屯换。Map是不支持泛型的
哪些地方是執(zhí)行在主線程的
- [Activity的所有生命周期(http://www.reibang.com/p/ec6984aa1bb4)都是執(zhí)行在主線程的.
- Service默認(rèn)是執(zhí)行在主線程的
- BroadcastReceiver的onReceive回調(diào)是執(zhí)行在主線程的.
- 沒有使用子線程的looper的Handler的handleMessage, post(Runnable)是執(zhí)行在主線程的.
- AsyncTask的回調(diào)中除了doInBackground, 其他都是執(zhí)行在主線程的.
- View的post(Runnable)是執(zhí)行在主線程的.
android如何動態(tài)刷新UI
1.利用Looper更新UI界面
2.AsyncTask利用線程任務(wù)異步更新UI界面 如果是后臺任務(wù),像是下載任務(wù)等与学,就需要使用AsyncTask彤悔。
3.利用Runnable更新UI界面
請描述一下Intent 和 Intent Filter。
Intent在Android中被翻譯為"意圖"索守,熟語來講就是目的晕窑,他們是三種應(yīng)用程序基本組件—activity,service和broadcast receiver之間互相激活的手段卵佛。在調(diào)用Intent名稱時使用ComponentName也就是類的全名時為顯示調(diào)用杨赤。這種方式一般用于應(yīng)用程序的內(nèi)部調(diào)用敞斋,因為你不一定會知道別人寫的類的全名。我們來看看隱式Intent怎么用疾牲?首先我們先配置我們的Activity的Intent Filter
<intent-filter><actionandroid:name="com.example.project.SHOW_CURRENT"/></intent-filter>
這樣在調(diào)用的時候指定Intent的action植捎,系統(tǒng)就是自動的去對比是哪個intent-filter符合我們的Activity,找到后就會啟動Activity阳柔。
一個intent filter是IntentFilter類的實例, 但是它一般不出現(xiàn)在代碼中,而是出現(xiàn)在android Manifest文件中, 以<intent-filter>的形式. (有一個例外是broadcast receiver的intent filter是使用Context.registerReceiver()來動態(tài)設(shè)定的, 其intent filter也是在代碼中創(chuàng)建的.)
一個filter有action, data, category等字段. 一個隱式intent為了能被某個intent filter接受, 必須通過3個測試. 一個intent為了被某個組件接受, 則必須通過它所有的intent filter中的一個.
廣播如何調(diào)用焰枢,有什么方式,各自的區(qū)別舌剂?
程序中發(fā)送廣播通過sendBroadcastReceiver()實現(xiàn)
接收廣播通過定義一個類繼承BroadcastReceiver并重寫onReceive()方法實現(xiàn)
注冊廣播有兩種方式:
第一種靜態(tài)方式:在清單文件中通過<receive>標(biāo)簽聲明
第二種代碼動態(tài)方式:
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver receiver = new IncomgSMSReceiver();
registerReceiver(receiver.filter);
1)第二種不是常駐型廣播济锄,也就是說廣播跟隨activity的生命周期。注意: 在activity結(jié)束前霍转,移除廣播接收器荐绝。
2)第一種是常駐型,也就是說當(dāng)應(yīng)用程序關(guān)閉后避消,如果有信息廣播來很泊,程序也會被系統(tǒng)調(diào)用自動運行。
Android中asset文件夾和raw文件夾區(qū)別沾谓?
res/raw和assets的相同點:
兩者目錄下的文件在打包后會原封不動的保存在apk包中委造,不會被編譯成二進(jìn)制。
res/raw和assets的不同點:
1)res/raw中的文件會被映射到R.java文件中均驶,訪問的時候直接使用資源ID即 R.raw.filename昏兆;assets文件夾下的文件不會被映射到R.java中,訪問的時候需要AssetManager類妇穴。
2)res/raw不可以有目錄結(jié)構(gòu)爬虱,而assets則可以有目錄結(jié)構(gòu),也就是assets目錄下可以再建立文件夾
3)讀取文件資源舉例:
讀取res/raw下的文件資源腾它,通過以下方式獲取輸入流來進(jìn)行寫操作
InputStream is = getResources().openRawResource(R.raw.filename);
讀取assets下的文件資源跑筝,通過以下方式獲取輸入流來進(jìn)行寫操作
AssetManager am = null;
am = getAssets();
InputStream is = am.open("filename");
android系統(tǒng)架構(gòu)
1)應(yīng)用程序?qū)? java語言 應(yīng)用程序開發(fā)
2)應(yīng)用程序框架層 java語言 OS定制 framework層開發(fā)
3)系統(tǒng)運行庫層 C C++ 實現(xiàn) so庫
4)Linux內(nèi)核層
請介紹下Android的數(shù)據(jù)存儲方式。
使用SharedPreferences存儲數(shù)據(jù)瞒滴;
文件存儲數(shù)據(jù)曲梗;
SQLite數(shù)據(jù)庫存儲數(shù)據(jù);
使用ContentProvider存儲數(shù)據(jù)妓忍;
網(wǎng)絡(luò)存儲數(shù)據(jù)
請介紹下ContentProvider是如何實現(xiàn)數(shù)據(jù)共享的虏两。
答:當(dāng)應(yīng)用繼承ContentProvider類,并重寫該類用于提供數(shù)據(jù)和存儲數(shù)據(jù)的方法世剖,就可以向其他應(yīng)用共享其數(shù)據(jù)定罢。
雖然使用其他方法也可以對外共享數(shù)據(jù),但數(shù)據(jù)訪問方式會因數(shù)據(jù)存儲的方式而不同旁瘫,如:采用文件方式對外共享數(shù)據(jù)祖凫,需要進(jìn)行文件操作讀寫數(shù)據(jù)琼蚯;
采用sharedpreferences共享數(shù)據(jù),需要使用sharedpreferences API讀寫數(shù)據(jù)惠况。
而使用ContentProvider共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)訪問方式凌停。
當(dāng)應(yīng)用需要通過ContentProvider對外共享數(shù)據(jù)時,
第一步需要繼承ContentProvider并重寫下面方法:
第二步需要在AndroidManifest.xml使用<provider>對該ContentProvider進(jìn)行配置售滤,為了能讓其他應(yīng)用找到該ContentProvider , ContentProvider 采用了authorities(主機(jī)名/域名)對它進(jìn)行唯一標(biāo)識台诗,你可以把 ContentProvider看作是一個網(wǎng)站(想想完箩,網(wǎng)站也是提供數(shù)據(jù)者),authorities 就是他的域名:
你后臺的Activity被系統(tǒng)回收怎么辦拉队? 如何在回收之前保存當(dāng)前狀態(tài)
當(dāng)一個Activity被pause或者stop的時候,這個Activity的對象實際上還是保存在內(nèi)存中,因此這個Activity中的信息(成員和狀態(tài)信息)還可以重新獲取到.
如果系統(tǒng)為了整理內(nèi)存而銷毀了整合各Activity對象時,系統(tǒng)沒法簡單的原封不動地恢復(fù)先前的Activity對象及其狀態(tài)信息. Activity中提供了一個方法:onSavedInstanceState(Bundle obj).當(dāng)系統(tǒng)銷毀一個Activity時,會將Activity的狀態(tài)信息已鍵值對形式存放在bundle對象中.
第一次啟動Activity時,這個bundle對象是空的,null.如果Activity被系統(tǒng)銷毀了,然后用戶要回退回去看的話,系統(tǒng)會調(diào)用這個Activity的onCreate方法,并把bundle對象傳遞過去.
這個函數(shù)有默認(rèn)的行為,因此就算你不覆蓋它,它在Activity中也有實現(xiàn).
另外,剛才查看了一下Activity的源碼,發(fā)現(xiàn)Activity還有個onRestoreInstanceState(Bundle outState)方法.這個方法的描述中也寫到在Activity恢復(fù)先前保存的狀態(tài)時會被調(diào)用.
第二種情況 在OnStop中保存狀態(tài)在本地弊知,然后在OnResume中本地恢復(fù)狀態(tài)。
如何將一個Activity設(shè)置成窗口的樣式粱快。 ]
1.在你的styles.xml文件-中可以新建一如下的style:
<style name="Theme.FloatActivity" parent="android:style/Theme.Dialog">
在AndroidManifest.xml中在你需要顯示為窗口的activity中添加如果屬性:android:theme="@style/Theme.FloatActivity"秩彤。
設(shè)置透明模式
android:theme="@android:style/Theme.Translucent"
如何退出Activity?如何安全退出已調(diào)用多個Activity的Application
1事哭、拋異常強(qiáng)制退出: 該方法通過拋異常漫雷,使程序Force Close。 驗證可以鳍咱,但是降盹,需要解決的問題是,如何使程序結(jié)束掉谤辜,而不彈出Force Close的窗口蓄坏。
2、記錄打開的Activity: 用到Task杖 每打開一個Activity丑念,就記錄下來涡戳。在需要退出時,關(guān)閉每一個Activity即可脯倚。
3渔彰、發(fā)送特定廣播: 在需要結(jié)束應(yīng)用時,發(fā)送一個特定的廣播推正,每個Activity收到廣播后胳岂,關(guān)閉即可。
4舔稀、遞歸退出 在打開新的Activity時使用startActivityForResult乳丰,然后自己加標(biāo)志,在onActivityResult中處理内贮,遞歸關(guān)閉产园。 除了第一個汞斧,都是想辦法把每一個Activity都結(jié)束掉,間接達(dá)到目的什燕。 但是這樣做同樣不完美粘勒。 你會發(fā)現(xiàn),如果自己的應(yīng)用程序?qū)γ恳粋€Activity都設(shè)置了nosensor屎即,在兩個Activity結(jié)束的間隙庙睡,sensor可能有效了。 但至少技俐,我們的目的達(dá)到了乘陪,而且沒有影響用戶使用。
Android App 安全策略
Activity window view 的關(guān)系
Activity雕擂、View啡邑、Window的理解一篇文章就夠了
window 視圖承載器
Activity在attch方法的時候,會創(chuàng)建一個phonewindow(window的子類)
onCreate中的setContentView方法井赌,會創(chuàng)建DecorView
DecorView 的addview方法谤逼,會把layout中的布局加載進(jìn)來。
java class 初始化和對象的創(chuàng)建順序
靜態(tài)變量/靜態(tài)代碼塊 -> 普通代碼塊 -> 構(gòu)造函數(shù)
- 父類靜態(tài)變量和靜態(tài)代碼塊仇穗;
- 子類靜態(tài)變量和靜態(tài)代碼塊流部;
- 父類普通成員變量和普通代碼塊;
- 父類的構(gòu)造函數(shù)纹坐;
- 子類普通成員變量和普通代碼塊贵涵;
- 子類的構(gòu)造函數(shù)。
class 文件被加載到內(nèi)存中需要經(jīng)過 3 大步:裝載恰画、鏈接宾茂、初始化
模塊化 vs 組件化
模塊化粒度更小,更側(cè)重于重用,而組件化粒度稍大于模塊,更側(cè)重于業(yè)務(wù)解耦.
LeakCanary的實現(xiàn)原理。
用ActivityLifecycleCallbacks接口來檢測Activity生命周期
主要是在Activity的&onDestroy方法中拴还,手動調(diào)用 GC跨晴,然后利用ReferenceQueue+WeakReference,來判斷是否有釋放不掉的引用片林,然后結(jié)合dump memory的hpof文件, 用HaHa分析出泄漏地方端盆。
WebView優(yōu)化
- 全局WebView
方法:
在客戶端剛啟動時,就初始化一個全局的WebView待用费封,并隱藏焕妙;
當(dāng)用戶訪問了WebView時,直接使用這個WebView加載對應(yīng)網(wǎng)頁弓摘,并展示焚鹊。 - 客戶端代理數(shù)據(jù)請求
方法:
在客戶端初始化WebView的同時,直接由native開始網(wǎng)絡(luò)請求數(shù)據(jù)韧献;
當(dāng)頁面初始化完成后末患,向native獲取其代理請求的數(shù)據(jù)
Android自定義組件實現(xiàn)思路
Android自定義組件有三種實現(xiàn)思路:
- 繼承某個現(xiàn)有組件研叫,在其基礎(chǔ)上添加額外功能,如繼承Gallery實現(xiàn)CoverFlow效果
- 繼承某個Layout,實現(xiàn)復(fù)合組件自定義璧针,如TextView和EditText組合實現(xiàn)登錄注冊組件
- 繼承View嚷炉,實現(xiàn)onDraw()方法,實現(xiàn)自己繪制組件探橱,如翻頁效果組件
版本更新的實現(xiàn)思路
答:在服務(wù)器相應(yīng)URL上有版本文件, 客戶端同時存儲該應(yīng)用當(dāng)前版本號 (SharedPreferences/Sqlite), 每次打開應(yīng)用,去檢測服務(wù)器版本號與本地版本號是否一致,如果不一 致,則自定義對話框提示是否下載更新
實現(xiàn)一個自定義view的基本流程
1申屹、自定義View的屬性 編寫attr.xml文件
2、在layout布局文件中引用隧膏,同時引用命名空間
3哗讥、在View的構(gòu)造方法中獲得我們自定義的屬性 ,在自定義控件中進(jìn)行讀人街病(構(gòu)造方法拿到attr.xml文件值)
4、重寫onMesure
5车酣、重寫onDraw
View的整個繪制流程可以分為以下三個階段:
measure: 判斷是否需要重新計算View的大小曲稼,需要的話則計算;
layout: 判斷是否需要重新計算View的位置湖员,需要的話則計算贫悄;
draw: 判斷是否需要重新繪制View,需要的話則重繪制娘摔。
這三個子階段可以用下圖來描述:
OnMeasure理解
首先會對父容器的MeasureSpec進(jìn)行測量得出specMode和specSize(尺寸大小)窄坦,然后對specMode進(jìn)行判斷是哪種類型,在對子元素的LayoutParams進(jìn)行判斷凳寺,最后來確定子元素的MeasureSpce鸭津,MeasureSpec由resultSize和resultMode組成,resultSize是View尺寸大小肠缨,resultMode是View類型逆趋。
specMode的類型有三種,每一種都有特殊含義:
1晒奕、EXACTLY
它對應(yīng)于LayoutParams中的match_parent和具體的數(shù)值這兩種模式
2闻书、AT_MOST
父容器指定了一個可用大小即SpecSize,View的大小不能超過這個值脑慧,它對應(yīng)于LayoutParams中的wrap_content魄眉。
- UNSPECIFIED
表示開發(fā)人員可以將視圖按照自己的意愿設(shè)置成任意的大小,沒有任何限制闷袒。這種情況比較少見坑律,不太會用到。
NDK開發(fā)流程囊骤?(JNI運行原理)
答: NDK應(yīng)用的開發(fā)流程(在應(yīng)用中定義本地接口(native), 編譯成.h頭文件,交由C程序員實現(xiàn),將.c實現(xiàn)通過NDK編譯成.so動態(tài)鏈接庫,導(dǎo)入項目中l(wèi)ibs/armeabi,代碼中調(diào)用該本地接口)
應(yīng)用場景: 音頻,視頻解碼,拍攝車牌號,識別車牌號
如何實現(xiàn)一鍵退出脾歇?
定義一個類繼承Application蒋腮,定義一個集合存放所有的activity,
定義一個添加的方法藕各,再寫一個退出的方法池摧,使用for循環(huán)全部調(diào)用finish方法,然
后在每個Activity的onCreate方法中調(diào)用自定義類里的添加方法激况,然后在需要使用一
鍵退出的地方調(diào)用類中的退出方法即可作彤。
android客戶端如何實現(xiàn)自動登錄
答: 通過SharedPreferences存儲用戶名,密碼,當(dāng)存儲不為空時實現(xiàn)自動登錄功能
ArrayList和LinkedList的大致區(qū)別:
1.ArrayList是實現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)乌逐。 (LinkedList是雙向鏈表竭讳,有next也有previous)
2.對于隨機(jī)訪問get和set,ArrayList覺得優(yōu)于LinkedList浙踢,因為LinkedList要移動指針绢慢。
3.對于新增和刪除操作add和remove,LinedList比較占優(yōu)勢洛波,因為ArrayList要移動數(shù)據(jù)胰舆。
HandlerThread 的原理和使用場景;
HandlerThread源碼實現(xiàn)還是挺清楚的蹬挤,首先我們看一下它的run()方法缚窿,可以發(fā)現(xiàn)該方法中調(diào)用Looper.myLooper()創(chuàng)建了一個Looper對象mLooper,并把該對象放到線程變量sThreadLocal中焰扳,然后通過調(diào)用Looper.loop()開啟消息循環(huán)倦零,Looper.loop()方法會不斷循環(huán)從MessageQueue中取出消息處理消息,沒有消息是則會阻塞吨悍。
HandlerThread有什么作用呢扫茅?能干什么?
比如說我們現(xiàn)在有個需求必須要Handler創(chuàng)建在子線程進(jìn)行工作
我們需要手動創(chuàng)建子線程然后在子線程中創(chuàng)建Looper一些操作:
new Thread(new Runnable() {
@Override
public void run() {
// 在當(dāng)前線程創(chuàng)建Looper對象
Looper.prepare();
// 創(chuàng)建Handler對象傳入當(dāng)前線程的Looper
Handler handler = new Handler(Looper.myLooper());
// 開始循環(huán)消息隊列
Looper.loop();
}
}).start();
然而谷歌提供的HandlerThread類可以簡化如上代碼
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
就是這么簡單,Handler就創(chuàng)建并工作在線程了
Android Studio 3.0 中 Gradle 的 api 和 implementation 有什么區(qū)別育瓜;
api:和 compile 的作用一樣诞帐,當(dāng)前 module 會暴露其依賴的其他 module 內(nèi)容。
implementation:只在內(nèi)部使用了該 module爆雹,不會向外部暴露其依賴的 module 內(nèi)容停蕉。
EventBus原理
總結(jié)一下:register會把當(dāng)前類中匹配的方法,存入一個map,而post會根據(jù)實參去map查找進(jìn)行反射調(diào)用
Android的四大組件是什么?它們的作用是什么钙态?
Android有四大組件:Activity慧起、Service、Broadcast Receiver册倒、Content Provider蚓挤。
Activity :應(yīng)用程序中,一個Activity通常就是一個單獨的屏幕,它上面可以顯示一些控件也可以監(jiān)聽并處理用戶的事件做出響應(yīng)灿意。Activity之間通過Intent進(jìn)行通信估灿。
Service 服務(wù):一個Service 是一段長生命周期的,沒有用戶界面的程序缤剧,可以用來開發(fā)如監(jiān)控類程序馅袁。
BroadcastReceive廣播接收器:你的應(yīng)用可以使用它對外部事件進(jìn)行過濾只對感興趣的外部事件(如當(dāng)電話呼入時,或者數(shù)據(jù)網(wǎng)絡(luò)可用時)進(jìn)行接收并做出響應(yīng)荒辕。廣播接收器沒有用戶界面汗销。然而,它們可以啟動一個activity或serice 來響應(yīng)它們收到的信息抵窒。
Content Provider內(nèi)容提供者 :主要用于多個應(yīng)用間數(shù)據(jù)共享弛针。這些數(shù)據(jù)可以存儲在文件系統(tǒng)中或SQLite數(shù)據(jù)庫。
二叉樹的遍歷:
一般來說李皇,二叉樹常用的遍歷方式有:前序遍歷削茁、中序遍歷、后序遍歷掉房、層序遍歷 四種遍歷方式茧跋,不同的遍歷算法,其思想略有不同圃阳,我們來看一下這四種遍歷方法主要的算法思想:
1厌衔、先序遍歷二叉樹順序:根節(jié)點 –> 左子樹 –> 右子樹璧帝,即先訪問根節(jié)點捍岳,然后是左子樹,最后是右子樹杨刨。
上圖中二叉樹的前序遍歷結(jié)果為:0 -> 1 -> 3 -> 4 -> 2 -> 5 -> 6
2挖滤、中序遍歷二叉樹順序:左子樹 –> 根節(jié)點 –> 右子樹是嗜,即先訪問左子樹,然后是根節(jié)點银萍,最后是右子樹。
上圖中二叉樹的中序遍歷結(jié)果為:3 -> 1 -> 4 -> 0 -> 5 -> 2 -> 6
3恤左、后續(xù)遍歷二叉樹順序:左子樹 –> 右子樹 –> 根節(jié)點贴唇,即先訪問左子樹,然后是右子樹飞袋,最后是根節(jié)點戳气。
上圖中二叉樹的后序遍歷結(jié)果為:3 -> 4 -> 1 -> 5 -> 6 -> 2 -> 0
4、層序遍歷二叉樹順序:從最頂層的節(jié)點開始巧鸭,從左往右依次遍歷瓶您,之后轉(zhuǎn)到第二層,繼續(xù)從左往右遍歷,持續(xù)循環(huán)呀袱,直到所有節(jié)點都遍歷完成
上圖中二叉樹的層序遍歷結(jié)果為:0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6
Android--判斷App處于前臺還是后臺的方案
判斷App處于前臺還是后臺的方案
通過runningProcess獲取到一個當(dāng)前正在運行的進(jìn)程的List贸毕,我們遍歷這個List中的每一個進(jìn)程,判斷這個進(jìn)程的一個importance 屬性是否是前臺進(jìn)程夜赵,并且包名是否與我們判斷的APP的包名一樣明棍,如果這兩個條件都符合,那么這個App就處于前臺油吭。
Intent的原理击蹲,作用,可以傳遞哪些類型的參數(shù)婉宰?
答:intent是連接Activity, Service, BroadcastReceiver, ContentProvider四大組件的信使,歌豺,可以傳遞八種基本數(shù)據(jù)類型以及string, Bundle類型,以及實現(xiàn)了Serializable或者Parcelable的類型心包。
Intent可以劃分成顯式意圖和隱式意圖类咧。
顯式意圖:調(diào)用Intent.setComponent()或Intent.setClass()方法明確指定了組件名的Intent為顯式意圖,顯式意圖明確指定了Intent應(yīng)該傳遞給哪個組件蟹腾。
隱式意圖:沒有明確指定組件名的Intent為隱式意圖痕惋。 Android系統(tǒng)會根據(jù)隱式意圖中設(shè)置的動作(action)、類別(category)娃殖、數(shù)據(jù)(URI和數(shù)據(jù)類型)找到最合適的組件來處理這個意圖值戳。
如何實現(xiàn)屏幕分辨率的自適應(yīng)?
答: 最好可以通過權(quán)重(layout_weight)的方式來分配每個組件的大小炉爆,也可以通過具體的像素(dip)來確定大小堕虹。
盡量使用Relativelayout 。
已知應(yīng)用支持平臺設(shè)備的分辨率,可以提供多個layout_320480 ...
drawable-hdpi,drawable-mdpi,drawable-ldpi分別代表分辨率為480800,360480,240360, 放置圖片大小相差1.5倍
最后還需要在AndroidManifest.xml里添加下面一段芬首,沒有這一段自適應(yīng)就不能實現(xiàn):
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:anyDensity = "true"/>
在</application>標(biāo)簽和</manifest> 標(biāo)簽之間添加上面那段代碼赴捞。即可。
備注:三者的解析度不一樣郁稍,就像你把電腦的分辨率調(diào)低赦政,圖片會變大一樣,反之分辨率高耀怜,圖片縮小
還可以通過.9.png實現(xiàn)圖片的自適應(yīng)
簡述Android中的IPC機(jī)制
IPC(Inter-Process Communication恢着,進(jìn)程間通信),aidl是 Android Interface definition language的縮寫,它是一種android內(nèi)部進(jìn)程通信接口的描述語言财破,通過它我們可以定義進(jìn)程間的通信接口.編譯器可以通過擴(kuò)展名為aidl的文件生成一段代碼掰派,通過預(yù)先定義的接口達(dá)到兩個進(jìn)程內(nèi)部通信進(jìn)程的目的.
BroadcastReceiver也可以實現(xiàn)進(jìn)程間通信
ContentProvider 提供進(jìn)程間數(shù)據(jù)共享
MVP MVVM的調(diào)用關(guān)系
MVP(Passive View)的依賴關(guān)系
1、View不再負(fù)責(zé)同步的邏輯狈究,而是由Presenter負(fù)責(zé)碗淌。Presenter中既有業(yè)務(wù)邏輯也有同步邏輯盏求。
2、View需要提供操作界面的接口給Presenter進(jìn)行調(diào)用亿眠。Presenter獲取到Model變更的消息以后碎罚,通過View提供的接口更新界面。
MVVM
ViewModel是View與Model的連接器纳像,持有可被觀察的數(shù)據(jù)持有者和網(wǎng)絡(luò)請求操作荆烈,數(shù)據(jù)變更實時渲染UI。
MVVM可以看作是一種特殊的MVP(Passive View)模式竟趾,或者說是對MVP模式的一種改良
MVVM的依賴關(guān)系和MVP依賴憔购,只不過是把P換成了VM。
相對規(guī)范的mvvm應(yīng)該這樣寫
1.mvvm和MVP比較大的區(qū)別是:vm和v是單向引用岔帽, 只有activity持有vm引用玫鸟,vm是不持有view的引用的,所以vm的構(gòu)造方法中不能傳入視圖相關(guān)的對象犀勒。之所以要這樣屎飘,是為了防止生命周期問題導(dǎo)致的內(nèi)存泄漏。
2.數(shù)據(jù)驅(qū)動贾费。在常規(guī)的開發(fā)模式中钦购,數(shù)據(jù)變化需要更新UI的時候,需要先獲取UI控件的引用褂萧,然后再更新UI押桃。 獲取用戶的輸入和操作也需要通過UI控件的引用。在MVVM中导犹,這些都是通過數(shù)據(jù)驅(qū)動來自動完成的唱凯, 數(shù)據(jù)變化后會自動更新UI,UI的改變也能自動反饋到數(shù)據(jù)層锡足,數(shù)據(jù)成為主導(dǎo)因素波丰。這樣MVVM層在業(yè)務(wù)邏輯處理中只要關(guān)心數(shù)據(jù)壳坪,不需要直接和UI打交道舶得,在業(yè)務(wù)處理過程中簡單方便很多。
3.mvvm解決了mvp中接口繁雜爽蝴、內(nèi)存泄漏等疑難雜癥沐批。
4 結(jié)合jetpack相關(guān)組件,mvvm效果會很好蝎亚。
橫豎屏切換時候Activity的生命周期九孩?
(1)設(shè)置 android:configChanges="orientation" 和不設(shè)置這個屬性,生命周期表現(xiàn)為重新創(chuàng)建activity
(2)設(shè)置 android:configChanges="orientation|keyboardHidden"发框,在2.3上表現(xiàn)為不重新創(chuàng)建activity躺彬,4.0如下
a)android:targetSdkVersion<="12",生命周期表現(xiàn)為不重新創(chuàng)建activity
b)android:targetSdkVersion>"12",表現(xiàn)為重新創(chuàng)建activity
(3)設(shè)置 android:configChanges="orientation|keyboardHidden|screenSize"宪拥,在2.3和4.0上都表現(xiàn)為不重新創(chuàng)建
ScrollView 與 recyclerView仿野、WebView的滑動沖突
用ScrollView 嵌套recyclerView或者WebView沖突時、可以在recyclerView或者WebView外面嵌套RelativeLayout
對于Android調(diào)用JS代碼的方法有2種:
通過WebView的loadUrl()
通過WebView的evaluateJavascript()
對于JS調(diào)用Android代碼的方法有3種:
通過WebView的addJavascriptInterface()進(jìn)行對象映射
通過 WebViewClient 的shouldOverrideUrlLoading ()方法回調(diào)攔截 url
通過 WebChromeClient 的onJsAlert()她君、onJsConfirm()脚作、onJsPrompt()方法回調(diào)攔截JS對話框alert()、confirm()缔刹、prompt() 消息
WebView中球涛,主要漏洞有三類:
任意代碼執(zhí)行漏洞
漏洞產(chǎn)生原因
JS調(diào)用Android的其中一個方式是通過addJavascriptInterface接口進(jìn)行對象映射:
webView.addJavascriptInterface(new JSObject(), "myObj");
// 參數(shù)1:Android的本地對象
// 參數(shù)2:JS的對象
// 通過對象映射將Android中的本地對象和JS中的對象進(jìn)行關(guān)聯(lián),從而實現(xiàn)JS調(diào)用Android的對象和方法
所以校镐,漏洞產(chǎn)生原因是:當(dāng)JS拿到Android這個對象后亿扁,就可以調(diào)用這個Android對象中所有的方法,包括系統(tǒng)類(java.lang.Runtime 類)鸟廓,從而進(jìn)行任意代碼執(zhí)行魏烫。
解決方案
Google 在Android 4.2 版本中規(guī)定對被調(diào)用的函數(shù)以 @JavascriptInterface進(jìn)行注解從而避免漏洞攻擊
密碼明文存儲漏洞:
WebView默認(rèn)開啟密碼保存功能 :
mWebView.setSavePassword(true)`
開啟后,在用戶輸入密碼時肝箱,會彈出提示框:詢問用戶是否保存密碼哄褒;
如果選擇”是”,密碼會被明文保到 /data/data/com.package.name/databases/webview.db 中煌张,這樣就有被盜取密碼的危險
解決方案
關(guān)閉密碼保存提醒
域控制不嚴(yán)格漏洞
可以在Application里面啟動Activity嗎呐赡?
在Application中通過以上方式跳轉(zhuǎn)到Activity的話,會出現(xiàn)異常:原因是原有的任務(wù)棧已經(jīng)銷毀骏融,因此要判斷啟動的activity是不是被銷毀了链嘀。
解決方法:為activity開啟新的棧,Intent.FLAG_ACTIVITY_NEW_TASK 設(shè)置狀態(tài)档玻,首先查找是否存在和被啟動的Activity具有相同的任務(wù)棧怀泊,如果有則直接把這個棧整體移到前臺,并保持棧中的狀態(tài)不變误趴,既棧中的activity順序不變霹琼,如果沒有,則新建一個棧來存放被啟動的Activity凉当。
Activity的啟動模式枣申。
在多Activity開發(fā)中,有可能是自己應(yīng)用之間的Activity跳轉(zhuǎn)看杭,或者夾帶其他應(yīng)用的可復(fù)用Activity忠藤。可能會希望跳轉(zhuǎn)到原來某個Activity實例楼雹,而不是產(chǎn)生大量重復(fù)的Activity模孩。這需要為Activity配置特定的加載模式尖阔,而不是使加載模式。
在android里榨咐,有4種activity的啟動模式诺祸,分別為:
standard: 標(biāo)準(zhǔn)模式,也是默認(rèn)模式祭芦,一調(diào)用startActivity()方法就會產(chǎn)生一個新的實例筷笨。
singleTop: 如果已經(jīng)有一個實例位于Activity棧的頂部時,就不產(chǎn)生新的實例龟劲,而只是調(diào)用Activity中的newInstance()方法胃夏。如果不位于棧頂,會產(chǎn)生一個新的實例昌跌。
singleTask: 單一任務(wù)仰禀。意思就是說當(dāng)前的activity只有一個實例,無論在任何地方startActivity出來這個activity蚕愤,它都只存在一個實例答恶。并且,它會將在他之上的所有activity都銷毀萍诱。通常這個activity都是用來作為MainActivity悬嗓。
singleInstance: 它具備所有singleTask的特點,唯一不同的是裕坊,它是存在于另一個任務(wù)棧中包竹。上面的三種模式都存在于同一個任務(wù)棧中,而這種模式則是存在于另一個任務(wù)棧中籍凝。
RxJava的鏈?zhǔn)秸{(diào)用過程周瞎?map操作符和flatMap操作符的區(qū)別?
map適用于一對一轉(zhuǎn)換饵蒂,當(dāng)然也可以配合flatmap進(jìn)行適用
flatmap適用于一對多声诸,多對多的場景
獲取控件寬和高的方法。
觀察者模式
觀察View的繪制流程退盯,設(shè)置OnGlobalLayoutListener監(jiān)聽彼乌,布局完成時會調(diào)用onGlobalLayout(),在onGlobalLayout()方法里面獲取空間的寬和高手動測量(自己調(diào)用measure()方法)
int measuredWidth = mTextView.getMeasuredWidth();
int measuredHeight = mTextView.getMeasuredHeight();View.post(Runnable action)
View.post()中的run方法和onWindowFocusChanged方法幾乎是同時執(zhí)行得问,都是在onLayout之后囤攀,所以都是可以得到控件的寬高的H砻狻9场!
Android中你認(rèn)為哪種動畫最為強(qiáng)大膏萧?簡述其實現(xiàn)原理漓骚。
通過不斷控制 值 的變化蝌衔,再不斷 自動 賦給對象的屬性,從而實現(xiàn)動畫效果
屬性動畫蝌蹂,基于反射噩斟。它的內(nèi)部使用一種時間循環(huán)的機(jī)制來計算值與值之間的動畫過渡, 通過插值器和估值器計算屬性的變化百分比和值孤个。
Multidex了解嗎剃允?它是用來解決什么問題的?一個工程有10W個方法齐鲤,分幾個dex文件斥废?每個dex文件的方法數(shù)是多少?
Multidex用來解決單個dex文件方法數(shù)65535上限導(dǎo)致打包不成功的問題给郊。一個10w方法的app打包應(yīng)該有兩個dex文件牡肉。其中一個方法數(shù)達(dá)到上限,另一個為100000-65535=34465淆九。
bundle的數(shù)據(jù)結(jié)構(gòu)统锤,如何存儲,既然有了Intent.putExtra炭庙,為啥還要用bundle饲窿。
bundle的內(nèi)部結(jié)構(gòu)其實是Map,傳遞的數(shù)據(jù)可以是boolean焕蹄、byte免绿、int、long擦盾、float嘲驾、double、string等基本類型或它們對應(yīng)的數(shù)組迹卢,也可以是對象或?qū)ο髷?shù)組辽故。當(dāng)Bundle傳遞的是對象或?qū)ο髷?shù)組時,必須實現(xiàn)Serializable 或Parcelable接口腐碱。
如何繪制大于父view的子view
1.clipChild用來定義他的子控件是否要在他應(yīng)有的邊界內(nèi)進(jìn)行繪制誊垢。 默認(rèn)情況下,clipChild被設(shè)置為true症见。 也就是不允許進(jìn)行擴(kuò)展繪制喂走。
- clipToPadding用來定義ViewGroup是否允許在padding中繪制。默認(rèn)情況下谋作,cliptopadding被設(shè)置為ture芋肠, 也就是把padding中的值都進(jìn)行裁切了。
多點觸控如何傳遞
在看 onDisptchTouchEvent 的時候遵蚜,發(fā)現(xiàn)他是用了一個 mFirstTouchTarget 成員變量 來記住當(dāng)前是否為第一個觸控點帖池,然后下個觸摸點下來的時候 會檢查 mFirstTouchTarget 是不是已經(jīng)存在奈惑,如果已經(jīng)存在 那么他就會調(diào)用 dispatchTransformedTouchEvent(ev, canceled, null,TouchTarget.ALL_POINTER_IDS); 來分發(fā)這次觸摸事件,有趣的是dispatchTransformedTouchEvent 睡汹,他會根據(jù) 傳進(jìn)的第三個參數(shù) child進(jìn)行判斷是否為null肴甸,如果為空那么說明他已經(jīng)沒有子view了。他就會直接調(diào)用 super.dispatchTouchEvent 來讓他的父類方法囚巴,即View.dispatchTouchEvent 來判斷是否 需要攔截原在,或者處理。出現(xiàn)這種情況的話 就會最終調(diào)用 這個viewgroup的ontouch事件彤叉,或者是onTouchListenner
AsyncTask機(jī)制
AsyncTask晤斩,異步任務(wù),也就是說在UI線程運行的時候姆坚,可以在后臺的執(zhí)行一些異步的操作澳泵;AsyncTask可以很容易且正確地使用UI線程,AsyncTask允許進(jìn)行后臺操作兼呵,并在不顯示使用工作線程或Handler機(jī)制的情況下兔辅,將結(jié)果反饋給UI線程。但是AsyncTask只能用于短時間的操作(最多幾秒就應(yīng)該結(jié)束的操作)击喂,如果需要長時間運行在后臺维苔,就不適合使用AsyncTask了,只能去使用Java提供的其他API來實現(xiàn)懂昂。
Android 線程間通信有哪幾種方式
共享變量(內(nèi)存)
AsyncTask
handle機(jī)制
runOnUiThread(Runnable)
view.post(Runnable)
JAVA中線程同步的方法(7種)匯總
介时、同步方法
即有synchronized關(guān)鍵字修飾的方法。 由于java的每個對象都有一個內(nèi)置鎖凌彬,當(dāng)用此關(guān)鍵字修飾方法時沸柔, 內(nèi)置鎖會保護(hù)整個方法。在調(diào)用該方法前铲敛,需要獲得內(nèi)置鎖褐澎,否則就處于阻塞狀態(tài)。同步代碼塊
即有synchronized關(guān)鍵字修飾的語句塊伐蒋。 被該關(guān)鍵字修飾的語句塊會自動被加上內(nèi)置鎖工三,從而實現(xiàn)同步wait與notify
wait():使一個線程處于等待狀態(tài),并且釋放所持有的對象的lock先鱼。sleep():使一個正在運行的線程處于睡眠狀態(tài)俭正,是一個靜態(tài)方法,調(diào)用此方法要捕捉InterruptedException異常焙畔。
notify():喚醒一個處于等待狀態(tài)的線程掸读,注意的是在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程寺枉,而且不是按優(yōu)先級抑淫。
notifyAll():喚醒所有處入等待狀態(tài)的線程绷落,注意并不是給所有喚醒線程一個對象的鎖姥闪,而是讓它們競爭
四、使用特殊域變量(volatile)實現(xiàn)線程同步
可見性砌烁。對一個volatile變量的讀筐喳,總是能看到(任意線程)對這個volatile變量最后的寫入。
原子性:對任意單個volatile變量的讀/寫具有原子性函喉,但類似于volatile++這種復(fù)合操作不具有原子性避归。
Throwable、Exception管呵、Error三者的關(guān)系梳毙,Exception和Error有什么區(qū)別,Error可以被捕獲嘛
Throwable是java.lang包中一個專門用來處理異常的類捐下。它有兩個子類账锹,即Error 和Exception,它們分別用來處理兩組異常坷襟。
奸柬、Throwable類是整個異常體系類的“父級類”,當(dāng)然最終追根溯源到底的父類當(dāng)然要歸于Object類婴程。
一般Exception是程序在編譯期間產(chǎn)生的異常廓奕,程序員必須通過try-catch進(jìn)行捕獲異常,因此也叫檢查型異常档叔。example:IOException桌粉。。衙四。
Error指jvm導(dǎo)致的內(nèi)部錯誤番甩,類似系統(tǒng)崩潰等。
哪些方面取優(yōu)化網(wǎng)絡(luò)連接
第一節(jié)說到了網(wǎng)絡(luò)請求對App和用戶的影響, 那么我們怎么從哪些方面去優(yōu)化網(wǎng)絡(luò)進(jìn)而減少甚至消滅這些影響呢?
簡單來說, 兩個方面:
減少Radio活躍時間
也就是減少網(wǎng)絡(luò)數(shù)據(jù)獲取的頻次.
這就減少了radio的電量消耗, 控制電量使用.
減少獲取數(shù)據(jù)包的大小
可以減少流量消耗
也可以讓每次請求更快, 在網(wǎng)絡(luò)情況不好的情況下也有良好表現(xiàn), 提升用戶體驗.
引用
(一).強(qiáng)引用(StrongReference)
垃圾回收機(jī)制不會回收強(qiáng)引用所指向的內(nèi)存届搁,就算系統(tǒng)內(nèi)存不足報出內(nèi)存溢出(OOM)異常缘薛,導(dǎo)致系統(tǒng)崩潰
垃圾回收機(jī)制也不會去回收強(qiáng)引用的內(nèi)容來解決內(nèi)存不足的問題.
//強(qiáng)引用,也就是一般引用,使用new關(guān)鍵詞新建出來的引用關(guān)系
ImageView imageview = new ImageView();
(二).軟引用(SoftReference)
如果一個對象只具有軟引用卡睦,則內(nèi)存空間足夠宴胧,垃圾回收器就不會回收它;
如果內(nèi)存空間不足了表锻,就會回收這些對象的內(nèi)存恕齐。只要垃圾回收器沒有回收它,該對象就可以被程序使用瞬逊。
軟引用可用來實現(xiàn)內(nèi)存敏感的高速緩存
(三).弱引用(WeakReference)
弱引用與軟引用的區(qū)別在于:弱引用的對象擁有更短暫的生命周期显歧。
在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中仪或,一旦發(fā)現(xiàn)了只具有弱引用的對象,
不管當(dāng)前內(nèi)存空間足夠與否士骤,都會回收它的內(nèi)存范删。不過,由于垃圾回收器是一個優(yōu)先級很低的線程拷肌,
因此不一定會很快發(fā)現(xiàn)那些只具有弱引用的對象到旦。
(四).虛引用(PhantomReference)
“虛引用”顧名思義,就是形同虛設(shè)巨缘,與其他幾種引用都不同添忘,虛引用并不會決定對象的生命周期。
如果一個對象僅持有虛引用若锁,那么它就和沒有任何引用一樣搁骑,在任何時候都可能被垃圾回收器回收。
三級緩存原理
真如下圖所示又固,
1.首先我們從內(nèi)存中獲取bitmap仲器,
2.1.如果獲取的bitmap != null,直接加載到ImageVIew
2.2.如果獲取的bitmap==null,那么將繼續(xù)從硬盤獲取bitmap
3.1如果從硬盤獲取的bitmap !=null,加載到ImageView.同時將bitmap緩存到內(nèi)存緩存中
3.2如果從硬盤獲取的bitmap == null,繼續(xù)從網(wǎng)絡(luò)獲取
4.1從網(wǎng)絡(luò)獲取到圖片口予,然后
4.2.加載到ImageVIew,緩存到硬盤娄周,緩存到內(nèi)存
進(jìn)階基礎(chǔ)題
Service詳解
關(guān)于AIDL使用和Binder機(jī)制詳解
app啟動流程
app啟動流程-2
學(xué)習(xí)AIDL上
學(xué)習(xí)AIDL下
AIDL Demo
Android View的繪制流程
android launchMode理解以及應(yīng)用場景
Android:聊聊我所理解的MVP
MVP應(yīng)用
三級緩存 緩存原理
webView與js交互 webview優(yōu)化
Service與Activity之間通信的幾種方式
Java四種引用解析以及在Android的應(yīng)用
內(nèi)存監(jiān)控,內(nèi)存泄露問題 內(nèi)存泄露檢測有什么好方法沪停,
描述常見的幾種內(nèi)存泄漏
App優(yōu)化之提升你的App啟動速度 優(yōu)化啟動速度
如何對 Android 應(yīng)用進(jìn)行性能加快應(yīng)用啟動速度
Touch事件分發(fā)機(jī)制
Android跨進(jìn)程通訊的方式
Android 進(jìn)程泵罕妫活
非主線程中能不能直接new Handler()
Android 異步消息處理機(jī)制 讓你深入理解 Looper、Handler木张、Message三者關(guān)系
JAVA中線程同步的方法
Android 中實現(xiàn)多線程編程原理
EventBus原理