面向?qū)ο螅?/b>
封裝:隱藏實(shí)現(xiàn)細(xì)節(jié),提高程序的復(fù)用性和維護(hù)性
繼承:子類(lèi)繼承父類(lèi),表明子類(lèi)擁有父類(lèi)的屬性和方法(注意是public protected修飾符的)
多態(tài):父類(lèi)引用指向子類(lèi)對(duì)象
Android四大組件:
Activity、Service、ContentProvider、BroadcastReceiver。
Activity生命周期:
onCreate、onStart、onResume、onPause、onStop、onDestroy、onRestart
在Service的生命周期里,常用的有:
手動(dòng)調(diào)用方法作用? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
startService()啟動(dòng)服務(wù)
stopService()關(guān)閉服務(wù)
bindService()綁定服務(wù)
unbindService()解綁服務(wù)
內(nèi)部自動(dòng)調(diào)用的方法作用
onCreat()創(chuàng)建服務(wù)
onStartCommand()開(kāi)始服務(wù)
onDestroy()銷(xiāo)毀服務(wù)
onBind()綁定服務(wù)
onUnbind()解綁服務(wù)
ContentProvider 是如何實(shí)現(xiàn)數(shù)據(jù)共享的
我們可以定義?個(gè)類(lèi)繼承?ContentProvider,然后覆寫(xiě)該類(lèi)的insert、delete、update 等?法,在 這些?法?訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)等資源。同時(shí)將我們 ContentProvider?注冊(cè)在 AndroidManifest??件中,其他應(yīng) ?需要使?的時(shí)候只需獲取 ContentResolver,然后通過(guò) ContentResolver進(jìn)行對(duì)數(shù)據(jù)庫(kù)的增刪改查
BroadCastReceiver的理解
BroadCastReceiver為廣播接收器,它用于接收廣播intent。
廣播是一種廣泛運(yùn)用在應(yīng)用程序之間傳輸信息的機(jī)制。而 BroadcastReceiver 是對(duì)發(fā)送出來(lái)的廣播進(jìn)行過(guò)濾接收并響應(yīng)的一類(lèi)組件;BroadcastReceiver 自身并不實(shí)現(xiàn)圖形用戶(hù)界面,但是當(dāng)它收到某個(gè)通知后,BroadcastReceiver可以啟動(dòng)Activity作為響應(yīng), 或者通過(guò) NotificationMananger提醒用戶(hù),或者啟動(dòng) Service 等等。
Android五大布局:
線(xiàn)性、相對(duì)、絕對(duì)、幀、網(wǎng)格
LinearLayout、RelativeLayout、FrameLayout、AbsoluteLayout、TableLayout
Android 的數(shù)據(jù)存儲(chǔ)?式
SharedPreference、XML、SQLite、?件存儲(chǔ)
Android動(dòng)畫(huà):
屬性動(dòng)畫(huà):
Android 3.0(API 11)后才提供的一種全新動(dòng)畫(huà)模式
其出現(xiàn)原因?yàn)樽饔脤?duì)象局限于View,沒(méi)有改變View的屬性,只是改變視覺(jué)效果,動(dòng)畫(huà)效果單一
{下載進(jìn)度條}使用了屬性動(dòng)畫(huà)
補(bǔ)間動(dòng)畫(huà):
補(bǔ)間動(dòng)畫(huà)由Animation類(lèi)來(lái)實(shí)現(xiàn)具體效果,包括平移(TranslateAnimation)、縮放(ScaleAnimation)、旋轉(zhuǎn)(RotateAnimation)、透明度(AlphaAnimation)四個(gè)子類(lèi),四種變化。
幀動(dòng)畫(huà):
下拉刷新時(shí)頭布局里我們使用了幀動(dòng)畫(huà)
自定義View
自定義控件的實(shí)現(xiàn)有三種方式,分別是:組合控件、自繪控件和繼承控件
自定義View的流程
1.自定義View的屬性(非必需)
2.在View的構(gòu)造方法中獲得我們自定義的屬性(非必需)
3.重寫(xiě)onMesure
4.重寫(xiě)onDraw
APP基本性能優(yōu)化:
快、穩(wěn)、省、小。
快:使用時(shí)避免出現(xiàn)卡頓,響應(yīng)速度快,減少用戶(hù)等待的時(shí)間,滿(mǎn)足用戶(hù)期望。
穩(wěn):減低 crash 率和 ANR 率,不要在用戶(hù)使用過(guò)程中崩潰和無(wú)響應(yīng)。
?。汗?jié)省流量和耗電,減少用戶(hù)使用成本,避免使用時(shí)導(dǎo)致手機(jī)發(fā)燙。
?。喊惭b包小可以降低用戶(hù)的安裝成本。
卡頓優(yōu)化
UI 繪制、應(yīng)用啟動(dòng)、頁(yè)面跳轉(zhuǎn)、事件響應(yīng)
優(yōu)化建議
布局優(yōu)化:
減少層級(jí)。合理使用 RelativeLayout 和 LinerLayout,合理使用Merge。
提高顯示速度。使用 ViewStub,它是一個(gè)看不見(jiàn)的、不占布局位置、占用資源非常小的視圖對(duì)象。
布局復(fù)用。可以通過(guò)?標(biāo)簽來(lái)提高復(fù)用。
盡可能少用wrap_content。wrap_content 會(huì)增加布局 measure 時(shí)計(jì)算成本,在已知寬高為固定值時(shí),不用wrap_content 。
刪除控件中無(wú)用的屬性。
避免過(guò)度繪制:
布局上的優(yōu)化。移除 XML 中非必須的背景,移除 Window 默認(rèn)的背景、按需顯示占位背景圖片
自定義View優(yōu)化。使用 canvas.clipRect()來(lái)幫助系統(tǒng)識(shí)別那些可見(jiàn)的區(qū)域,只有在這個(gè)區(qū)域內(nèi)才會(huì)被繪制。
啟動(dòng)優(yōu)化:
UI 布局。應(yīng)用一般都有閃屏頁(yè),優(yōu)化閃屏頁(yè)的 UI 布局,可以通過(guò) Profile GPU Rendering 檢測(cè)丟幀情況。
啟動(dòng)加載邏輯優(yōu)化??梢圆捎梅植技虞d、異步加載、延期加載策略來(lái)提高應(yīng)用啟動(dòng)速度。
數(shù)據(jù)準(zhǔn)備。數(shù)據(jù)初始化分析,加載數(shù)據(jù)可以考慮用線(xiàn)程初始化等策略。
合理的刷新機(jī)制:
盡量減少刷新次數(shù)。
盡量避免后臺(tái)有高的 CPU 線(xiàn)程運(yùn)行。
縮小刷新區(qū)域。
內(nèi)存優(yōu)化:
在 Android 系統(tǒng)中有個(gè)垃圾內(nèi)存回收機(jī)制,在虛擬機(jī)層自動(dòng)分配和釋放內(nèi)存,因此不需要在代碼中分配和釋放某一塊內(nèi)存,從應(yīng)用層面上不容易出現(xiàn)內(nèi)存泄漏和內(nèi)存溢出等問(wèn)題,但是需要內(nèi)存管理。Android 系統(tǒng)在內(nèi)存管理上有一個(gè) Generational Heap Memory 模型,內(nèi)存回收的大部分壓力不需要應(yīng)用層關(guān)心, Generational Heap Memory 有自己一套管理機(jī)制,當(dāng)內(nèi)存達(dá)到一個(gè)閾值時(shí),系統(tǒng)會(huì)根據(jù)不同的規(guī)則自動(dòng)釋放系統(tǒng)認(rèn)為可以釋放的內(nèi)存,也正是因?yàn)?Android 程序把內(nèi)存控制的權(quán)力交給了 Generational Heap Memory,一旦出現(xiàn)內(nèi)存泄漏和溢出方面的問(wèn)題,排查錯(cuò)誤將會(huì)成為一項(xiàng)異常艱難的工作。除此之外,部分 Android 應(yīng)用開(kāi)發(fā)人員在開(kāi)發(fā)過(guò)程中并沒(méi)有特別關(guān)注內(nèi)存的合理使用,也沒(méi)有在內(nèi)存方面做太多的優(yōu)化,當(dāng)應(yīng)用程序同時(shí)運(yùn)行越來(lái)越多的任務(wù),加上越來(lái)越復(fù)雜的業(yè)務(wù)需求時(shí),完全依賴(lài) Android 的內(nèi)存管理機(jī)制就會(huì)導(dǎo)致一系列性能問(wèn)題逐漸呈現(xiàn),對(duì)應(yīng)用的穩(wěn)定性和性能帶來(lái)不可忽視的影響,因此,解決內(nèi)存問(wèn)題和合理優(yōu)化內(nèi)存是非常有必要的。
內(nèi)存分配
在 Android 系統(tǒng)中,內(nèi)存分配實(shí)際上是對(duì)堆的分配和釋放。當(dāng)一個(gè) Android 程序啟動(dòng),應(yīng)用進(jìn)程都是從一個(gè)叫做 Zygote 的進(jìn)程衍生出來(lái),系統(tǒng)啟動(dòng) Zygote 進(jìn)程后,為了啟動(dòng)一個(gè)新的應(yīng)用程序進(jìn)程,系統(tǒng)會(huì)衍生 Zygote 進(jìn)程生成一個(gè)新的進(jìn)程,然后在新的進(jìn)程中加載并運(yùn)行應(yīng)用程序的代碼。其中,大多數(shù)的 RAM pages 被用來(lái)分配給Framework 代碼,同時(shí)促使 RAM 資源能夠在應(yīng)用所有進(jìn)程之間共享。
但是為了整個(gè)系統(tǒng)的內(nèi)存控制需要,Android 系統(tǒng)會(huì)為每一個(gè)應(yīng)用程序都設(shè)置一個(gè)硬性的 Dalvik Heap Size 最大限制閾值,整個(gè)閾值在不同設(shè)備上會(huì)因?yàn)?RAM 大小不同而有所差異。如果應(yīng)用占用內(nèi)存空間已經(jīng)接近整個(gè)閾值時(shí),再?lài)L試分配內(nèi)存的話(huà),就很容易引起內(nèi)存溢出的錯(cuò)誤。
內(nèi)存回收機(jī)制
我們需要知道的是,在 Java 中內(nèi)存被分為三個(gè)區(qū)域:Young Generation(年輕代)、Old Generation(年老代)、Permanent Generation(持久代)。最近分配的對(duì)象會(huì)存放在 Young Generation 區(qū)域。對(duì)象在某個(gè)時(shí)機(jī)觸發(fā) GC 回收垃圾,而沒(méi)有回收的就根據(jù)不同規(guī)則,有可能被移動(dòng)到 Old Generation,最后累積一定時(shí)間在移動(dòng)到 Permanent Generation 區(qū)域。系統(tǒng)會(huì)根據(jù)內(nèi)存中不同的內(nèi)存數(shù)據(jù)類(lèi)型分別執(zhí)行不同的 GC 操作。GC 通過(guò)確定對(duì)象是否被活動(dòng)對(duì)象引用來(lái)確定是否收集對(duì)象,進(jìn)而動(dòng)態(tài)回收無(wú)任何引用的對(duì)象占據(jù)的內(nèi)存空間。但需要注意的是頻繁的 GC 會(huì)增加應(yīng)用的卡頓情況,影響應(yīng)用的流暢性,因此需要盡量減少系統(tǒng) GC 行為,以便提高應(yīng)用的流暢度,減小卡頓發(fā)生的概率。
常見(jiàn)內(nèi)存泄漏場(chǎng)景
如果在內(nèi)存泄漏發(fā)生后再去找原因并修復(fù)會(huì)增加開(kāi)發(fā)的成本,最好在編寫(xiě)代碼時(shí)就能夠很好地考慮內(nèi)存問(wèn)題,寫(xiě)出更高質(zhì)量的代碼,這里列出一些常見(jiàn)的內(nèi)存泄漏場(chǎng)景,在以后的開(kāi)發(fā)過(guò)程中需要避免這類(lèi)問(wèn)題。
資源性對(duì)象未關(guān)閉。比如Cursor、File文件等,往往都用了一些緩沖,在不使用時(shí),應(yīng)該及時(shí)關(guān)閉它們。
注冊(cè)對(duì)象未注銷(xiāo)。比如事件注冊(cè)后未注銷(xiāo),會(huì)導(dǎo)致觀(guān)察者列表中維持著對(duì)象的引用。
類(lèi)的靜態(tài)變量持有大數(shù)據(jù)對(duì)象。
非靜態(tài)內(nèi)部類(lèi)的靜態(tài)實(shí)例。
Handler臨時(shí)性?xún)?nèi)存泄漏。如果Handler是非靜態(tài)的,容易導(dǎo)致 Activity 或 Service 不會(huì)被回收。
容器中的對(duì)象沒(méi)清理造成的內(nèi)存泄漏。
WebView。WebView 存在著內(nèi)存泄漏的問(wèn)題,在應(yīng)用中只要使用一次 WebView,內(nèi)存就不會(huì)被釋放掉。
優(yōu)化內(nèi)存空間
沒(méi)有內(nèi)存泄漏,并不意味著內(nèi)存就不需要優(yōu)化,在移動(dòng)設(shè)備上,由于物理設(shè)備的存儲(chǔ)空間有限,Android 系統(tǒng)對(duì)每個(gè)應(yīng)用進(jìn)程也都分配了有限的堆內(nèi)存,因此使用最小內(nèi)存對(duì)象或者資源可以減小內(nèi)存開(kāi)銷(xiāo),同時(shí)讓GC 能更高效地回收不再需要使用的對(duì)象,讓?xiě)?yīng)用堆內(nèi)存保持充足的可用內(nèi)存,使應(yīng)用更穩(wěn)定高效地運(yùn)行。常見(jiàn)做法如下:
對(duì)象引用。強(qiáng)引用、軟引用、弱引用、虛引用四種引用類(lèi)型,根據(jù)業(yè)務(wù)需求合理使用不同,選擇不同的引用類(lèi)型。
減少不必要的內(nèi)存開(kāi)銷(xiāo)。注意自動(dòng)裝箱,增加內(nèi)存復(fù)用,比如有效利用系統(tǒng)自帶的資源、視圖復(fù)用、對(duì)象池、Bitmap對(duì)象的復(fù)用。
使用最優(yōu)的數(shù)據(jù)類(lèi)型。比如針對(duì)數(shù)據(jù)類(lèi)容器結(jié)構(gòu),可以使用ArrayMap數(shù)據(jù)結(jié)構(gòu),避免使用枚舉類(lèi)型,使用緩存Lrucache等等。
圖片內(nèi)存優(yōu)化??梢栽O(shè)置位圖規(guī)格,根據(jù)采樣因子做壓縮,用一些圖片緩存方式對(duì)圖片進(jìn)行管理等等。
穩(wěn)定性?xún)?yōu)化
Android 應(yīng)用的穩(wěn)定性定義很寬泛,影響穩(wěn)定性的原因很多,比如內(nèi)存使用不合理、代碼異常場(chǎng)景考慮不周全、代碼邏輯不合理等,都會(huì)對(duì)應(yīng)用的穩(wěn)定性造成影響。其中最常見(jiàn)的兩個(gè)場(chǎng)景是:Crash 和 ANR,這兩個(gè)錯(cuò)誤將會(huì)使得程序無(wú)法使用,比較常用的解決方式如下:
提高代碼質(zhì)量。比如開(kāi)發(fā)期間的代碼審核,看些代碼設(shè)計(jì)邏輯,業(yè)務(wù)合理性等。
代碼靜態(tài)掃描工具。常見(jiàn)工具有Android Lint、Findbugs、Checkstyle、PMD等等。
Crash監(jiān)控。把一些崩潰的信息,異常信息及時(shí)地記錄下來(lái),以便后續(xù)分析解決。
Crash上傳機(jī)制。在Crash后,盡量先保存日志到本地,然后等下一次網(wǎng)絡(luò)正常時(shí)再上傳日志信息。
ListView優(yōu)化:
ListView?的優(yōu)化有多種多樣的策略。在我們的項(xiàng)?中主要做了如下優(yōu)化。
1、重? ConvertView,2、給 ConvertView?綁定ViewHolder,3、分頁(yè)加載數(shù)據(jù),4、使?緩存。前兩個(gè)是通?的解決?案,后兩個(gè)是針對(duì)我們業(yè)務(wù)的個(gè)性化解決?案。我們的數(shù)據(jù)來(lái)?服務(wù)端,如果服務(wù)端有 1000?條數(shù)據(jù) 的話(huà),我們客戶(hù)端不可能傻?式的?次性? ListView?把這些數(shù)據(jù)全部加載進(jìn)來(lái),因此我們就?分頁(yè)加載 數(shù)據(jù),每次加載 20?頁(yè),當(dāng)?戶(hù)請(qǐng)求更多的時(shí)候再獲取更多數(shù)據(jù),?絡(luò)的訪(fǎng)問(wèn)就算?速再快也多多少少會(huì)有 ?定的延遲,因此我們的?絡(luò)請(qǐng)求是異步處理的,同時(shí)從?絡(luò)加載來(lái)的數(shù)據(jù)使?了 2?級(jí)緩存來(lái)處理,第?級(jí) 是內(nèi)存級(jí)別的緩存,第?級(jí)是本地?件的緩存。當(dāng) ListView?加載數(shù)據(jù)的時(shí)候?先從內(nèi)存中找,如果找不 到再去本地?件中找,只有都找不到的情況下才去請(qǐng)求?絡(luò)。
MVP模式
MVP 模式將Activity 中的業(yè)務(wù)邏輯全部分離出來(lái),讓Activity 只做 UI 邏輯的處理,所有跟Android API無(wú)關(guān)的業(yè)務(wù)邏輯由 Presenter 層來(lái)完成。
將業(yè)務(wù)處理分離出來(lái)后最明顯的好處就是管理方便,但是缺點(diǎn)就是增加了代碼量。
在MVP 架構(gòu)中跟MVC類(lèi)似的是同樣也分為三層。
Activity 和Fragment 視為View層,負(fù)責(zé)處理 UI。
Presenter 為業(yè)務(wù)處理層,既能調(diào)用UI邏輯,又能請(qǐng)求數(shù)據(jù),該層為純Java類(lèi),不涉及任何Android API。
Model 層中包含著具體的數(shù)據(jù)請(qǐng)求,數(shù)據(jù)源。
三層之間調(diào)用順序?yàn)関iew->presenter->model,為了調(diào)用安全著想不可反向調(diào)用!不可跨級(jí)調(diào)用!
Android多線(xiàn)程:
1. Handler+Thread
2. AsyncTask
3. ThreadPoolExecutor
4. IntentService
Handler+Thread
Android主線(xiàn)程包含一個(gè)消息隊(duì)列(MessageQueue),該消息隊(duì)列里面可以存入一系列的Message或Runnable對(duì)象。通過(guò)一個(gè)Handler你可以往這個(gè)消息隊(duì)列發(fā)送Message或者Runnable對(duì)象,并且處理這些對(duì)象。每次你新創(chuàng)建一個(gè)Handle對(duì)象,它會(huì)綁定于創(chuàng)建它的線(xiàn)程(也就是UI線(xiàn)程)以及該線(xiàn)程的消息隊(duì)列,從這時(shí)起,這個(gè)handler就會(huì)開(kāi)始把Message或Runnable對(duì)象傳遞到消息隊(duì)列中,并在它們出隊(duì)列的時(shí)候執(zhí)行它們。
Handler可以把一個(gè)Message對(duì)象或者Runnable對(duì)象壓入到消息隊(duì)列中,進(jìn)而在UI線(xiàn)程中獲取Message或者執(zhí)行Runnable對(duì)象,Handler把壓入消息隊(duì)列有兩類(lèi)方式,Post和sendMessage:
Post方式:
Post允許把一個(gè)Runnable對(duì)象入隊(duì)到消息隊(duì)列中。它的方法有:
post(Runnable)/postAtTime(Runnable,long)/postDelayed(Runnable,long)
對(duì)于Handler的Post方式來(lái)說(shuō),它會(huì)傳遞一個(gè)Runnable對(duì)象到消息隊(duì)列中,在這個(gè)Runnable對(duì)象中,重寫(xiě)run()方法。一般在這個(gè)run()方法中寫(xiě)入需要在UI線(xiàn)程上的操作。
sendMessage:
sendMessage允許把一個(gè)包含消息數(shù)據(jù)的Message對(duì)象壓入到消息隊(duì)列中。它的方法有:sendEmptyMessage(int)/sendMessage(Message)/sendMessageAtTime(Message,long)/sendMessageDelayed(Message,long)
Handler如果使用sendMessage的方式把消息入隊(duì)到消息隊(duì)列中,需要傳遞一個(gè)Message對(duì)象,而在Handler中,需要重寫(xiě)handleMessage()方法,用于獲取工作線(xiàn)程傳遞過(guò)來(lái)的消息,此方法運(yùn)行在UI線(xiàn)程上。Message是一個(gè)final類(lèi),所以不可被繼承。
優(yōu)缺點(diǎn):
1. Handler用法簡(jiǎn)單明了,可以將多個(gè)異步任務(wù)更新UI的代碼放在一起,清晰明了
2. 處理單個(gè)異步任務(wù)代碼略顯多
適用范圍:
1. 多個(gè)異步任務(wù)的更新UI
AsyncTask
AsyncTask是android提供的輕量級(jí)的異步類(lèi),可以直接繼承AsyncTask,在類(lèi)中實(shí)現(xiàn)異步操作,并提供接口反饋當(dāng)前異步執(zhí)行的程度(可以通過(guò)接口實(shí)現(xiàn)UI進(jìn)度更新),最后反饋執(zhí)行的結(jié)果給UI主線(xiàn)程。
AsyncTask通過(guò)一個(gè)阻塞隊(duì)列BlockingQuery<Runnable>存儲(chǔ)待執(zhí)行的任務(wù),利用靜態(tài)線(xiàn)程池THREAD_POOL_EXECUTOR提供一定數(shù)量的線(xiàn)程,默認(rèn)128個(gè)。在Android 3.0以前,默認(rèn)采取的是并行任務(wù)執(zhí)行器,3.0以后改成了默認(rèn)采用串行任務(wù)執(zhí)行器,通過(guò)靜態(tài)串行任務(wù)執(zhí)行器SERIAL_EXECUTOR控制任務(wù)串行執(zhí)行,循環(huán)取出任務(wù)交給THREAD_POOL_EXECUTOR中的線(xiàn)程執(zhí)行,執(zhí)行完一個(gè),再執(zhí)行下一個(gè)。
IntentService
IntentService繼承自Service,是一個(gè)經(jīng)過(guò)包裝的輕量級(jí)的Service,用來(lái)接收并處理通過(guò)Intent傳遞的異步請(qǐng)求??蛻?hù)端通過(guò)調(diào)用startService(Intent)啟動(dòng)一個(gè)IntentService,利用一個(gè)work線(xiàn)程依次處理順序過(guò)來(lái)的請(qǐng)求,處理完成后自動(dòng)結(jié)束Service。
特點(diǎn)
1. 一個(gè)可以處理異步任務(wù)的簡(jiǎn)單Service