天天保持好的精神狀態和好的行爲習慣java
週六:星巴克一杯咖啡,看一下午書(最近在看東野圭吾的黎明之街)緩解一下週一到週五緊張的神經。慢慢的品嚐美食。晚上看個電影(古仔演反派仍是帥)
週日:窩在家裏追一天劇,出門散散步
更多完整項目下載。未完待續。源碼。圖文知識後續上傳github。
能夠點擊關於我 聯繫我獲取
VX:mm14525201314
因爲面的Android崗位,須要準備一些Java和Android方面的知識,有不少的文章都會去介紹怎麼去複習基礎的知識或者進階知識,或者是閱讀一些經典的面試數據。你們能夠根據網上的文章和一些數據梳理一個本身的知識體系,將一個一個知識點造成點再到面,這樣能更加深入的理解,並且有本身的側重點,我就列舉一下個人準備的方向:linux
onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDetroy()
android
service
啓動方式有兩種ios
startService()
方式進行啓動bindService()
方式進行啓動。不一樣的啓動方式他們的生命週期是不同.git
經過startService()
這種方式啓動的service
生命週期是這樣:
調用startService() --> onCreate()--> onStartConmon()--> onDestroy()。
這種方式啓動的話,須要注意一下幾個問題:github
startService
被調用之後,屢次在調用startService(),onCreate()
方法也只會被調用一次,而onStartConmon()
會被屢次調用,當咱們調用stopService()
的時候,onDestroy()
就會被調用,從而銷燬服務。startService
啓動時候,經過intent傳值,在onStartConmon()
方法中獲取值的時候,必定要先判斷intent是否爲null。經過bindService()
方式進行綁定,這種方式綁定service
生命週期:
`bindService-->onCreate()-->onBind()-->unBind()-->onDestroy()
bindservice 這種方式進行啓動service好處是更加便利activity中操做service,若是要在activity中調用,在須要在activity獲取
ServiceConnection對象,經過
ServiceConnection`來獲取service中內部類的類對象,而後經過這個類對象就能夠調用類中的方法,固然這個類須要繼承Binder對象面試
app
啓動的過程有兩種狀況算法
launcher
上點擊相應的應用圖標startActivity
來啓動一個新的activity。
咱們建立一個新的項目,默認的根activity
都是MainActivity
,而全部的activity
都是保存在堆棧中的,咱們啓動一個新的activity就會放在上一個activity上面,而咱們從桌面點擊應用圖標的時候,因爲launcher
自己也是一個應用,當咱們點擊圖標的時候,系統就會調用startActivitySately()
,通常狀況下,咱們所啓動的activity的相關信息都會保存在intent中,好比action,category
等等。咱們在安裝這個應用的時候,系統也會啓動一個PackaManagerService
的管理服務,這個管理服務會對AndroidManifest.xml
文件進行解析,從而獲得應用程序中的相關信息,好比service,activity,Broadcast
等等,而後得到相關組件的信息。當咱們點擊應用圖標的時候,就會調用startActivitySately()
方法,而這個方法內部則是調用startActivty()
,而startActivity()
方法最終仍是會調用startActivityForResult()
這個方法。而在startActivityForResult()
這個方法。由於startActivityForResult()
方法是有返回結果的,因此係統就直接給一個-1,就表示不須要結果返回了。而startActivityForResult()
這個方法實際是經過Instrumentation
類中的execStartActivity()
方法來啓動activity,Instrumentation
這個類主要做用就是監控程序和系統之間的交互。而在這個execStartActivity()
方法中會獲取ActivityManagerService
的代理對象,經過這個代理對象進行啓動activity。啓動會就會調用一個checkStartActivityResult()
方法,若是說沒有在配置清單中配置有這個組件,就會在這個方法中拋出異常了。固然最後是調用的是Application.scheduleLaunchActivity()
進行啓動activity,而這個方法中經過獲取獲得一個ActivityClientRecord
對象,而這個ActivityClientRecord
經過handler來進行消息的發送,系統內部會將每個activity組件使用ActivityClientRecord
對象來進行描述,而ActivityClientRecord
對象中保存有一個LoaderApk
對象,經過這個對象調用handleLaunchActivity
來啓動activity組件,而頁面的生命週期方法也就是在這個方法中進行調用。設計模式
此處延伸:什麼狀況下用動態註冊api
Broadcast
廣播,註冊方式主要有兩種.
靜態註冊
,也可成爲常駐型廣播,這種廣播須要在Androidmanifest.xml
中進行註冊,這中方式註冊的廣播,不受頁面生命週期的影響,即便退出了頁面,也能夠收到廣播這種廣播通常用於想開機自啓動啊等等,因爲這種註冊的方式的廣播是常駐型廣播,因此會佔用CPU的資源。動態註冊
,而動態註冊的話,是在代碼中註冊的,這種註冊方式也叫很是駐型廣播,受到生命週期的影響,退出頁面後,就不會收到廣播,咱們一般運用在更新UI方面。這種註冊方式優先級較高。最後須要解綁,否會會內存泄露廣播是分爲有序廣播和無序廣播。
此處延伸:Volley
裏用的哪一種請求方式
首先HttpClient
和HttpUrlConnection
這兩種方式都支持Https
協議,都是以流的形式進行上傳或者下載數據,也能夠說是以流的形式進行數據的傳輸,還有ipv6
,以及鏈接池等功能。HttpClient
這個擁有很是多的API,因此若是想要進行擴展的話,而且不破壞它的兼容性的話,很難進行擴展,也就是這個緣由,Google在Android6.0的時候,直接就棄用了這個HttpClient.
而HttpUrlConnection
相對來講就是比較輕量級了,API比較少,容易擴展,而且可以知足Android大部分的數據傳輸。比較經典的一個框架volley,在Android 2.3版本之前都是使用Android HttpClient,
在Android 2.3之後就使用了HttpUrlConnection
。
Java虛擬機:
java
虛擬機基於棧。基於棧的機器必須使用指令來載入和操做棧上數據,所需指令更多更多。
java
虛擬機運行的是java
字節碼。java
類會被編譯成一個或多個字節碼.class
文件.
Dalvik虛擬機:
dalvik
虛擬機是基於寄存器的Dalvik
運行的是自定義的.dex
字節碼格式。java類被編譯成.class文件後,會經過一個dx
工具將全部的.class文件轉換成一個.dex
文件,而後dalvik
虛擬機會從其中讀取指令和數據.
全部android應用的線程都是對應一個linux
線程,都運行在本身的沙盒中,不一樣的應用在不一樣的進程中運行。每一個android dalvik
應用程序都被賦予了一個獨立的linux PID(app_*)
此處延伸:進程的優先級是什麼
當前業界的Android進程保活手段主要分爲黑、白、灰三種,其大體的實現思路以下:
黑色保活:
不一樣的app進程,用廣播相互喚醒,包括利用系統提供的廣播進行喚醒.
黑色保活
所謂黑色保活,就是利用不一樣的app進程使用廣播來進行相互喚醒。舉個3個比較常見的場景:
SDK
也會喚醒相應的app進程,如微信sdk
會喚醒微信,支付寶sdk
會喚醒支付寶。由此發散開去,就會直接觸發了下面的 場景3白色保活
白色保活手段很是簡單,就是調用系統api啓動一個前臺的Service進程,這樣會在系統的通知欄生成一個Notification,用來讓用戶知道有這樣一個app在運行着,哪怕當前的app退到了後臺。
灰色保活
灰色保活,這種保活手段是應用範圍最普遍。它是利用系統的漏洞來啓動一個前臺的Service進程,與普通的啓動方式區別在於,它不會在系統通知欄處出現一個Notification
,看起來就如同運行着一個後臺Service
進程同樣。這樣作帶來的好處就是,用戶沒法察覺到你運行着一個前臺進程(由於看不到Notification
),但你的進程優先級又是高於普通後臺進程的。那麼如何利用系統的漏洞呢,大體的實現思路和代碼以下:
思路一:API < 18
,啓動前臺Service
時直接傳入new Notification()
;
思路二:API >= 18
,同時啓動兩個id相同的前臺Service
,而後再將後啓動的Service作stop處理
熟悉Android系統的童鞋都知道,系統出於體驗和性能上的考慮,app在退到後臺時系統並不會真正的kill掉這個進程,而是將其緩存起來。打開的應用越多,後臺緩存的進程也越多。在系統內存不足的狀況下,系統開始依據自身的一套進程回收機制來判斷要kill掉哪些進程,以騰出內存來供給須要的app。這套殺進程回收內存的機制就叫Low Memory Killer
,它是基於Linux內核的OOM Killer(Out-Of-Memory killer)
機制誕生。
進程的重要性,劃分5級:
(Foreground process)
(Visible process)
(Service process)
(Background process)
(Empty process)
瞭解完Low Memory Killer,再科普一下oom_adj
。什麼是oom_adj
?它是 linux
內核分配給每一個系統進程的一個值,表明進程的優先級,進程回收機制就是根據這個優先級來決定是否進行回收。對於oom_adj
的做用,你只須要記住如下幾點便可:
進程的oom_adj
越大,表示此進程優先級越低,越容易被殺回收;越小,表示進程優先級越高,越不容易被殺回收
普通app進程的oom_adj>=0
,系統進程的oom_adj
纔可能<0
有些手機廠商把這些知名的app放入了本身的白名單中,保證了進程不死來提升用戶體驗(如微信、QQ、陌陌都在小米的白名單中)。若是從白名單中移除,他們終究仍是和普通app同樣躲避不了被殺的命運,爲了儘可能避免被殺,仍是老老實實去作好優化工做吧。
因此,進程保活的根本方案終究仍是回到了性能優化上,進程永生不死終究是個徹頭徹尾的僞命題!
Context是一個抽象基類。在翻譯爲上下文,也能夠理解爲環境,是提供一些程序的運行環境基礎信息。Context下有兩個子類,ContextWrapper
是上下文功能的封裝類,而ContextImpl
則是上下文功能的實現類。而ContextWrapper
又有三個直接的子類, ContextThemeWrapper
、Service
和Application
。其中,ContextThemeWrapper
是一個帶主題的封裝類,而它有一個直接子類就是Activity,因此Activity和Service以及Application的Context是不同的,只有Activity須要主題,Service不須要主題。
Context一共有三種類型,分別是Application
、Activity
和Service
。這三個類雖然分別各類承擔着不一樣的做用,但它們都屬於Context的一種,而它們具體Context的功能則是由ContextImpl
類去實現的,所以在絕大多數場景下,Activity、Service和Application這三種類型的Context都是能夠通用的。
不過有幾種場景比較特殊,好比啓動Activity,還有彈出Dialog。出於安全緣由的考慮,Android是不容許Activity或Dialog憑空出現的,一個Activity的啓動必需要創建在另外一個Activity的基礎之上,也就是以此造成的返回棧。而Dialog則必須在一個Activity上面彈出(除非是System Alert類型的Dialog),所以在這種場景下,咱們只能使用Activity類型的Context,不然將會出錯。
getApplicationContext()
和getApplication()
方法獲得的對象都是同一個application對象,只是對象的類型不同。
Context數量 = Activity數量 + Service數量 + 1 (1爲Application)
這個問題真的很很差回答。因此這裏先來個算是比較恰當的比喻來形容下它們的關係吧。Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖)LayoutInflater
像剪刀,Xml
配置像窗花圖紙。
1:Activity構造的時候會初始化一個Window,準確的說是PhoneWindow
。
2:這個PhoneWindow
有一個ViewRoot
,這個ViewRoot
是一個View或者說ViewGroup
,是最初始的根視圖。
3:ViewRoot
經過addView
方法來一個個的添加View。好比TextView
,Button等
4:這些View的事件監聽,是由WindowManagerService
來接受消息,而且回調Activity函數。好比onClickListener
,onKeyDown
等。
此處延伸:棧(First In Last Out)
與隊列(First In First Out)
的區別
棧與隊列的區別:
standard 模式
這是默認模式,每次激活Activity時都會建立Activity實例,並放入任務棧中。使用場景:大多數Activity。
singleTop 模式
若是在任務的棧頂正好存在該Activity的實例,就重用該實例( 會調用實例的onNewIntent()),不然就會建立新的實例並放入棧頂,即便棧中已經存在該Activity的實例,只要不在棧頂,都會建立新的實例。使用場景如新聞類或者閱讀類App的內容頁面。
singleTask 模式
若是在棧中已經有該Activity的實例,就重用該實例(會調用實例的onNewIntent()
)。重用時,會讓該實例回到棧頂,所以在它上面的實例將會被移出棧。若是棧中不存在該實例,將會建立新的實例放入棧中。使用場景如瀏覽器的主界面。無論從多少個應用啓動瀏覽器,只會啓動主界面一次,其他狀況都會走onNewIntent
,而且會清空主界面上面的其餘頁面。
singleInstance 模式
在一個新棧中建立該Activity的實例,並讓多個應用共享該棧中的該Activity實例。一旦該模式的Activity實例已經存在於某個棧中,任何應用再激活該Activity時都會重用該棧中的實例( 會調用實例的 onNewIntent()
)。其效果至關於多個應用共享一個應用,無論誰激活該Activity 都會進入同一個應用中。使用場景如鬧鈴提醒,將鬧鈴提醒與鬧鈴設置分離。singleInstance
不要用於中間頁面,若是用於中間頁面,跳轉會有問題,好比:A -> B (singleInstance) -> C
,徹底退出後,在此啓動,首先打開的是B。
自定義控件:
一、組合控件。這種自定義控件不須要咱們本身繪製,而是使用原生控件組合成的新控件。如標題欄。
二、繼承原有的控件。這種自定義控件在原生控件提供的方法外,能夠本身添加一些方法。如製做圓角,圓形圖片。
三、徹底自定義控件:這個View上所展示的內容所有都是咱們本身繪製出來的。好比說製做水波紋進度條。
View的繪製流程:OnMeasure()——>OnLayout()——>OnDraw()
第一步:OnMeasure()
:測量視圖大小。從頂層父View到子View遞歸調用measure方法,measure方法又回調OnMeasure。
第二步:OnLayout()
:肯定View位置,進行頁面佈局。從頂層父View向子View的遞歸調用view.layout方法的過程,即父View根據上一步measure子View所獲得的佈局大小和佈局參數,將子View放在合適的位置上。
第三步:OnDraw()
:繪製視圖。ViewRoot
建立一個Canvas對象,而後調用OnDraw()
。
六個步驟:
1.Touch
事件分發中只有兩個主角:ViewGroup
和View
。
ViewGroup
包含onInterceptTouchEvent
、dispatchTouchEvent
、onTouchEvent
三個相關事件。
View
包含dispatchTouchEvent
、onTouchEvent
兩個相關事件。
其中ViewGroup
又繼承於View。
2.ViewGroup
和View
組成了一個樹狀結構,根節點爲Activity內部包含的一個ViewGroup
。
3.觸摸事件由Action_Down、Action_Move、Aciton_UP
組成,其中一次完整的觸摸事件中,Down和Up都只有一個,Move有若干個,能夠爲0個。
4.當Acitivty
接收到Touch事件時,將遍歷子View進行Down事件的分發。ViewGroup
的遍歷能夠當作是遞歸的。分發的目的是爲了找到真正要處理本次完整觸摸事件的View,這個View會在onTouchuEvent
結果返回true。
5.當某個子View返回true時,會停止Down事件的分發,同時在ViewGroup
中記錄該子View。接下去的Move和Up事件將由該子View直接進行處理。因爲子View是保存在ViewGroup
中的,多層ViewGroup
的節點結構時,上級ViewGroup
保存的會是真實處理事件的View所在的ViewGroup
對象:如ViewGroup0-ViewGroup1-TextView
的結構中,TextView
返回了true,它將被保存在ViewGroup1
中,而ViewGroup1
也會返回true,被保存在ViewGroup0
中。當Move和UP事件來時,會先從ViewGroup0
傳遞至ViewGroup1
,再由ViewGroup1
傳遞至TextView
。
6.當ViewGroup
中全部子View都不捕獲Down事件時,將觸發ViewGroup
自身的onTouch
事件。觸發的方式是調用super.dispatchTouchEvent
函數,即父類View的dispatchTouchEvent
方法。在全部子View都不處理的狀況下,觸發Acitivity的onTouchEvent
方法。
7.onInterceptTouchEvent
有兩個做用:
ViewGroup
捕獲Up和Move事件。onSaveInstanceState(Bundle)
會在activity轉入後臺狀態以前被調用,也就是onStop()
方法以前,onPause
方法以後被調用;
幀動畫:
指經過指定每一幀的圖片和播放時間,有序的進行播放而造成動畫效果,好比想聽的律動條。
補間動畫:
指經過指定View的初始狀態、變化時間、方式,經過一系列的算法去進行圖形變換,從而造成動畫效果,主要有Alpha、Scale、Translate、Rotate四種效果。
注意:只是在視圖層實現了動畫效果,並無真正改變View的屬性,好比滑動列表,改變標題欄的透明度。
屬性動畫:
在Android3.0的時候才支持,經過不斷的改變View的屬性,不斷的重繪而造成動畫效果。相比於視圖動畫,View的屬性是真正改變了。好比view的旋轉,放大,縮小。
Android跨進程通訊,像intent,contentProvider.廣播,service均可以跨進程通訊。
intent:
這種跨進程方式並非訪問內存的形式,它須要傳遞一個uri,好比說打電話。
contentProvider:
這種形式,是使用數據共享的形式進行數據共享。
service:
遠程服務,好比aidl
廣播:
廣播 包含靜態廣播,動態廣播。
此處延伸:簡述Binder
AIDL:
每個進程都有本身的Dalvik VM
實例,都有本身的一塊獨立的內存,都在本身的內存上存儲本身的數據,執行着本身的操做,都在本身的那片狹小的空間裏過完本身的一輩子。而aidl
就相似與兩個進程之間的橋樑,使得兩個進程之間能夠進行數據的傳輸,跨進程通訊有多種選擇,好比BroadcastReceiver
, Messenger
等,可是 BroadcastReceiver
佔用的系統資源比較多,若是是頻繁的跨進程通訊的話顯然是不可取的;Messenger進行跨進程通訊時請求隊列是同步進行的,沒法併發執行。
Binder機制簡單理解:
在Android系統的Binder機制中,是有Client,Service,ServiceManager,Binder
驅動程序組成的,其中Client,service,Service Manager
運行在用戶空間,Binder驅動程序是運行在內核空間的。而Binder就是把這4種組件粘合在一塊的粘合劑,其中核心的組件就是Binder驅動程序,Service Manager
提供輔助管理的功能,而Client
和Service
正是在Binder驅動程序和Service Manager
提供的基礎設施上實現C/S 之間的通訊。其中Binder驅動程序提供設備文件/dev/binder
與用戶控件進行交互,
Client、Service,Service Manager
經過open
和ioctl
文件操做相應的方法與Binder驅動程序進行通訊。而Client
和Service
之間的進程間通訊是經過Binder驅動程序間接實現的。而Binder Manager是一個守護進程,用來管理Service,並向Client提供查詢Service接口的能力。
Android中主線程是不能進行耗時操做的,子線程是不能進行更新UI的。因此就有了handler,它的做用就是實現線程之間的通訊。
handler整個流程中,主要有四個對象,handler,Message,MessageQueue,Looper
。當應用建立的時候,就會在主線程中建立handler對象,
咱們經過要傳送的消息保存到Message
中,handler經過調用sendMessage
方法將Message發送到MessageQueue
中,Looper
對象就會不斷的調用loop()方法
不斷的從MessageQueue
中取出Message交給handler進行處理。從而實現線程之間的通訊。
在Android系統的Binder機制中,是有Client,Service,ServiceManager,Binder
驅動程序組成的,其中Client,service,Service Manager
運行在用戶空間,Binder驅動程序是運行在內核空間的。而Binder就是把這4種組件粘合在一塊的粘合劑,其中核心的組件就是Binder驅動程序,Service Manager提供輔助管理的功能,而Client和Service正是在Binder驅動程序和Service Manager提供的基礎設施上實現C/S之間的通訊。其中Binder驅動程序提供設備文件/dev/binder
與用戶控件進行交互,Client、Service,Service Manager
經過open和ioctl文件操做相應的方法與Binder驅動程序進行通訊。而Client和Service之間的進程間通訊是經過Binder驅動程序間接實現的。而Binder Manager是一個守護進程,用來管理Service,並向Client提供查詢Service接口的能力。
咱們知道Java虛擬機 —— JVM
是加載類的class文件的,而Android虛擬機——Dalvik/ART VM
是加載類的dex
文件,而他們加載類的時候都須要ClassLoader,ClassLoader
有一個子BaseDexClassLoader
,而BaseDexClassLoader
下有一個數組——DexPathList
,是用來存放dex
文件,當BaseDexClassLoader
經過調用findClass
方法時,實際上就是遍歷數組,找到相應的dex
文件,找到,則直接將它return。而熱修復的解決方法就是將新的dex
添加到該集合中,而且是在舊的dex
的前面,因此就會優先被取出來而且return返回。
OOM
)和內存泄露(對象沒法被回收)的區別。LeakCanary
內存溢出out of memory
:
是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory
;
好比申請了一個integer
,但給它存了long
才能存下的數,那就是內存溢出。內存溢出通俗的講就是內存不夠用。
內存泄露memory leak
:
是指程序在申請內存後,沒法釋放已申請的內存空間,一次內存泄露危害能夠忽略,但內存泄露堆積後果很嚴重,不管多少內存,早晚會被佔光
內存泄露緣由:
1、Handler 引發的內存泄漏。
解決:將Handler聲明爲靜態內部類,就不會持有外部類SecondActivity
的引用,其生命週期就和外部類無關,
若是Handler裏面須要context的話,能夠經過弱引用方式引用外部類
2、單例模式引發的內存泄漏。
解決:Context
是ApplicationContext
,因爲ApplicationContext
的生命週期是和app一致的,不會致使內存泄漏
3、非靜態內部類建立靜態實例引發的內存泄漏。
解決:把內部類修改成靜態的就能夠避免內存泄漏了
4、非靜態匿名內部類引發的內存泄漏。
解決:將匿名內部類設置爲靜態的。
5、註冊/反註冊未成對使用引發的內存泄漏。
註冊廣播接受器、EventBus
等,記得解綁。
6、資源對象沒有關閉引發的內存泄漏。
在這些資源不使用的時候,記得調用相應的相似close()、destroy()、recycler()、release()
等方法釋放。
7、集合對象沒有及時清理引發的內存泄漏。
一般會把一些對象裝入到集合中,當不使用的時候必定要記得及時清理集合,讓相關對象再也不被引用。
Fragment
中調用另一個Fragment
中的方法字體使用sp
,dp
,多使用match_parent,wrap_content,weight
圖片資源,不一樣圖片的的分辨率,放在相應的文件夾下可以使用百分比代替。
app優化:
工具:Hierarchy Viewer 分析佈局
工具:TraceView測試分析耗時
App啓動優化
佈局優化
響應優化
內存優化
電池使用優化
網絡優化
App啓動的方式有三種:
冷啓動:
App沒有啓動過或App進程被killed, 系統中不存在該App進程, 此時啓動App即爲冷啓動。
熱啓動:
熱啓動意味着你的App進程只是處於後臺, 系統只是將其從後臺帶到前臺, 展現給用戶。
介於冷啓動和熱啓動之間,
通常來講在如下兩種狀況下發生:
(1)用戶back
退出了App
, 而後又啓動.
App進程可能還在運行, 可是activity須要重建。
(2)用戶退出App後, 系統可能因爲內存緣由將App殺死, 進程和activity都須要重啓, 可是能夠在onCreate
中將被動殺死鎖保存的狀態(saved instance state)
恢復。
啓動優化:
Application的onCreate
(特別是第三方SDK初始化),首屏Activity的渲染都不要進行耗時操做,若是有,就能夠放到子線程或者IntentService
中。
佈局優化
儘可能不要過於複雜的嵌套。可使用<include>,<merge>,<ViewStub>
響應優化
Android系統每隔16ms會發出VSYNC信號重繪咱們的界面(Activity)。
頁面卡頓的緣由:
(1)過於複雜的佈局.
(2)UI線程的複雜運算
(3)頻繁的GC
致使頻繁GC有兩個緣由:
一、內存抖動, 即大量的對象被建立又在短期內立刻被釋放.
二、瞬間產生大量的對象會嚴重佔用內存區域。
電池使用優化
工具:Batterystats & bugreport
(1)優化網絡請求
(2)定位中使用GPS, 請記得及時關閉
網絡優化
網絡鏈接對用戶的影響:流量,電量,用戶等待,可在Android studio下方logcat
旁邊那個工具Network Monitor檢測
API設計:
App與Server之間的API設計要考慮網絡請求的頻次, 資源的狀態等. 以便App能夠以較少的請求來完成業務需求和界面的展現.
Gzip壓縮:
使用Gzip來壓縮request和response, 減小傳輸數據量, 從而減小流量消耗.
圖片的Size:
能夠在獲取圖片時告知服務器須要的圖片的寬高, 以便服務器給出合適的圖片, 避免浪費.
網絡緩存:
適當的緩存, 既可讓咱們的應用看起來更快, 也能避免一些沒必要要的流量消耗.
(1)對圖片自己進行操做。
儘可能不要使用setImageBitmap、setImageResource、BitmapFactory.decodeResource
來設置一張大圖,由於這些方法在完成decode後,最終都是經過 java 層的createBitmap
來完成的,須要消耗更多內存.
(2)圖片進行縮放的比例,SDK中建議其值是2的指數值,值越大會致使圖片不清晰。
(3)不用的圖片記得調用圖片的recycle()方法
Android與JS
經過WebView
互相調用方法,其實是:
Android去調用JS的代碼
經過WebView
的loadUrl()
,使用該方法比較簡潔,方便。可是效率比較低,獲取返回值比較困難。
經過WebView
的evaluateJavascript()
,該方法效率高,可是4.4以上的版本才支持,4.4如下版本不支持。因此建議二者混合使用。
JS去調用Android的代碼
WebView
的addJavascriptInterface()
進行對象映射 ,該方法使用簡單,僅將Android對象和JS對象映射便可,可是存在比較大的漏洞。漏洞產生緣由是:當JS拿到Android這個對象後,就能夠調用這個Android對象中全部的方法,包括系統類(java.lang.Runtime 類)
,從而進行任意代碼執行。
解決方法:
(1)Google 在Android 4.2版本中規定對被調用的函數以@JavascriptInterface
進行註解從而避免漏洞攻擊。
(2)在Android 4.2版本以前採用攔截prompt()進行漏洞修復。
WebViewClient
的shouldOverrideUrlLoading ()
方法回調攔截url 。這種方式的優勢:
不存在方式1的漏洞;
缺點:JS獲取Android方法的返回值複雜。(ios主要用的是這個方式)
(1)Android經過 WebViewClient 的回調方法shouldOverrideUrlLoading ()攔截 url
(2)解析該url的協議
(3)若是檢測到是預先約定好的協議,就調用相應方法
WebChromeClient
的onJsAlert()
、onJsConfirm()
、onJsPrompt()
方法回調攔截JS對話框alert()、confirm()、prompt() 消息這種方式的優勢:不存在方式1的漏洞;缺點:JS獲取Android方法的返回值複雜。
垃圾收集算法的核心思想是:
對虛擬機可用內存空間,即堆空間中的對象進行識別,若是對象正在被引用,那麼稱其爲存活對象,反之,若是對象再也不被引用,則爲垃圾對象,能夠回收其佔據的空間,用於再分配。垃圾收集算法的選擇和垃圾收集系統參數的合理調節直接影響着系統性能。
ANR全名Application Not Responding, 也就是"應用無響應". 當操做在一段時間內系統沒法處理時, 系統層面會彈出上圖那樣的ANR對話框.
產生緣由:
(1)5s內沒法響應用戶輸入事件(例如鍵盤輸入, 觸摸屏幕等).
(2)BroadcastReceiver
在10s內沒法結束
(3)Service 20s內沒法結束(低機率)
解決方式:
(1)不要在主線程中作耗時的操做,而應放在子線程中來實現。如onCreate()
和onResume()
裏儘量少的去作建立操做。
(2)應用程序應該避免在BroadcastReceiver
裏作耗時的操做或計算。
(3)避免在Intent Receiver裏啓動一個Activity,由於它會建立一個新的畫面,並從當前用戶正在運行的程序上搶奪焦點。
(4)service是運行在主線程的,因此在service中作耗時操做,必需要放在子線程中。
此處延伸:Double Check
的寫法被要求寫出來。
單例模式:分爲惡漢式和懶漢式
惡漢式:
public class Singleton { private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance ; } }
懶漢式:
public class Singleton02 { private static Singleton02 instance; public static Singleton02 getInstance() { if (instance == null) { synchronized (Singleton02.class) { if (instance == null) { instance = new Singleton02(); } } } return instance; } }
此處延伸:手寫mvp例子,與mvc之間的區別,mvp的優點
MVP模式
對應着Model
:業務邏輯和實體模型,view
:對應着activity,負責View的繪製以及與用戶交互,Presenter
:負責View和Model之間的交互,
MVP模式是在MVC
模式的基礎上,將Model與View完全分離使得項目的耦合性更低,在Mvc
中項目中的activity對應着mvc
中的C--Controllor
,而項目中的邏輯處理都是在這個C中處理,同時View與Model之間的交互,也是也就是說,mvc
中全部的邏輯交互和用戶交互,都是放在Controllor
中,也就是activity中。View和model是能夠直接通訊的。而MVP模式則是分離的更加完全,分工更加明確Model業務邏輯和實體模型,view負責與用戶交互,Presenter 負責完成View於Model間的交互,MVP
和MVC最大的區別是MVC中是容許Model和View進行交互的,而MVP中很明顯,Model與View之間的交互由Presenter完成。還有一點就是Presenter
與View
之間的交互是經過接口的
(1)安裝和下載Cygwin
,下載Android NDK
(2)在ndk
項目中JNI
接口的設計
(3)使用C/C++實現本地方法
(4)JNI生成動態連接庫.so文件
(5)將動態連接庫複製到java工程,在java工程中調用,運行java工程便可
RecyclerView
能夠完成ListView
,GridView
的效果,還能夠完成瀑布流的效果。同時還能夠設置列表的滾動方向(垂直或者水平);RecyclerView
中view
的複用不須要開發者本身寫代碼,系統已經幫封裝完成了。RecyclerView
能夠進行局部刷新。RecyclerView
提供了API
來實現item
的動畫效果。
在性能上:
若是須要頻繁的刷新數據,須要添加動畫,則RecyclerView
有較大的優點。
若是隻是做爲列表展現,則二者區別並非很大。
更多完整項目下載。未完待續。源碼。圖文知識後續上傳github。
能夠點擊關於我 聯繫我獲取
VX:mm14525201314