什么情況下會(huì)導(dǎo)致內(nèi)存泄露
如何對(duì)Android 應(yīng)用進(jìn)行性能分析以及優(yōu)化;
說(shuō)一款你認(rèn)為當(dāng)前比較火的應(yīng)用并設(shè)計(jì)(直播APP);
OOM的避免異常及解決方法;
1.什么是ANR 如何避免它?
Android App優(yōu)化之ANR詳解
ANR 應(yīng)用程序無(wú)響應(yīng) 根本原因不要在主線程(UI線程做繁重的工作)
使用主線程的地方
1.Activity的所有生命周期回調(diào)都是執(zhí)行在主線城的
2.Service默認(rèn)是執(zhí)行在主線城的
3.BroadCastReceiver的onReceive回調(diào)是在主線程的
4.沒(méi)有使用子線程的looper的Handler的handlerMessage,post(Runnable) 是在主線城的
5.AsyncTask的回調(diào)中除了doInBackground()方法,其他回調(diào)都是在主線城的
6.View的post(Runnable)是執(zhí)行在主線城的
使用子線程的地方
1.使用Thread 方式
1)繼承Thread 2)實(shí)現(xiàn)Runnable接口
2.使用AsyncTask方式
3.使用HandlerThread方式
Android中結(jié)合Handler和Thread的一種方式. 默認(rèn)情況下Handler的handleMessage是執(zhí)行在主線程的, 但是如果我給這個(gè)Handler傳入了子線程的looper, handleMessage就會(huì)執(zhí)行在這個(gè)子線程中的. HandlerThread正是這樣的一個(gè)結(jié)合體:
// 啟動(dòng)一個(gè)名為new_thread的子線程
HandlerThread thread = new HandlerThread("new_thread");
thread.start();
// 取new_thread賦值給ServiceHandler
private ServiceHandler mServiceHandler;
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// 此時(shí)handleMessage是運(yùn)行在new_thread這個(gè)子線程中了.
}
}
4.IntentService
Service是運(yùn)行在主線程的, 然而IntentService是運(yùn)行在子線程的.
實(shí)際上IntentService就是實(shí)現(xiàn)了一個(gè)HandlerThread + ServiceHandler的模式.
以上HandlerThread的使用代碼示例也就來(lái)自于IntentService源碼
5.Loader
Android 3.0引入的數(shù)據(jù)加載器, 可以在Activity/Fragment中使用. 支持異步加載數(shù)據(jù), 并可監(jiān)控?cái)?shù)據(jù)源在數(shù)據(jù)發(fā)生變化時(shí)傳遞新結(jié)果. 常用的有CursorLoader, 用來(lái)加載數(shù)據(jù)庫(kù)數(shù)據(jù).
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
// 使用LoaderManager來(lái)初始化Loader
getLoaderManager().initLoader(0, null, this);
//如果 ID 指定的加載器已存在,則將重復(fù)使用上次創(chuàng)建的加載器。
//如果 ID 指定的加載器不存在,則 initLoader() 將觸發(fā) LoaderManager.LoaderCallbacks 方法 //onCreateLoader()。在此方法中,您可以實(shí)現(xiàn)代碼以實(shí)例化并返回新加載器
// 創(chuàng)建一個(gè)Loader
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
// First, pick the base URI to use depending on whether we are
// currently filtering.
Uri baseUri;
if (mCurFilter != null) {
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
Uri.encode(mCurFilter));
} else {
baseUri = Contacts.CONTENT_URI;
}
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ Contacts.DISPLAY_NAME + " != '' ))";
return new CursorLoader(getActivity(), baseUri,
CONTACTS_SUMMARY_PROJECTION, select, null,
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}
// 加載完成
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
}
View的繪制流程
View的繪制是從ViewRoot的performTraversals()方法開(kāi)始的,經(jīng)過(guò)measure,layout,draw這個(gè)3大步驟。
measure的過(guò)程:
measure過(guò)程是對(duì)整個(gè)view樹(shù)的所有控件計(jì)算寬高
measure是沖ViewRoot類中的host.measure開(kāi)始的,內(nèi)部調(diào)用的是View的measure(int widthMeasureSpec,int heightMeasureSpec)方法,measure方法里面調(diào)用了onMeasure(int widthMeasureSpec,int heightMeasureSpec)方法,方法中的兩個(gè)參數(shù)都是是MeasureSpec類型(指父控件對(duì)子控件寬高的期望值,它是一個(gè)32位的int類型數(shù),前兩位表示測(cè)量模式,后30位表示測(cè)量大?。?br>
測(cè)量模式一共有3種:
1)EXACTLY 精確測(cè)量模式,xml文件中寫(xiě)200dp,march_parent等代表使用該模式,
2)AT_MOST 最大模式,xml文件中寫(xiě)wrap_content表示使用該模式。
3)UNSPECIFIED 無(wú)限大測(cè)量模式,只有在繪制特定自定義View時(shí)才用的到這個(gè)模式。
真正代表測(cè)量結(jié)束的方法是setMeasuredDimension方法,該方法傳入的兩個(gè)參數(shù)是寬高的SpecSize。測(cè)量結(jié)束后我們可以通過(guò)getMeasureHeight和getMeasureWidth來(lái)獲取測(cè)量寬高。
自定義ViewGroup一定要重寫(xiě)onMeasure方法,用于測(cè)量子View的寬高,不重寫(xiě)的話子View沒(méi)有寬高。
自定義View如果在xml中使用了wrap_content屬性,就需要重寫(xiě)onMeasure方法來(lái)設(shè)置wrap_content的默認(rèn)大小,不然會(huì)顯示出match_parent的效果。
layout的過(guò)程:
ViewGroup用來(lái)將子View放在合適的位置上。
layout是從ViewRoot類中的host.layout開(kāi)始的,內(nèi)部調(diào)用的是ViewGroup的layout方法。在ViewGroup的layout方法中,先調(diào)用setFrame來(lái)確定自己的左上右下的位置,再調(diào)用onLayout來(lái)確定子View的位置。
自定義ViewGroup一定要重寫(xiě)layout方法來(lái)確定子View的位置,自定義View一般不需要重寫(xiě)該方法,它的位置是右父控件確定的。
draw過(guò)程:
此過(guò)程是真正將內(nèi)容展示在屏幕上讓我們能夠看到的過(guò)程。
draw是從ViewRoot類中的host.draw開(kāi)始的,內(nèi)部調(diào)用的是View的draw方法。
draw的步驟:
1)繪制背景。
2)繪制內(nèi)容,也就是調(diào)用onDraw方法。
3)繪制子View,調(diào)用的是dispatchDraw方法。
4)繪制裝飾,如listview的滾動(dòng)條等。
對(duì)于View的繪制過(guò)程,既可以說(shuō)是簡(jiǎn)單的,也可以說(shuō)是復(fù)雜的,簡(jiǎn)單的在于Google已經(jīng)幫我們將draw框架寫(xiě)好了,我們?cè)谧远xViewGroup時(shí)不用管draw過(guò)程,只需要實(shí)現(xiàn)measure和layout過(guò)程。復(fù)雜在于,我們寫(xiě)繼承View的自定義控件的時(shí)候需要重寫(xiě)onDraw方法,這樣才能繪制出你自定義的View的內(nèi)容,onDraw(Canvas canvas)方法中最重要的兩個(gè)東西是Paint和Canvas,這個(gè)使用起來(lái)算是比較復(fù)雜的。
Android View的繪制流程
自定義View如何考慮機(jī)型適配
- 合理使用warp_content,match_parent.
- 盡可能的是使用RelativeLayout
- 針對(duì)不同的機(jī)型,使用不同的布局文件放在對(duì)應(yīng)的目錄下,android會(huì)自動(dòng)匹配。
- 盡量使用點(diǎn)9圖片。
- 使用與密度無(wú)關(guān)的像素單位dp,sp
- 引入android的百分比布局。
- 切圖的時(shí)候切大分辨率的圖,應(yīng)用到布局當(dāng)中。在小分辨率的手機(jī)上也會(huì)有很好的顯示效果。
自定義View的事件分發(fā)機(jī)制
安卓自定義View進(jìn)階-事件分發(fā)機(jī)制詳解
安卓自定義View進(jìn)階-事件分發(fā)機(jī)制原理
View和ViewGroup分別有哪些事件分發(fā)相關(guān)的回調(diào)方法

自定義View如何提供獲取View屬性的接口
Art和Dalvik對(duì)比
在程序運(yùn)行過(guò)程中Dalvik虛擬機(jī)不斷的進(jìn)行將字節(jié)碼轉(zhuǎn)換為機(jī)器碼的工作。
而Art引入了AOT這種預(yù)編譯技術(shù),在應(yīng)用程序的安裝過(guò)程中已經(jīng)將所有的字節(jié)碼編譯為了機(jī)器碼,在運(yùn)行的時(shí)候直接調(diào)用。Art極大的提高了程序的運(yùn)行效率,同時(shí)減少了手機(jī)的耗電量,在垃圾回收機(jī)制上也有很大的優(yōu)化,但是Art模式下應(yīng)用程序的安裝需要消耗更多的時(shí)間,同時(shí)也需要跟多的安裝空間。
Dalvik 是Android4.4及以下平臺(tái)的虛擬機(jī)。
Art 是在Android4.4以上平臺(tái)使用的虛擬機(jī)。
虛擬機(jī)原理,如何自己設(shè)計(jì)一個(gè)虛擬機(jī)(內(nèi)存管理,類加載,雙親委派);
JVM內(nèi)存模型及類加載機(jī)制
內(nèi)存對(duì)象的循環(huán)引用及避免
ddms 和 traceView的區(qū)別
1, ddms:是android開(kāi)發(fā)環(huán)境中的dalvik虛擬機(jī)調(diào)試監(jiān)控服務(wù);
ddms能夠提供,測(cè)試設(shè)備截屏,針對(duì)特定的進(jìn)程查看正在運(yùn)行的線程以及堆信息,Logcat,廣播狀態(tài)信息,模擬電話呼叫,接收sms,虛擬地理坐標(biāo)等。
2,traceView是android平臺(tái)配備的性能分析的工具;它可以通過(guò)圖形化讓我們了解要跟蹤的程序的性能,并且能具體到方法。
區(qū)別:ddms是一個(gè)程序執(zhí)行查看器,在里面可以看見(jiàn)線程和堆棧等信息,traceView是程序性能分析器。
內(nèi)存回收機(jī)制與GC算法(各種算法的優(yōu)缺點(diǎn)以及應(yīng)用場(chǎng)景)
gc是java的垃圾回收機(jī)制
引用計(jì)數(shù)法(Reference Counting Collector):使用計(jì)數(shù)器來(lái)區(qū)分存活對(duì)象和不再使用的對(duì)象。一般來(lái)說(shuō),堆中的每個(gè)對(duì)象對(duì)應(yīng)一個(gè)引用計(jì)數(shù)器。當(dāng)每一次創(chuàng)建一個(gè)對(duì)象并賦給一個(gè)變量時(shí),引用計(jì)數(shù)器置為1。當(dāng)對(duì)象被賦給任意變量時(shí),引用計(jì)數(shù)器每次加1當(dāng)對(duì)象出了作用域后(該對(duì)象丟棄不再使用),引用計(jì)數(shù)器減1,一旦引用計(jì)數(shù)器為0,對(duì)象就滿足了垃圾收集的條件。
標(biāo)記算法(Tracing Collector):使用了根集的概念,基于tracing算法的垃圾收集器從根集開(kāi)始掃描,識(shí)別出哪些對(duì)象可達(dá),哪些對(duì)象不可達(dá),并用某種方式標(biāo)記可達(dá)對(duì)象。
整理算法(Compacting Collecotr):該算法會(huì)將所有的對(duì)象移到堆的一端。能解決堆碎片的問(wèn)題。
復(fù)制算法:將內(nèi)存分為兩個(gè)區(qū)域(from space 和 to space)。所有的對(duì)象都分配到from space。清理時(shí)先將所有標(biāo)為活動(dòng)對(duì)象copy到to space,然后清除from space空間。然后互換from space和to apce的身份,每次清理都重復(fù)上述過(guò)程。
gc收集器:serial收集器:?jiǎn)尉€程,工作時(shí)必須暫停其他工作線程,多用于client機(jī)器上,使用復(fù)制算法。
ParNew收集器:serial的多線程版本,server模式下jvm首選的新生代收集器。復(fù)制算法。
Parallel Scavenge收集器:可控制吞吐量的收集器,吞吐量指有效運(yùn)行時(shí)間。復(fù)制算法。
Serial Old收集器:serial的老年代版本,使用整理算法。
Parallel Old收集器:Parallel Scavenge收集器的老版本,多線程,標(biāo)記整理。
CMS收集器:整理算法。最短回收停頓時(shí)間,缺點(diǎn)是產(chǎn)生碎片。
GI收集器:基本思想是化整為零,將堆分為多個(gè)Region,優(yōu)先回收價(jià)值最大的Region。并行并發(fā),分代收集,空間整合。整理算法。
GC原理時(shí)機(jī)以及GC對(duì)象
內(nèi)存泄露場(chǎng)景及解決方法
屏幕適配的處理技巧都有哪些
四大組件及生命周期
Activity
Service
Service 官方資料 需翻墻
Service 資料
ContentProvider
BroadcastReceiver
ContentProvider的權(quán)限管理(讀寫(xiě)分離,權(quán)限控制-精確到表級(jí),URL控制);
Activity的四種啟動(dòng)模式對(duì)比
Android 深入解析 Activity 的 launchMode 啟動(dòng)模式,Intent Flag,taskAffinity
Activity狀態(tài)保存于恢復(fù)
什么是AIDL 以及如何使用
AIDL:android interface definition language的縮寫(xiě)。
AIDL是用來(lái)實(shí)現(xiàn)進(jìn)程間通信的,可以幫我們實(shí)現(xiàn)發(fā)布以及調(diào)用遠(yuǎn)程服務(wù)。
使用:
1)服務(wù)端:創(chuàng)建一個(gè)Service用來(lái)監(jiān)聽(tīng)客戶端的連接請(qǐng)求,然后創(chuàng)建一個(gè)AIDL文件,將服務(wù)端暴露給客戶端的接口在這個(gè)文件中聲明,最后在Service中實(shí)現(xiàn)這個(gè)AIDL接口。
2)客戶端:首先綁定服務(wù)端的Service,綁定成功后將服務(wù)端返回的Binder對(duì)象轉(zhuǎn)成AIDL接口所屬的類型,接著就可以調(diào)用AIDL中的方法。
請(qǐng)解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關(guān)系
Android--異步消息處理機(jī)制(Handler、Looper、Message、MessageQueue)
Fragment生命周期
onAttach(),onCreate(),onCreateView(),onActivityCreated(),onViewStateRestore(),onStart(),onResume(),onPause(),onStop(),onDestroy(),onDestroyView(),onDetach(),
Fragment狀態(tài)保存
startActivityForResult是哪個(gè)類的方法,在什么情況下使用,如果在Adapter中使用應(yīng)該如何解耦
AsyncTask原理及不足
intentService原理
HandlerThread+ServiceHandler
Activity 怎么和Service 綁定,怎么在Activity 中啟動(dòng)自己對(duì)應(yīng)的Service
請(qǐng)描述一下Service 的生命周期;
啟動(dòng)服務(wù)的生命周期 onCreate->onStartCommand()->onDestroy()
綁定服務(wù)的生命周期 onCreate()->onBind()->onUnBind()->onDestroy()
AsyncTask+HttpClient與AsyncHttpClient有什么區(qū)別;
如何保證一個(gè)后臺(tái)服務(wù)不被殺死,比較省電的方式是什么
Android中通過(guò)Service實(shí)現(xiàn)后臺(tái)任務(wù)。
方法一:
通過(guò)將Service綁定到Notification,成為一個(gè)前提服務(wù),可以提高存活率
在Service中創(chuàng)建一個(gè)Notification,再調(diào)用Service.startForeground(int id,Notification notification)方法運(yùn)行在前臺(tái)即可。這個(gè)方式使用360等如阿健管家可以殺死。
方法二:
通過(guò)定時(shí)警報(bào)來(lái)不斷啟動(dòng)Service,這樣就算Service被殺死,也能再啟動(dòng)。同時(shí)也可以監(jiān)聽(tīng)網(wǎng)絡(luò)切換,開(kāi)鎖屏等廣播啟動(dòng)Service。
參考:
Intent intent = new Intent(mContext,MyService.class);
PendingIntent sender = PendingIntent.getService(mContext,0,intent,0);
AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),5*10000,sender);
這種方式不斷啟動(dòng)的邏輯處理起來(lái)很麻煩。
方法三:
通過(guò)jni調(diào)用c,在c語(yǔ)音中啟動(dòng)一個(gè)進(jìn)程fork()。 可以保證360等手機(jī)管家不會(huì)清理。但是帶來(lái)了jni交互,稍微有點(diǎn)麻煩。
如何通過(guò)廣播攔截和abort一條短信;
廣播是否可以請(qǐng)求網(wǎng)絡(luò)
廣播引起anr的時(shí)間限制
進(jìn)程間通信,AIDL
事件分發(fā)中的onTouch 和onTouchEvent 有什么區(qū)別,又該如何使用?
說(shuō)說(shuō)ContentProvider、ContentResolver、ContentObserver 之間的關(guān)系;
請(qǐng)介紹下ContentProvider 是如何實(shí)現(xiàn)數(shù)據(jù)共享的
Android提供了ContentProvider,一個(gè)程序可以通過(guò)實(shí)現(xiàn)一個(gè)ContentProvider的抽象接口將自己的數(shù)據(jù)完全暴露出去,而且ContentProvicer是以類似數(shù)據(jù)庫(kù)中表的方式將數(shù)據(jù)暴露。也就是說(shuō)ContentProvider就像一個(gè)“數(shù)據(jù)庫(kù)”。那么外界獲取其提供的數(shù)據(jù),也就應(yīng)該與從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)的操作基本一樣,只不過(guò)是采用URI來(lái)表示外界需要訪問(wèn)的“數(shù)據(jù)庫(kù)”。外部訪問(wèn)通過(guò)ContentResolver去訪問(wèn)并操作這些被暴露的數(shù)據(jù)。
Handler機(jī)制及底層實(shí)現(xiàn)
Handler包括四個(gè)角色:
Handler:負(fù)責(zé)發(fā)送消息處理消息。
Message:消息實(shí)體對(duì)象,handler通過(guò)sendMessage將實(shí)體放到消息隊(duì)列中。
MessageQueQue:存放消息的隊(duì)列。
Looper:消息輪詢器,不停的從消息隊(duì)列中取出消息交給handler處理。
在主線程創(chuàng)建Handler,在需要發(fā)送消息的地方創(chuàng)建一個(gè)Message,通過(guò)handler發(fā)送。這個(gè)消息回到MessageQueQue中,然后Looper會(huì)將這個(gè)消息取出交給handler處理。
Handler可以有多個(gè),但是在同一線程中Looper和MessageQueQue只能有一個(gè)。
Binder機(jī)制及底層實(shí)現(xiàn)
Binder包含四個(gè)角色:
Server 服務(wù)器
Client 客戶終端 ,獲得實(shí)名Binder的引用。Server向ServiceManger注冊(cè)了Binder實(shí)體及名字后,Client就可以通過(guò)名字獲得該Binder的引用。例如我們申請(qǐng)獲得名字叫張三的Binder的引用,ServiceManager收到這個(gè)連接請(qǐng)求,從請(qǐng)求數(shù)據(jù)包里獲得Binder的名字。再找到該名字對(duì)應(yīng)的條目,從條目中取出Binder的引用。將該引用作為回復(fù)發(fā)送給發(fā)起請(qǐng)求的Client。
ServiceManager 域名服務(wù)器(DNS),負(fù)責(zé)將字符形式的Binder名字轉(zhuǎn)化成Client中對(duì)該Binder的應(yīng)用,使得Client能通過(guò)Binder名字獲得Server中Binder實(shí)體的引用。
Binder驅(qū)動(dòng) 可以理解為路由器。Binder驅(qū)動(dòng)負(fù)責(zé)進(jìn)程之間Binder通信的建立,Binder在進(jìn)程間的傳遞。
Binder使用Client-Server通信方式,安全性好,簡(jiǎn)單高效。再加上其面向?qū)ο蟮脑O(shè)計(jì)思想,獨(dú)特的接收緩存管理和線程池管理方式,成為Android進(jìn)程間通信的中流砥柱。
ListView 中圖片錯(cuò)位的問(wèn)題是如何產(chǎn)生的
錯(cuò)位原理: 如果我們只是簡(jiǎn)單的顯示數(shù)據(jù),沒(méi)有convertView的復(fù)用和異步操作,就不會(huì)產(chǎn)生圖片錯(cuò)位。重用convertView但沒(méi)有異步操作也不會(huì)有錯(cuò)位現(xiàn)象。例如我們的listView中剛好顯示7個(gè)item,當(dāng)向下滑動(dòng)時(shí),顯示出item8,而item8是重用的item1,如果此時(shí)異步網(wǎng)絡(luò)請(qǐng)求item8的圖片,比item1的圖片慢,那么item8就會(huì)顯示item1的圖片。當(dāng)item8下載完成,此時(shí)用戶向上滑顯示item1時(shí),又復(fù)用的item8的image。這樣就導(dǎo)致的圖片錯(cuò)位。
解決方法: 對(duì)imageview設(shè)置tag,并預(yù)設(shè)一張圖片。向下滑動(dòng)后,item8顯示,item1隱藏。但由于item1是第一次進(jìn)來(lái)就顯示所以一般情況下,item1都會(huì)比item8先下載完,此時(shí)可見(jiàn)的item8的tag和隱藏了的item1的url不匹配,所以就算item1的圖片下載完也不會(huì)顯示到item8中,因?yàn)閠ag標(biāo)識(shí)的永遠(yuǎn)是可見(jiàn)圖片中的url
holder.img.setTag(imgUrl);
holder.img.setImageResource(R.drawable.ic_launcher);
if(imageView.getTag() != null && imageView.getTag().equals(imageUrl)){ imageView.setImageBitmap(result);}
在manifest 和代碼中如何注冊(cè)和使用BroadcastReceiver
<receiver android:name="包名.自己擴(kuò)展的廣播接收者名">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
說(shuō)說(shuō)Activity、Intent、Service 是什么關(guān)系
ApplicationContext和ActivityContext的區(qū)別
這是兩種不同的context,也是最常見(jiàn)的兩種.第一種中context的生命周期與Application的生命周期相關(guān)的,context隨著Application的銷毀而銷毀,伴隨application的一生,與activity的生命周期無(wú)關(guān).第二種中的context跟Activity的生命周期是相關(guān)的,但是對(duì)一個(gè)Application來(lái)說(shuō),Activity可以銷毀幾次,那么屬于Activity的context就會(huì)銷毀多次.至于用哪種context,得看應(yīng)用場(chǎng)景,個(gè)人感覺(jué)用Activity的context好一點(diǎn),不過(guò)也有的時(shí)候必須使用Application的context.application context
一張Bitmap所占內(nèi)存以及內(nèi)存占用的計(jì)算
Serializable 和Parcelable 的區(qū)別
在Android上應(yīng)該盡量采用Parcelable,它效率更高。
Parcelabe代碼比Serializable多一些。
Parcelabe比Serializable速度高十倍以上。
Serializable只需要對(duì)某個(gè)類以及它的屬性實(shí)現(xiàn)Serializable接口即可,無(wú)需實(shí)現(xiàn)方法。缺點(diǎn)是使用的反射,序列化的過(guò)程較慢,這種機(jī)制會(huì)在序列化的時(shí)候創(chuàng)建許多的臨時(shí)對(duì)象。容易觸發(fā)GC。
Parcable方法實(shí)現(xiàn)的原理是將一根完整的對(duì)象進(jìn)行分解,而分解后的每一部分都是Intent所支持的數(shù)據(jù)類型,這樣也就實(shí)現(xiàn)傳遞對(duì)象的功能。
請(qǐng)描述一下BroadcastReceiver
請(qǐng)描述一下Android 的事件分發(fā)機(jī)制
請(qǐng)介紹一下NDK
一 : NDK是一系列工具的集合
NDK提供了一系列的工具,幫助開(kāi)發(fā)者快速開(kāi)發(fā)C或C++的動(dòng)態(tài)庫(kù),并能自動(dòng)將so和java應(yīng)用一起打包成apk。這些工具對(duì)開(kāi)發(fā)者的幫助是巨大的。
NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件隔離CPU,平臺(tái),ABI等差異。開(kāi)發(fā)人員只需要簡(jiǎn)單修改mk文件(指出哪些文件需要編譯,編譯特性要求等)就可以創(chuàng)建出so。
NDK可以自動(dòng)將so和java應(yīng)用一起打包,極大的減輕了開(kāi)發(fā)人員的打包工作。
二 : NDK提供了一份穩(wěn)定,功能有限的API頭文件聲明。
Google明確聲明該API是穩(wěn)定的,在后續(xù)所有版本中都穩(wěn)定支持當(dāng)前發(fā)布的API。從該版本的NDK中看出,這些API支持的功能非常有限,包含:c標(biāo)準(zhǔn)庫(kù),標(biāo)準(zhǔn)數(shù)學(xué)庫(kù),壓縮庫(kù),Log庫(kù)。
什么是NDK庫(kù),如何在jni中注冊(cè)native函數(shù),有幾種注冊(cè)方式
AsyncTask 如何使用;
對(duì)于應(yīng)用更新這塊是如何做的?(灰度,強(qiáng)制更新,分區(qū)域更新);
混合開(kāi)發(fā),RN,weex,H5,小程序(做Android的了解一些前端js等還是很有好處的)
混合開(kāi)發(fā)就是在一個(gè)App中內(nèi)嵌一個(gè)輕量級(jí)的瀏覽器,一部分源生的功能改為Html5來(lái)開(kāi)發(fā),這部分功能不僅能夠在不升級(jí)App的情況下動(dòng)態(tài)更新,也可以在Android或者iOS的App上同時(shí)運(yùn)行,讓用戶的體驗(yàn)更好又可以節(jié)省開(kāi)發(fā)的資源。
混合開(kāi)發(fā)最主要的是Html5和Native的交互
在Android中WebView本來(lái)就支持js和java相互調(diào)用,只需要開(kāi)啟WebView的腳本執(zhí)行,然后通過(guò)mWebView.addJavascriptInterface(new JsBridge(),"bxbxbai");向Html5頁(yè)面注入一股Java對(duì)象,然后就可以在Html5頁(yè)面中調(diào)用Native的功能了。
Android4.2以后的系統(tǒng)規(guī)定允許被js調(diào)用的Java方法必須以@JavascriptInterface進(jìn)行注解。
兩個(gè)Activity 之間跳轉(zhuǎn)時(shí)必然會(huì)執(zhí)行的是哪幾個(gè)方法?
答:一般情況下比如說(shuō)有兩個(gè)activity,分別叫A,B,當(dāng)在A 里面激活B 組件的時(shí)候, A 會(huì)調(diào)用onPause()方法,然后B 調(diào)用onCreate() ,onStart(), onResume()。
這個(gè)時(shí)候B 覆蓋了窗體, A 會(huì)調(diào)用onStop()方法. 如果B 是個(gè)透明的,或者是對(duì)話框的樣式, 就不會(huì)調(diào)用A 的onStop()方法。