Android性能優(yōu)化(高級(jí))
-
簡(jiǎn)述Android的系統(tǒng)架構(gòu)印蔬?
- android的系統(tǒng)架構(gòu)從下往上分為L(zhǎng)inux內(nèi)核層拐袜,運(yùn)行庫狐粱,應(yīng)用程序框架層和應(yīng)用程序?qū)印?/li>
-
如何對(duì)Android應(yīng)用進(jìn)行性能分析灵汪;
- 使用ddms工具中的traceview败许,heap垒酬,allocation tracker工具砰嘁。traceview是Android平臺(tái)特有的數(shù)據(jù)采集和分析工具,可以用來分析耗時(shí)操作等勘究。heap視圖工具可以幫助我們檢查代碼中是否存在有造成內(nèi)存泄漏的地方矮湘,allocation tracker工具是內(nèi)存分配跟蹤工具。
-
什么情況下會(huì)導(dǎo)致內(nèi)存泄露口糕;
- Android的虛擬機(jī)是基于寄存器的Dalvik,它的最大堆內(nèi)存是16M缅阳,部分機(jī)器是24M,因此能利用的內(nèi)存空間是有限的景描,一旦超出就會(huì)造成OutOfMemory異常券时。
- 內(nèi)存泄漏的幾點(diǎn)原因:1)資源釋放問題,程序代碼的問題伏伯,長(zhǎng)期保持某些資源橘洞,如context,cursor说搅,io流的引用炸枣,資源得不到釋放就造成內(nèi)存泄漏。2)對(duì)象內(nèi)存過大問題,保存了多個(gè)耗用內(nèi)存過大的對(duì)象(如bitmap适肠,xml文件)霍衫,造成內(nèi)存超出限制。3)static關(guān)鍵字的使用侯养,static在Java中敦跌,當(dāng)用來修飾成員變量的時(shí)候,那么該變量就屬于該類逛揩,而不是該類的實(shí)例柠傍,因此用static修飾的變量,生命周期很長(zhǎng)辩稽。針對(duì)static的解決方案:盡量避免static成員變量引用資源耗費(fèi)過多的實(shí)例惧笛,比如context,context盡量使用ApplicationContext逞泄,因?yàn)锳pplication的context的生命周期比較長(zhǎng)患整,引用他不會(huì)出現(xiàn)內(nèi)存泄漏的問題。4)線程導(dǎo)致內(nèi)存泄漏喷众,線程的生命周期不可控各谚。
-
OOM是什么?應(yīng)如何避免到千?
內(nèi)存溢出嘲碧,要避免OOM異常需要先知道是什么原因?qū)е碌漠惓#?/p>
-
圖片過大導(dǎo)致OOM,在Android中用bitmap很容易導(dǎo)致內(nèi)存溢出父阻,比如報(bào)如下錯(cuò)誤:
Java.lang.OutOfMemoryError : bitmap size exceeds VM budget。-
解決方法:
//1)等比例縮小圖片 options.inSampleSize = 2; //Options 只保存圖片尺寸大小望抽,不保存圖片到內(nèi)存 BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 2; Bitmap bmp = null; bmp = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts); //回收 bmp.recycle(); //2)對(duì)圖片采用弱引用加矛,及時(shí)的進(jìn)行recycle()操作。 SoftReference<Bitmap> bitmap = new SoftReference<Bitmap>(pBitmap); if(bitmap != null){ if(bitmap.get() != null && !bitmap.get().isRecycled()){ bitmap.get().recycle(); bitmap = null; } } 3)使用圖片加載框架處理圖片煤篙。
-
-
界面切換的時(shí)候?qū)е翺OM斟览,一般情況下,開發(fā)中都會(huì)禁止橫屏辑奈,一旦橫豎屏切換的多了苛茂,activity的生命周期就會(huì)重新銷毀然后創(chuàng)建。切換的次數(shù)多了鸠窗,就會(huì)導(dǎo)致OOM妓羊。這種問題沒有固定的解決方案,可以從一下幾方面著手分析稍计,
-
1)看頁面布局中有沒有大的圖片躁绸,如背景圖之類的,去除xml文件中相關(guān)設(shè)置,改在代碼中設(shè)置(放在onCreate()方法中)
Drawable drawable = getResources().getDrawable(R.drawable.id); ImageView imageView = new ImageView(this); imageView.setBackgroundDrawable(drawable); //在activity destory的時(shí)候注意净刮,要drawable.setCallback(null)剥哑,防止得不到及時(shí)的釋放。
-
查新數(shù)據(jù)庫時(shí)沒有關(guān)閉游標(biāo)淹父。
構(gòu)造adapter時(shí)株婴,沒有使用緩存convertView,使用convertView的好處:
當(dāng)convertView 為空時(shí)暑认,用setTag()方法為每個(gè)View 綁定一個(gè)存放控件的ViewHolder 對(duì)象困介。當(dāng)convertView 不為空,重復(fù)利用已經(jīng)創(chuàng)建的view 的時(shí)候穷吮,使用getTag()方法獲取綁定的ViewHolder 對(duì)象逻翁,這樣就避免了findViewById 對(duì)控件的層層查詢,而是快速定位到控件捡鱼。bitmap對(duì)象不再使用的時(shí)候調(diào)用recycle()方法釋放內(nèi)存八回。
使用廣播沒有注銷的時(shí)候也會(huì)產(chǎn)生OOM。
-
ANR是什么驾诈? 應(yīng)如何避免和解決缠诅?
- application not responding 程序無響應(yīng)。ANR一般有三種類型: activity 5秒乍迄,broadcastReceiver10秒管引,services20秒。超時(shí)的原因一般有兩種:1)當(dāng)前的事件沒有機(jī)會(huì)得到處理(UI線程正在處理前一個(gè)事件沒有及時(shí)完成或者looper被某種原因阻塞状沉健)2)當(dāng)前的事件正在處理褥伴,但沒有及時(shí)完成,UI線程盡量只做UI相關(guān)的工作漾狼,耗時(shí)操作(數(shù)據(jù)庫操作重慢,io流,連接網(wǎng)絡(luò)或者其他可能阻礙UI線程的操作)放入單獨(dú)的線程處理逊躁,盡量用handler來處理UI thread和thread之間的交互似踱。
-
Android中線程間通信有那幾種方式?
- 共享內(nèi)存(變量)稽煤,文件核芽,數(shù)據(jù)庫,handler酵熙,Java中wait()轧简,notify(),notifyAll()匾二。
-
線程和進(jìn)程之間的區(qū)別吉懊?
- 一個(gè)應(yīng)用程序至少有一個(gè)進(jìn)程庐橙,一個(gè)進(jìn)程至少有一條線程,一個(gè)線程可以創(chuàng)建和撤銷另一個(gè)線程借嗽,同一個(gè)進(jìn)程中的多個(gè)線程可以并發(fā)執(zhí)行态鳖。從邏輯角度講,多線程的意義在于一個(gè)應(yīng)用程序中恶导,有多個(gè)執(zhí)行部分可以同時(shí)執(zhí)行浆竭,但操作系統(tǒng)并沒有將多個(gè)線程看成多個(gè)獨(dú)立的應(yīng)用,來實(shí)現(xiàn)進(jìn)程的調(diào)度惨寿,管理和資源分配邦泄。
android的屏幕適配 :
-
屏幕適配的方式有哪些?
- 適配方式有:權(quán)重weight適配裂垦,layout適配顺囊,代碼使配羞秤,dp適配(layout中定義布局設(shè)置的參數(shù)使用dp)呀舔,dimens適配。
- 在values-1280x720目錄中的dimens增蹭。xml文件中定義同樣的尺寸名稱晕换,但是使用不同的尺寸午乓,當(dāng)在布局文件中使用長(zhǎng)或?qū)拞挝粫r(shí),用@dimens/width來定義闸准。如果在values-1280x720中放置了dimens常量益愈,一定要記得將該常量的對(duì)應(yīng)值在values目錄中的dimens.xml中也放一份,因?yàn)樵撐募悄J(rèn)配置夷家,當(dāng)用戶的手機(jī)不是1280*720的時(shí)候蒸其,系統(tǒng)應(yīng)用用的是默認(rèn)values目錄中的dimens.xml。
-
屏幕適配的處理技巧库快?
- 在分辨率大小不同的問題上摸袁,推薦使用權(quán)重weight適配,一般應(yīng)用于線性布局中缺谴。
- 盡量使用線性布局,相對(duì)布局耳鸯,如果屏幕放不下數(shù)據(jù)湿蛔,可以使用ScrollView來拖動(dòng)。
- 盡量使用9-patch圖片县爬,可以自動(dòng)的根據(jù)圖片上面顯示的內(nèi)容被拉伸和收縮阳啥。
AIDL
-
什么是ALDI?應(yīng)如何使用财喳?
- AIDL是android interface definition language 意思是Android接口定義語言察迟。使用aidl可以幫助我們發(fā)布以及調(diào)用遠(yuǎn)程服務(wù)斩狱,實(shí)現(xiàn)跨進(jìn)程通信。
-
AIDL如何工作扎瓶,能處理哪些類型數(shù)據(jù)?
- 編譯器可以通過aidl文件生成一段代碼所踊,通過預(yù)先定義的接口達(dá)到兩個(gè)進(jìn)程內(nèi)部通信進(jìn)程跨進(jìn)程對(duì)象訪問的目的,需要完成兩件事:一是引入aidl的相關(guān)類概荷;二是調(diào)用aidl產(chǎn)生的class文件秕岛,理論上,參數(shù)可以傳遞基本數(shù)據(jù)類型和String误证,還有就是Bundle的派生類继薛。
android 的事件處理 :
handler消息機(jī)制:
Android中主線程主要是用來創(chuàng)建,更新UI的愈捅,而耗時(shí)操作遏考,網(wǎng)絡(luò)請(qǐng)求等則需要在子線程中操作。而handler主要接受子線程發(fā)送的數(shù)據(jù)蓝谨,并用該數(shù)據(jù)來配合主線程更新UI灌具,handler運(yùn)行在主線程中,他和子線程通過message對(duì)象來傳遞數(shù)據(jù)(子線程通過sendMessage()方法來發(fā)送消息像棘,數(shù)據(jù))稽亏,將子線程發(fā)送來的這些消息放入到主線程中,配合主線程來更新UI缕题。
handleThread截歉,Looper,MessageQueue和Message的關(guān)系:handlerThread負(fù)責(zé)將需要傳遞的信息封裝成Message對(duì)象烟零,通過handler對(duì)象的sendMesage()方法將消息傳遞給looper瘪松,在有l(wèi)ooper將message放入messageQueue消息隊(duì)列中,當(dāng)looper對(duì)象看見MessageQueue中含有Message時(shí)锨阿,就將其廣播出去宵睦,該handler對(duì)象手到該消息之后,調(diào)用相應(yīng)的handler對(duì)象的handlerMessage()方法對(duì)其進(jìn)行處理墅诡。
-
handler消息機(jī)制的底層簡(jiǎn)單分析:
- 首先是messageQueue和Looper的創(chuàng)建:當(dāng)系統(tǒng)啟動(dòng)的時(shí)候壳嚎,先加載activityThread這個(gè)類,在這個(gè)類中的main方法會(huì)調(diào)用Looper.prepareMainLooper()這個(gè)方法末早,來創(chuàng)建一個(gè)Looper對(duì)象烟馅,Looper對(duì)象就會(huì)通過ThreadLocal把他和當(dāng)前線程綁定在一起,創(chuàng)建Looper的時(shí)候就創(chuàng)建了一個(gè)MessageQueue,MessageQueue是個(gè)final類型的成員變量然磷。這樣就保證了一個(gè)Looper對(duì)應(yīng)一個(gè)MessageQueue郑趁,所有的MessageQueue創(chuàng)建好了之后,就會(huì)一個(gè)線程對(duì)應(yīng)唯一的messageQueue姿搜。然后MessageQueue在創(chuàng)建的時(shí)候通過JNI創(chuàng)建了一個(gè)NativeMessageQueue,他又創(chuàng)建了一個(gè)c++Looper,所以說Handler的底層是通過C++來實(shí)現(xiàn)的寡润。MessageQueue中保存了一個(gè)int類型的成員變量mptr,他保存了NativeMessageQueue的指針,這樣就是了MessageQueue和NativeMessageQueue的對(duì)應(yīng)捆憎。
- 接下來是從消息隊(duì)列中取消息:之后就會(huì)調(diào)用Looper.loop()來取消息,這里面有一個(gè)死循環(huán),在這個(gè)死循環(huán)里存在著queue.next();的方法他是阻塞主線程的,它實(shí)際上就是調(diào)用了NativeMessageQueue去C++層取消息,如果取出來這個(gè)loop就去執(zhí)行,沒取出來就會(huì)阻塞在這里不去執(zhí)行,這樣就能是界面能夠停留而不至于代碼執(zhí)行完界面就跳出;取出消息后調(diào)用handler.dispatchMessage()來分發(fā)消息,message這里面有一個(gè)回調(diào),handler在創(chuàng)建的時(shí)候有一個(gè)回調(diào),如果兩個(gè)回調(diào)都為空的那么直接調(diào)用handleMessage()來處理消息,這就是取消息。
- 最后就是存消息:也就是向消息隊(duì)列中發(fā)送消息,不管是sendMessage還是sendMessageDelaty等他們調(diào)用都是sendMessageAtTime(),在這個(gè)方法里面他實(shí)際調(diào)用的是messqueue.enqueuemessage()這里面實(shí)際上就是拿著當(dāng)前消息要執(zhí)行的時(shí)間進(jìn)行排序,然后就會(huì)通過消息隊(duì)列保存起來,這里面有一個(gè)message.next()他們都可以通過這個(gè)方法一條指向下一條,這樣一條一條連起來,當(dāng)有消息需要馬上執(zhí)行就會(huì)調(diào)用nativewake(),這個(gè)方法就會(huì)把Looper.looper()的queue.next()喚醒就能取出消息,他就可以開始工作.
事件分發(fā)機(jī)制
-
OnTouchEvent的事件傳遞機(jī)制:
- 當(dāng)手指觸摸到屏幕時(shí),系統(tǒng)會(huì)調(diào)用相應(yīng)的view的onTouchEvent,傳入一系列的action,那么首先觸發(fā)的是activity的dispatchTouchEvent,然后觸發(fā)activity的onUserInteraction,在觸Layout的dispatchTouchEvent,然后觸發(fā)Layout的onInterceptTouchEvent.
如果dispatchTouchEvent:
事件由此分發(fā),通常會(huì)調(diào)用super. DispatchTouchEvent.
如果onInterceptTouchEvent(攔截事件):
返回true:表示事件被攔截會(huì)傳遞給自己的onTouchEvent處理,
返回false:不進(jìn)行攔截,會(huì)將事件傳遞給下一個(gè)view的dispatchTouchEvent()進(jìn)行判斷.
如果onTouchEvent:
返回結(jié)果為true:表示事件由自己處理,消費(fèi).
返回結(jié)果為false:表示當(dāng)前事件自己不做處理,交給父view的onTouchEvent處理.
view的繪制流程:
參考博文:http://www.reibang.com/p/5a71014e7b1b
-
子線程發(fā)消息到主線程更新UI梭纹,處理handler躲惰,asyncTask還有什么;
-
用activity對(duì)象的runOnUiThread()在線程中更新UI。
new Thread() { @Override public void run() { super.run(); //這兒是耗時(shí)操作栗柒,完成之后更新ui. runOnUiThread(new Runnable() { @Override public void run() { //更新ui ImageView.setImageBitmap(bitmap); } }); } }.start(); //如果是非上下文類中(activity)礁扮,可以通過傳遞上下文實(shí)現(xiàn)調(diào)用; //Activity activity = (Activity) imageView.getContext() ; activity.runOnUiThread(new Runable() { @Override public void run() { imageView.setImageBitmap(bitmap); } });
-
-
子線程中能不能new handler瞬沦,為什么太伊?
- 不能,如果在子線程中直接new Handler() 會(huì)拋異常逛钻。
Android 中的動(dòng)畫 :
-
動(dòng)畫類型有幾種僚焦,特點(diǎn)和區(qū)別是什么?
- 屬性動(dòng)畫曙痘,補(bǔ)間動(dòng)畫芳悲;補(bǔ)間動(dòng)畫只是顯示的位置變動(dòng),view的實(shí)際位置未改變边坤,表現(xiàn)為view移動(dòng)到其他地方名扛,點(diǎn)擊事件仍在原處才能相應(yīng),而屬性動(dòng)畫在控件移動(dòng)后時(shí)間響應(yīng)就在控件移動(dòng)后本身進(jìn)行處理茧痒。
-
如何修改Activity進(jìn)入和退出的動(dòng)畫;
- 通過兩種方式:1)通過定義activity的主題肮韧,2)通過復(fù)寫activity的overridePendingTransition(R.anim.fade,R.anim.hold)方法。
LRUCache的底層原理:
- 通過獲取內(nèi)存的最大可用值旺订,lrucache通過構(gòu)造函數(shù)傳入緩存值弄企,它是kb為單位,在不超出可使用內(nèi)存的最大值的情況下区拳,超出就會(huì)OOM拘领,通過使用最大緩存值的1/8作為緩存的大小,重寫sizeOf()方法來返回每一張圖片的大小樱调,這就是lurcache的是使用方法约素,那么lruchche為何這樣強(qiáng)大,原因是它的主要算法原理是將最近最少使用的對(duì)象用強(qiáng)引用存儲(chǔ)在LinkedHashMap中笆凌,并且將最近最少使用的對(duì)象在緩存值達(dá)到預(yù)設(shè)值之前從內(nèi)存中移除圣猎,在過去經(jīng)常使用一種非常流行的緩存技術(shù)實(shí)現(xiàn),就是軟引用和弱引用菩颖,但現(xiàn)在不再使用了样漆,因?yàn)樵贏ndroid2.3之后为障。垃圾回收機(jī)制更容易傾向于回收持有軟引用和弱引用的對(duì)象晦闰,這就讓軟引用和弱引用顯得不可靠放祟,另外在Android3,0之后,圖片的數(shù)據(jù)會(huì)存儲(chǔ)在本地內(nèi)存中呻右,因而無法用一種可預(yù)見的方式將其釋放跪妥,這就會(huì)潛在的造成應(yīng)用程序內(nèi)存溢出或者崩潰,而再有了lruCache這個(gè)功能之后声滥,解決這些問題就不在難了眉撵。
JNI的調(diào)用過程:
- 安裝和下載cygwin,下載Android NDK.
- ndk項(xiàng)目中JNI接口的設(shè)計(jì)落塑,
- 使用C/C++實(shí)現(xiàn)本地方法
- JNI生成動(dòng)態(tài)鏈接庫.so文件
- 將動(dòng)態(tài)鏈接庫復(fù)制到Java工程纽疟,在Java工程中調(diào)用,運(yùn)行Java工程即可憾赁。
圖片加載框架picasso污朽,glide,imageLoader龙考,F(xiàn)resco之間的區(qū)別:
-
共同的優(yōu)點(diǎn):
- 使用簡(jiǎn)單--都可以通過一句代碼實(shí)現(xiàn)圖片的獲取和顯示蟆肆。
- 可配置度高,自適應(yīng)行性高--可根據(jù)系統(tǒng)性能初始化緩存配置晦款,給句cpu核數(shù)確定最大并發(fā)數(shù)炎功,根據(jù)網(wǎng)絡(luò)狀態(tài)變化來調(diào)整最大并發(fā)數(shù),根據(jù)可用內(nèi)存確定最大緩存大小缓溅,
- 多級(jí)緩存--每種框架至少有兩級(jí)緩存蛇损,可以提高圖片的加載速度。
- 支持多種數(shù)據(jù)源--網(wǎng)絡(luò)肛宋,本地州藕,資源文件。
- 支持多種displayer--不僅支持imageView酝陈,同時(shí)支持多種view以及一些虛擬的imageview床玻。
- 支持動(dòng)畫。
imageLoader的設(shè)計(jì)模式:
* 一個(gè)強(qiáng)大的圖片加載框架沉帮,很好的處理了圖片加載的多線程锈死,緩存,內(nèi)存溢出等問題穆壕。多線程異步加載和顯示圖片(圖片來源于網(wǎng)絡(luò)待牵,sd卡,assets文件夾喇勋,drawable文件夾缨该,不能加載9patch圖片,可以加載視頻縮略圖)
* ImageLoader 收到加載及顯示圖片的任務(wù)川背,并將它交給 ImageLoaderEngine贰拿,ImageLoaderEngine 分發(fā)任務(wù)到具體線程池去執(zhí)行蛤袒,任務(wù)通過 Cache 及 ImageDownloader 獲取圖片,中間可能經(jīng)過 BitmapProcessor 和 ImageDecoder 處理膨更,最終轉(zhuǎn)換為Bitmap 交給 BitmapDisplayer 在 ImageAware 中顯示妙真。
* imageloader的優(yōu)點(diǎn):
*
* 支持下載進(jìn)度條監(jiān)聽,支持在view的滾動(dòng)中暫停圖片的加載荚守,實(shí)現(xiàn)了多種內(nèi)存緩存算法珍德,支持本地緩存文件名規(guī)則定義。
* 支持監(jiān)視加載的過程矗漾,可以暫停加載圖片锈候,在經(jīng)常使用的listview,GridView敞贡,可以設(shè)置滑動(dòng)時(shí)暫停加載晴及,停止滑動(dòng)的時(shí)候加載圖片。
* 高度可定制化嫡锌,可以根據(jù)自己的需求進(jìn)行各種配置虑稼,(線程池,圖片下載器势木,內(nèi)存緩存策略等)
* 支持圖片內(nèi)存緩存蛛倦,文件緩存
* 在網(wǎng)絡(luò)速度較慢的時(shí)候,還可以對(duì)圖片進(jìn)行加載并設(shè)置下載監(jiān)聽啦桌。
* 避免同一個(gè)uri加載過程中重復(fù)開啟任務(wù)加載
* 減少加載大圖片出現(xiàn)oom的情況溯壶。
* 不足:
*
* 不支持加載GIF圖片。
Picasso的設(shè)計(jì)模式:
* Picasso 收到加載及顯示圖片的任務(wù)甫男,創(chuàng)建 Request 并將它交給 Dispatcher且改,Dispatcher 分發(fā)任務(wù)到具體 RequestHandler,任務(wù)通過 MemoryCache 及 Handler(數(shù)據(jù)獲取接口) 獲取圖片板驳,圖片獲取成功后通過 PicassoDrawable 顯示到 Target 中又跛。
* Picasso的優(yōu)點(diǎn):
*
* 自帶統(tǒng)計(jì)監(jiān)控功能--支持圖片緩存使用的監(jiān)控,包括已使用內(nèi)存大小若治,節(jié)省的流量慨蓝。
* 支持優(yōu)先級(jí)處理。
* 支持延遲到圖片尺寸計(jì)算完成加載端幼,
* 支持飛行模式礼烈,并發(fā)線程數(shù)根據(jù)網(wǎng)絡(luò)類型而變。
* 無本地緩存--不是說沒有本地緩存婆跑,而是Picasso自身沒有定義本地緩存的接口此熬,默認(rèn)使用http的本地緩存。
* 不足:
*
* 不支持加載GIF圖片,緩存之后的圖片沒有進(jìn)行縮放
glide的設(shè)計(jì)模式:
* Glide 收到加載及顯示資源的任務(wù)犀忱,創(chuàng)建 Request 并將它交給RequestManager疟赊,Request 啟動(dòng) Engine 去數(shù)據(jù)源獲取資源(通過 Fetcher ),獲取到后 Transformation 處理后交給 Target峡碉。Glide 依賴于 DiskLRUCache、GifDecoder 等開源庫去完成本地緩存和 Gif 圖片解碼工作驮审。
* glide的優(yōu)點(diǎn):
* 支持多種圖片緩存鲫寄,GIF,webP疯淫,縮略圖地来,甚至是video。
* 支持優(yōu)先級(jí)處理
* 支持velloy熙掺,okHttp.實(shí)際上imageloader未斑。Picasso也支持velloy,OKHttp币绩。
* 內(nèi)存緩存的是處理之后的圖片蜡秽,而不是原始圖片,節(jié)省內(nèi)存大小缆镣。
fresco的優(yōu)點(diǎn):
* 支持流式芽突,支持類似于網(wǎng)頁上的從模糊到清晰加載圖片,漸進(jìn)式加載JPEG圖片董瞻。
* 圖片可以從任意的中心點(diǎn)顯示在imageView寞蚌,而不僅僅是圖片的中心。
* 支持多幀動(dòng)畫钠糊,GIF挟秤,webP.
* 缺點(diǎn): 框架較大,影響apk的體積抄伍,使用較繁瑣艘刚。
網(wǎng)絡(luò)請(qǐng)求框架Volley 和Ok-http,android-async-http,retrofit的區(qū)別:
volley框架:
* google推出的異步網(wǎng)絡(luò)請(qǐng)求框架和圖片加載框架,適合數(shù)據(jù)量小截珍,通信頻繁的網(wǎng)絡(luò)操作昔脯。
* 能夠使網(wǎng)絡(luò)通信更快,更簡(jiǎn)單笛臣,拓展性更好一點(diǎn)云稚,
* get,post網(wǎng)絡(luò)請(qǐng)求以及網(wǎng)絡(luò)圖像的高效率異步處理請(qǐng)求沈堡。
* 可以對(duì)網(wǎng)絡(luò)請(qǐng)求進(jìn)行排序優(yōu)先級(jí)管理静陈。
* 支持網(wǎng)絡(luò)請(qǐng)求的緩存
* 多級(jí)別取消請(qǐng)求
* 使用volley可以簡(jiǎn)化一些網(wǎng)絡(luò)通信的開發(fā),不適合大數(shù)據(jù)和流媒體的網(wǎng)絡(luò)請(qǐng)求,例如上百兆文件鲸拥,視頻上傳拐格。
* volley在Android2.2以下使用httpClient,2.2以上使用的是httpUriConnection.
* Volley的使用:http://blog.csdn.net/sinyu890807/article/details/17482095
基本的使用方法: http://www.kwstu.com/ArticleView/kwstu_20144118313429
直接返回Object的話刑赶,用Gson/FastJson與Volley的結(jié)合:http://www.cnblogs.com/freexiaoyu/p/3955137.html
* Volley問題收錄:Volley的request默認(rèn)回調(diào)到主線程中捏浊,如果有需求是要加載到sqlite等等仍需要在子線程中進(jìn)行的操作 解決方案 :https://www.zhihu.com/question/36672622/answer/76003423
async-Http框架:
* 清晰地網(wǎng)絡(luò)請(qǐng)求回調(diào)
* 網(wǎng)絡(luò)請(qǐng)求使用線程池ThreadPool,限制并發(fā)資源使用情況
* get/post基于參數(shù)構(gòu)建使用(RequestParams)
* 支持Multipart文件上傳撞叨,大數(shù)據(jù)上傳下載金踪。
* 內(nèi)置響應(yīng)解析成json.
* 持久化cookie存儲(chǔ),保存cookie到應(yīng)用程序的sharedPreferences.
* 支持二進(jìn)制文件牵敷,圖片的下載
* 使用的是httpClient
okhttp框架:
* OKhttp和retrofit都出自于Square公司胡岔,是高性能的http庫。
* OKhttp使用okio進(jìn)行數(shù)據(jù)傳輸枷餐, 包含一般的get靶瘸,post請(qǐng)求;基于http的文件毛肋,圖片上傳怨咪,加載;支持請(qǐng)求回調(diào)润匙,直接返回對(duì)象惊暴,對(duì)象集合;支持session的保持趁桃。
* 支持spdy,http2.0,websocket,支持同步辽话,異步,
* 封裝了線程池卫病,數(shù)據(jù)轉(zhuǎn)換油啤,參數(shù)使用,錯(cuò)誤處理等蟀苛;
* OKhttp使用教程:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html
retrofit框架:
* 出自于Square公司益咬,是對(duì)OKhttp做了一層封裝。
* 支持Gson解析帜平,retrofit已經(jīng)在內(nèi)部封裝了json解析
異步加載框架handler幽告,asyncTask,RXJava :
-
異步加載框架之a(chǎn)syncTask:
- 需要重寫的四個(gè)方法:doInBackground(Params params)運(yùn)行在后臺(tái)線程中;onPreExecute(),onProgressUpdate(progress),onPostExecute(result)這三個(gè)方法是運(yùn)行在UI線程中裆甩。
- 使用aysncTack需要遵守的原則:task實(shí)例必須在UI線程中創(chuàng)建冗锁;execute方法必須在UI線程中調(diào)用;不要手動(dòng)的調(diào)用那四個(gè)方法嗤栓。
- asyncTask內(nèi)部也是handler機(jī)制完成的冻河,只不過Android提供了執(zhí)行框架來提供線程池來執(zhí)相應(yīng)的任務(wù)箍邮,因?yàn)榫€程池的大小的問題,所以asyncTask值應(yīng)該用來執(zhí)行耗時(shí)較短的任務(wù)叨叙,比如HTTP請(qǐng)求锭弊,大規(guī)模的下載和數(shù)據(jù)庫的更改不適用于asyncTask,因?yàn)闀?huì)導(dǎo)致線程池堵塞擂错,沒有線程來執(zhí)行其他任務(wù)味滞,導(dǎo)致asyncTask根本執(zhí)行不了。
-
rxjava框架:
- rxjava是一個(gè)異步操作庫钮呀,在JavaVM上使用可觀測(cè)的序列來組成異步的剑鞍,基于事件的程序的庫,rxjava的優(yōu)勢(shì)在于簡(jiǎn)潔行楞,隨著程序邏輯變得越來越復(fù)雜,rxJava確一直簡(jiǎn)潔土匀,能夠很大程度的提升代碼的閱讀性子房。他通過拓展的觀察者模式來實(shí)現(xiàn)的。rxjava有四個(gè)基本的概念:被觀察者Observable就轧,觀察者Observer证杭,訂閱事件subscribe,Observable和observer通過subscribe()來實(shí)現(xiàn)訂閱關(guān)系妒御,從而Observable可以在需要的時(shí)候發(fā)出事件來通知Observer解愤。
MVC和MVP的區(qū)別腮出;
- MVC是model (模型) view (視圖) controller(控制器)佳晶,view強(qiáng)依賴于model是MVC的主要問題,使用MVC伟恶,將業(yè)務(wù)邏輯抽離到controller中惋啃,讓view層專注于UI.
- MVC指的是model view controller,model著的是數(shù)據(jù)層,主要負(fù)責(zé)相關(guān)的業(yè)務(wù)邏輯,包括數(shù)據(jù)庫,網(wǎng)絡(luò)本地緩存等,view是指界面,主要負(fù)責(zé)UI相關(guān)的業(yè)務(wù)邏輯,包括布局界面,相關(guān)控件的顯示,controller是控制層,主要負(fù)責(zé)處理在對(duì)象狀態(tài)下調(diào)用model和view的方法實(shí)現(xiàn)數(shù)據(jù)和UI展示的相關(guān)邏輯.以MVC的設(shè)計(jì)模式的開發(fā)流程在一定程度上提高了代碼的可維護(hù)性,比如要修改UI界面的相關(guān)數(shù)據(jù),就可以找到對(duì)應(yīng)的處理層來處理代碼,但由于model和view的相關(guān)邏輯都寫在avtivity控制層了,這樣后期維護(hù)起來比較麻煩,因此就產(chǎn)生了一種新的設(shè)計(jì)模式,MVP,MVP指的是model view presenter,是在MVC的基礎(chǔ)上,將controller層該為了presenter層,它成為了model和view層之間交互的橋梁,他本身不具有任何的邏輯代碼,只是在對(duì)應(yīng)的狀態(tài)下調(diào)用model和view層的方法來實(shí)現(xiàn)數(shù)據(jù)的相關(guān)邏輯和UI展示.
- 兩者的區(qū)別在于MVP中view不能直接的使用model層,它們之間的通信是通過Presenter(MVC中的Controller)來進(jìn)行的,所有的交互都發(fā)生在Presenter內(nèi)部哼鬓,而在MVC中View會(huì)直接從Model中讀取數(shù)據(jù)而不是通過 Controller。
網(wǎng)絡(luò)請(qǐng)求get和post的區(qū)別边灭;
- get是從服務(wù)器上獲取數(shù)據(jù)异希,post是向服務(wù)器上傳輸數(shù)據(jù)。
- get是把參數(shù)數(shù)據(jù)隊(duì)列加到提交表單的ACTION屬性所指的URL中绒瘦,值和表單內(nèi)各個(gè)字段一一對(duì)應(yīng)称簿,在URL中可以看到。post是通過HTTP post機(jī)制惰帽,將表單內(nèi)各個(gè)字段與其內(nèi)容放置在HTML HEADER內(nèi)一起傳送到ACTION屬性所指的URL地址憨降。用戶看不到這個(gè)過程。
- 對(duì)于get方式该酗,服務(wù)器端用Request.QueryString獲取變量的值券册,對(duì)于post方式,服務(wù)器端用Request.Form獲取提交的數(shù)據(jù)。
- get傳送的數(shù)據(jù)量較小烁焙,不能大于2KB航邢。post傳送的數(shù)據(jù)量較大,一般被默認(rèn)為不受限制骄蝇。但理論上膳殷,IIS4中最大量為80KB,IIS5中為100KB九火。
- get安全性非常低赚窃,post安全性較高。但是執(zhí)行效率卻比Post方法好岔激。
- get可以被瀏覽器緩存勒极,post不可以。
- get請(qǐng)求是安全的虑鼎,post不安全辱匿。
Android中常見的解決沖突的方案:
- 多個(gè)滑動(dòng)必然會(huì)產(chǎn)生沖突,比如最常見的scrollView中嵌套listview炫彩,一般做法是計(jì)算出listview的總高度匾七,這樣就不用去滑動(dòng)listview了。再比如viewpager嵌套fragment江兢,fragment中又有l(wèi)istview昨忆,這原本是由滑動(dòng)沖突的,但是viewpager內(nèi)部已經(jīng)幫我們解決了這種沖突杉允,如果需要自己解決的話邑贴,可以通過下面兩種方式解決:一是外部攔截法,外部攔截法是指在有點(diǎn)擊事件時(shí)都要經(jīng)過父容器叔磷,那么在父容器時(shí)如果需要攔截就攔截自己處理痢缎,不需要?jiǎng)t傳遞給下一層進(jìn)行處理,主要的攔截是需要重寫onInterceptTouchEvent()方法世澜。二是內(nèi)部攔截法独旷,是指父容器不攔截任何事件,所有事件都傳遞給子view寥裂,如果需要就直接消費(fèi)掉嵌洼,不需要在傳給父容器處理。需要重寫dispatchTouchEvent()方法封恰。
- 參考博文:http://blog.csdn.net/lylodyf/article/details/52438997
簡(jiǎn)述對(duì)Binder機(jī)制的理解麻养。
- binder機(jī)制是用來實(shí)現(xiàn)不同進(jìn)程之間的通信的。binder屬于一個(gè)驅(qū)動(dòng)诺舔,工作在linux層鳖昌,運(yùn)行在內(nèi)核態(tài)备畦,它的操作完成是基于一段內(nèi)存,因此我們開發(fā)的程序中對(duì)binder的調(diào)用都是通過系統(tǒng)的調(diào)用來完成的许昨,binder的架構(gòu)由服務(wù)端懂盐,binder驅(qū)動(dòng),客戶端三部分組成糕档。處于對(duì)程序的安全性莉恼,可靠性,傳輸性能的考慮速那,Android選用binder來實(shí)現(xiàn)不同進(jìn)程之間的通信俐银。
談?wù)剬?duì)context的理解。
- 從字面意思理解是“上下文"的意思端仰,從類的繼承關(guān)系來看捶惜,context是一個(gè)抽象的基類,它的實(shí)現(xiàn)子類有三種:application荔烧,activity和service吱七。我們通過它來訪問當(dāng)前包的資源(getResources,getAssets),啟動(dòng)其他組件(activity茴晋,service陪捷,broadCastReceiver)以及得到各種服務(wù)(getSystemService)回窘。換句話說诺擅,context提供了一個(gè)應(yīng)用運(yùn)行的環(huán)境,在context的大環(huán)境中啡直,應(yīng)用才可以訪問資源烁涌,才能完成和其他組件,服務(wù)交互酒觅。
如何縮減apk的大小撮执,apk的打包;
- Android打包本身會(huì)對(duì)png圖片進(jìn)行無損壓縮舷丹,但是純粹的進(jìn)行無損壓縮并不會(huì)對(duì)apk的減小有任何的效果抒钱,因此可以可以通過tinypng進(jìn)行有損壓縮。
- png換成jpg,如果圖片還大颜凯,在不降低畫質(zhì)的情況下谋币,可以在將jpg換成webp.
- 大圖縮小
- 覆蓋arr中一些默認(rèn)的大圖,典型的是support-v4包中包含的一些可能用到的圖片症概,在實(shí)際中app是用不到的蕾额。并不是吧所有用不到的圖片替換掉,而是把幾張較大的圖片用1x1的圖片替換彼城。
- 刪除armable-v7包中的so文件诅蝶, armable-v7和armable文件夾可以只保留armable退个。
- 微信資源壓縮打包。采用微信壓縮方案调炬。
- proground深度混淆代碼
- 深度清理代碼和資源语盈,引入的無用圖片,相同的圖片筐眷,圖片可用著色方案替換黎烈,用shape替換等。
- 去除重復(fù)庫
- 表情包在線化
談?wù)剬?duì)Android NDK的理解匀谣。
- Android NDK是一系列工具的集合照棋,可以快速的幫助開發(fā)者開發(fā)C/C++的動(dòng)態(tài)庫,并能自動(dòng)將so文件和Java應(yīng)用一起打包成apk武翎。
- ndk 提供了一份穩(wěn)定的烈炭,功能有限的API頭文件聲明;
- NDK是Android平臺(tái)支持C開發(fā)的開端宝恶。
Android中進(jìn)程間通訊的實(shí)現(xiàn)方式符隙。
Bundle/Intent傳遞數(shù)據(jù):可傳遞基本類型,String垫毙,實(shí)現(xiàn)了Serializable或Parcellable接口的數(shù)據(jù)結(jié)構(gòu)霹疫。Serializable是Java的序列化方法,Parcellable是Android的序列化方法综芥,前者代碼量少(僅一句)丽蝎,但I(xiàn)/O開銷較大,一般用于輸出到磁盤或網(wǎng)卡膀藐;后者實(shí)現(xiàn)代碼多屠阻,效率高,一般用戶內(nèi)存間序列化和反序列化傳輸额各。
文件共享:對(duì)同一個(gè)文件先后寫讀国觉,從而實(shí)現(xiàn)傳輸,Linux機(jī)制下虾啦,可以對(duì)文件并發(fā)寫麻诀,所以要注意同步。順便一提傲醉,Windows下不支持并發(fā)讀或?qū)憽?/p>
Messenger:Messenger是基于AIDL實(shí)現(xiàn)的蝇闭,服務(wù)端(被動(dòng)方)提供一個(gè)Service來處理客戶端(主動(dòng)方)連接,維護(hù)一個(gè)Handler來創(chuàng)建Messenger需频,在onBind時(shí)返回Messenger的binder丁眼。
雙方用Messenger來發(fā)送數(shù)據(jù),用Handler來處理數(shù)據(jù)昭殉。Messenger處理數(shù)據(jù)依靠Handler苞七,所以是串行的藐守,也就是說,Handler接到多個(gè)message時(shí)蹂风,就要排隊(duì)依次處理卢厂。AIDL:AIDL通過定義服務(wù)端暴露的接口,以提供給客戶端來調(diào)用惠啄,AIDL使服務(wù)器可以并行處理慎恒,而Messenger封裝了AIDL之后只能串行運(yùn)行,所以Messenger一般用作消息傳遞撵渡。
通過編寫aidl文件來設(shè)計(jì)想要暴露的接口融柬,編譯后會(huì)自動(dòng)生成響應(yīng)的java文件,服務(wù)器將接口的具體實(shí)現(xiàn)寫在Stub中趋距,用iBinder對(duì)象傳遞給客戶端粒氧,客戶端bindService的時(shí)候,用asInterface的形式將iBinder還原成接口节腐,再調(diào)用其中的方法外盯。ContentProvider:系統(tǒng)四大組件之一,底層也是Binder實(shí)現(xiàn)翼雀,主要用來為其他APP提供數(shù)據(jù)饱苟,可以說天生就是為進(jìn)程通信而生的。自己實(shí)現(xiàn)一個(gè)ContentProvider需要實(shí)現(xiàn)6個(gè)方法狼渊,其中onCreate是主線程中回調(diào)的箱熬,其他方法是運(yùn)行在Binder之中的。自定義的ContentProvider注冊(cè)時(shí)要提供authorities屬性囤锉,應(yīng)用需要訪問的時(shí)候?qū)傩园b成Uri.parse("content://authorities")坦弟。還可以設(shè)置permission护锤,readPermission官地,writePermission來設(shè)置權(quán)限。 ContentProvider有query烙懦,delete驱入,insert等方法,看起來貌似是一個(gè)數(shù)據(jù)庫管理類氯析,但其實(shí)可以用文件亏较,內(nèi)存數(shù)據(jù)等等一切來充當(dāng)數(shù)據(jù)源,query返回的是一個(gè)Cursor掩缓,可以自定義繼承AbstractCursor的類來實(shí)現(xiàn)雪情。
Socket:學(xué)過計(jì)算機(jī)網(wǎng)絡(luò)的對(duì)Socket不陌生,所以不需要詳細(xì)講述你辣。只需要注意巡通,Android不允許在主線程中請(qǐng)求網(wǎng)絡(luò)尘执,而且請(qǐng)求網(wǎng)絡(luò)必須要注意聲明相應(yīng)的permission。然后宴凉,在服務(wù)器中定義ServerSocket來監(jiān)聽端口誊锭,客戶端使用Socket來請(qǐng)求端口,連通后就可以進(jìn)行通信弥锄。
實(shí)現(xiàn)一個(gè)自定義view的基本流程丧靡;
- 自定義view的屬性:在res/values/下建立一個(gè)attrs.xml文件,在里面定義我們的屬性和聲明我們的整個(gè)樣式籽暇。在xml文件中一定要引入命名空間温治。
- 在view的構(gòu)造方法中獲取到我們的自定義屬性
- 重寫onMersure()方法
- 重寫onDraw()方法
- 參考博文:http://blog.csdn.net/lmj623565791/article/details/24252901/
幾種常見的設(shè)計(jì)模式;
單例模式:
-
單例模式是確保某個(gè)類只有一個(gè)實(shí)例,有懶漢式和餓漢式,
* 懶漢式,首先得私有化構(gòu)造函數(shù),防止類在外部被實(shí)例化,接下來就是書寫Singleton類型的getInstance()靜態(tài)的方法,避免線程不安全可以再靜態(tài)方法上加鎖synchronized.以下是線程安全的懶漢式的設(shè)計(jì)模式. public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } * 餓漢式是在類一加載的時(shí)候就直接進(jìn)行了實(shí)例化,本身就是線程安全的. //餓漢式單例類.在類初始化時(shí)戒悠,已經(jīng)自行實(shí)例化 public class Singleton1 { private Singleton1() {} private static final Singleton1 single = new Singleton1(); //靜態(tài)工廠方法 public static Singleton1 getInstance() { return single; } }
什么時(shí)候使用單例模式罐盔?
* 當(dāng)這個(gè)類的對(duì)象在多個(gè)地方創(chuàng)建的時(shí)候,使得內(nèi)部的方法多次調(diào)用救崔,但是我們希望只要一個(gè)對(duì)象操作這個(gè)方法惶看,或者不希望多個(gè)地方同時(shí)調(diào)用這個(gè)方法,我們需要保持這個(gè)方法的單一性質(zhì)六孵,我們就用單利模式纬黎。
簡(jiǎn)單的工廠類:
適配器模式:
談?wù)勀阍趯?shí)際項(xiàng)目中怎樣解決一個(gè)BUG;
- 異常附近多打印log信息
- 分析log日志,進(jìn)行斷點(diǎn)調(diào)試劫窒,
- 調(diào)試不出來本今,上stack Overflow貼上異常信息,請(qǐng)加大牛
- 多看看代碼主巍,從源碼中分析冠息,查找相關(guān)信息。
- 網(wǎng)上搜索相關(guān)問題孕索,解決方案逛艰,或?qū)で髱煾祹兔Α?/li>
怎樣對(duì)Android進(jìn)行優(yōu)化
- listview優(yōu)化,圖片優(yōu)化搞旭,內(nèi)存優(yōu)化散怖,盡量不使用過多的靜態(tài)類static,數(shù)據(jù)庫使用完成之后肄渗,要記得關(guān)閉cursor镇眷。廣播使用完之后要注銷。
談?wù)勀銓?duì)bitmap的理解翎嫡,什么時(shí)候應(yīng)該手動(dòng)調(diào)用bitmap.recycle().
- bitmap是Android中經(jīng)常使用的一個(gè)類欠动,它代表一個(gè)圖片資源,bitmap消耗內(nèi)存很嚴(yán)重惑申,如果不注意優(yōu)化代碼具伍,經(jīng)常會(huì)出現(xiàn)oom铆遭,優(yōu)化方式通常有:使用緩存;壓縮圖片沿猜;及時(shí)回收枚荣。
- 至于什么時(shí)候使用是手動(dòng)調(diào)用bitmap.recycle()方法,這個(gè)需要看具體場(chǎng)景了啼肩,原則是在不使用bitmap時(shí)橄妆,就要回收掉,需要注意的是祈坠,在Android2.3之前bitmap對(duì)象與像素?cái)?shù)據(jù)是分開存放的害碾,bitmap對(duì)象存在Java heap中而像素?cái)?shù)據(jù)存儲(chǔ)在Native Memory中,這時(shí)黑有必要調(diào)用recycle回收內(nèi)存赦拘,但是在2.3之后慌随,bitmap對(duì)象和像素?cái)?shù)據(jù)都是存在Heap中,通過GC就可以回收內(nèi)存躺同。
你一般在開發(fā)項(xiàng)目中都是用什么設(shè)計(jì)模式阁猜,如何來重構(gòu),優(yōu)化你的代碼蹋艺?
- 較為常用的是單例設(shè)計(jì)模式和工廠設(shè)計(jì)模式以及觀察者模式剃袍,一般需要保證對(duì)象在內(nèi)存中的唯一性時(shí)需要使用到單例模式,例如對(duì)數(shù)據(jù)庫操作的sqliteOpenHelpter的對(duì)象捎谨,工廠模式主要是為創(chuàng)建對(duì)象提供過渡接口民效,以便將創(chuàng)建的對(duì)象的具體過程屏蔽隔離起來,達(dá)到提高靈活性的目的涛救,觀察者模式定義對(duì)象間的一種一對(duì)多的依賴關(guān)系畏邢,當(dāng)一個(gè)對(duì)象的裝填發(fā)生變化時(shí),所有依賴于它的對(duì)象都得到通知并自動(dòng)更新检吆。
Android中第二次登陸實(shí)現(xiàn)自動(dòng)登錄
- 這是一個(gè)實(shí)際的案例流程舒萎,前提條件是所有用戶相關(guān)的接口都走h(yuǎn)ttps,非用戶相關(guān)的列表類數(shù)據(jù)走h(yuǎn)ttp。
- 第一次登錄的時(shí)候getUserInfo的時(shí)候帶一個(gè)長(zhǎng)效的token咧栗,該長(zhǎng)效的token用來判斷用戶是否登錄和換取短的token逆甜;
- 把長(zhǎng)效token保存到sharedPreferences中虱肄,
- 接口請(qǐng)求用長(zhǎng)效的token換取短token致板,短token服務(wù)端可以根據(jù)你的接口最后一次請(qǐng)求作為標(biāo)識(shí),超時(shí)時(shí)間為一天
- 所有接口都用短效token
- 如果返回短效token失效咏窿,執(zhí)行3步驟在直接標(biāo)識(shí)當(dāng)前接口斟或,
- 如果長(zhǎng)效token失效(用戶換設(shè)備或者超過兩周),提示用戶重新登錄集嵌。