生命周期:
如何提高service的生存率?
foreground process 前端進程
前端進程就是目前顯示在屏幕上和用戶交互的進程
比如說:
visible process 可見進程
沒有任何前臺組件,但是仍然能影響用戶在屏幕上看到東西。
比如:
Service process 服務進程
服務進程不會直接為用戶所見
比如在后臺播放mp3或者從網上下載東西
background process 后臺進程
比如:Activity執行了onStop
empty process 空進程
File,Sqlite,Content Provider,BroadCast Receiver,Intent,同個Application內部的話還可以通過靜態變量共享數據。
提高渲染的優先級
webSettings.setRenderPriority(RenderPriority.HIGH);
把圖片加載放在最后來加載渲染
webSettings.setBlockNetworkImage(true);
使用硬件加速,該功能在Android 3.0 (API level 11)才加入。
硬件加速可以在一下四個級別開啟或關閉:Application、Activity、Window、View
比如,在AndroidManifest.xml中添加android:hardwareAccelerated屬性;關閉view的硬件加速myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
開啟緩存
設置websetting
將一個對象暴露給JavaScript:webview.addJavascriptInterface。這個對象包含了JS調用的方法,這些方法用@JavascriptInterface修飾
JS通過這些方法與Android交互
MessageQueue本質上是一個單鏈表,不是Queue。采用FIFO方式管理,enqueueMessage()方法是將消息插入一條隊列,next()方法是一個無限循環的方法。如果有消息,則取出,如果沒有,就阻塞。
本質上是一個繼承了Thread的線程類。
通過創建HandlerThread**獲取looper對象,傳遞給Handler對象,執行異步任務。在HandlerThread中通過**Looper.prepare()來創建消息隊列,并通過Looper.loop()來開啟消息循環。創建HandlerThread后必須先調用start()方法,才能調用getLooper()獲取Looper對象。
HandlerThread封裝了Looper對象,使我們不用關心Looper的開啟和釋放的細節問題。如果不用HandlerThread的話,需要手動去調用Looper.prepare()和Looper.loop()這些方法。
原理:IntentService是一個抽象類,封裝了HandlerThread和Handler,負責處理耗時的任務。任務執行完畢后會自行停止。在onCreate()方法中開啟了一個HandlerThread線程,之后通過HandlerThread的Looper初始化了一個Handler,負責處理耗時操作。通過startService()方法啟動,在handler中調用抽象方法onHandleIntent(),該方法執行完成后自動調用stopself()方法停止
override onHandleIntent() 方法
優點:一方面不需要自己去創建線程,另一方面不需要考慮在什么時候關閉該Service
what
OOM 和 內存泄漏 的區別
how
Handler造成OOM
WebView造成OOM
三個核心步驟:Measure、Layout、Draw
重要
Activity不負責視圖的控制,而是交給Window。這個Window本質上是一個PhoneWindow,被windowmanager管理。
Window中有decorview,decorview是當前視圖的底層View,是setContentView所設置View的父View
View是所有控件的基類。
ViewRoot對應ViewRootImpl,它是連接WindowManager和DecorView的紐帶。繪制的三大流程都是在ViewRootImpl中完成的:從ViewRootImpl中的performTraversals開始,有三個方法performMeasure, performLayout, prformDraw分別對應measure,layout,draw三個流程,完成對頂級View的繪制。
在父View的Measure過程中,會調用子View的Measure過程,如此反復,完成對整個View樹的遍歷。同理,在Layout和Draw中也是如此。
優點:
缺點:
RecyclerView.Adapter
Serializable接口:Java的序列化接口,使用簡單,但開銷大,序列化和反序列化需要大量IO操作
Parcelable接口:是Android的序列化方式,使用復雜,但效率高。
對象是不能直接跨進程傳輸的。對象的跨進程傳輸,其本質是序列化和反序列化的過程
四大組件間,把數據封裝到Bundle。在一個進程中開啟另一個進程的Activity或者Service,就可以通過Intent把Bundle傳遞過去。其中,封裝在Bundle中的數據需要能夠被序列化
使用文件共享方式,多進程讀寫一個相同的文件,獲取文件內容進行交互。
使用ContentProvider,常用于多進程共享數據,比如系統的相冊,音樂等,我們也可以通過ContentProvider訪問到
使用Socket傳輸數據。服務端(比如一個進程中運行了一個Service)創建一個ServerSocket對象,監聽本地的端口;客戶端(比如另一個進程中運行的Activity)通過Socket連接本地的那個接口。經過TCP的三次握手后,建立連接。接著可以發送數據。使用socket不僅可以實現進程間通信,也可以實現設備間通信。
四個角色:Client、Server、ServiceManager、BinderDriver
調用過程:
1. Server向ServiceManager注冊
2. Client通過ServiceManager獲取Server的代理對象
3. Client向代理對象發起請求,該請求通過BinderDriver發送給Server處理
4. Server通過BinderDriver返回處理結果
注意:客戶端調用服務端的方法,被調用的方法運行在服務端的Binder線程池中,此時客戶端被掛起。因此此時需要避免ANR。(AIDL和Messager同理)
Binder連接池
在一個應用有多個使用AIDL的場景,無需為每一個AIDL創建自己的Service。而是使用一個Service,創建并返回一個Binder連接池的Binder對象。Activity在使用AIDL的時候,可以通過該Binder連接池對象,獲取不同的Binder對象(類似于工廠模式)
一種輕量級的跨進程通訊方案,底層使用AIDL實現。
是一種串行的通信,即服務端需要一個一個處理消息。因此,在大量并發請求的情況下,用Messager就不太合適。
使用流程:以Activity(進程1)和Service(進程2)通信為例
init進程-zygote進程-SystemServer進程-各種ManagerService(AMS,PMS,WMS)- launcher程序
launcher-AMS-(pause)-zygote-新進程ActivityThread-(main函數)-向AMS注冊-通知ActivityThread創建Activity并執行生命周期
Activity1-AMS-(pause)-在同一個ActivityThread-加載Activity2類,執行生命周期
1、減少不必要的jar包依賴
2、優先使用代碼來設置UI效果
3、去除沒用到的資源文件,壓縮其他資源文件的大小,不用適配所有尺寸的設備
4、盡量重用代碼,避免代碼的冗余
5、限制app支持的cpu架構的數目:在當前的Android 生態系統中,讓你的app支持 armabi 和 x86 架構就夠了;
what:dex是Android平臺上(Dalvik虛擬機)的可執行文件, 相當于Windows平臺中的exe文件, 每個Apk安裝包中都有dex文件。
單個dex文件所包含的最大方法數是65536,包含Android Framwork、依賴的jar包,以及應用本身的所有方法。
解決方法數越界:
基本使用:
布局優化:
OOM優化
ANR優化
ListView(GridView)優化
Bitmap優化
其中M層處理數據,業務邏輯等;V層處理界面的顯示結果;C層起到橋梁的作用,來控制V層和M層通信
視圖層(View):一般采用XML文件進行界面的描述,這些XML可以理解為AndroidApp的View。
控制層(Controller):Android中由Activit、Fragment承擔,負責邏輯處理
模型層(Model):提供數據,從進行數據庫或者網絡的操作。
缺點:在Android開發中,Activity并不是一個標準的MVC模式中的Controller,它的首要職責是加載應用的布局和初始化用戶界面,接受并處理來自用戶的操作請求,進而作出響應,既是view層,又是controller層。隨著界面及其邏輯的復雜度不斷提升,Activity類的職責不斷增加,以致變得龐大臃腫。
MVP框架由3部分組成:
優點:將在Activty中的大量邏輯操作放到Presenter控制層中,避免Activity的臃腫。
缺點:MVP模式需要多寫許多新的接口;過于復雜的邏輯會使得Presenter臃腫
實現方法:
LiveData:
ViewModel:將視圖的數據和邏輯從具有生命周期特性的實體(如 Activity 和 Fragment)中剝離開來。比如 AndroidViewModel(ViewModle的子類)
Room:官方數據庫框架,對原生的SQLite API進行了一層封裝。
個人理解:MVVM是一種思想,AAC提供多種工具。利用AAC中的工具實現MVVM的思想
View:
ViewModel:
Model:
基于觀察者模式,可以方便地以流的方式處理異步事件
創建:
Observable.create/just/from
Schedulers線程調度
在不指定線程的情況下, RxJava 遵循的是線程不變的原則
subscribeOn():
指定 subscribe() 所發生的線程,即 Observable.OnSubscribe 被激活時所處的線程。或者叫做事件產生的線程。
subscribeOn() 的位置放在哪里都可以,但它是只能調用一次的。
observeOn():
變換 操作符
背壓
在異步場景下,被觀察者的發送速度遠遠大于觀察者的處理速度。
Observable不支持背壓
Flowable支持背壓:
- 背壓策略:MISSING、ERROR、BUFFER、DROP、LATEST
是一個網絡請求框架,底層依賴OkHttp
支持兩種模式:callback、RxJava/RxAndroid
由于Java的跨平臺的特性,導致Java同本地交互的能力不夠強大,一些和操作系統相關的操作無法完成。通過JNI可以調用C和C++的代碼,提高自己的本地交互能力
OkHttp
XML全稱叫做可擴展標記語言,它的結構相對簡單,數據共享比較方便。但是對于一些比較復雜的數據,XML文件格式復雜,解析的代價大。
JSON的數據格式比較簡單,易于讀寫。但是目前還沒有XML應用廣泛。
GSON的Google的一個開源庫。這個開源庫可以很方便地將JSON數組轉換為對象,這在開發中簡化了將JSON的字段轉換為屬性的步驟。
apk下載到cache目錄,只有 rw 權限,沒有 x 權限,所以無法安裝
Runtime.getRuntime().exec()
執行 chmod 命令,修改為rwx
UncaughtExceptionHandler:
android全局異常捕獲器——在Application中調用**Thread.setDefaultUncaughtExceptionHandler
(uncaughtExceptionHandler)**,定制自己的錯誤日志系統。比如在發生Exception時,記錄exception的堆棧信息。
在application中,調用registerActivityLifecycleCallbacks(),通過實現了ActivityLifecycleCallbacks接口的實例,完成對Activity各個生命周期信息的采集。比如哪個Activity在什么時間處于onCreate、onStop等等,進而統計出Activity的使用時間和使用次數。
SDK提供不同接口,分別對應Fragment的各個生命周期,進而采集信息。使用時,需要用戶在Fragment的生命周期中的各個環節中,調用對應的接口。
會不會使用麻煩?會的,解決方法就是:在SDK中封裝一個Fragment的子類,在這個子類中按照上述方法采集信息。用戶在使用SDK過程中,可以直接繼承使用這個子類,而不是繼承使用Fragment。
采用插裝的辦法:SDK提供兩個接口,用戶在發起HTTP請求時,調用第一個接口,可以記錄下url和時間。在結束HTTP時,調用第二個接口,記錄下url、時間和返回碼。這兩組記錄就完成了對HTTP接口的數據采集?
會不會麻煩?會的,但是這種方法很通用,其他商用的SDK中也是這種方法。或者使用Gradle插件,在編譯的時候,將上述代碼自動插入項目中。
方案一:發現錯誤后立即上報。優點:實時性好;缺點:不能保證每一條信息都能上報成功。
方案二:發生錯誤后,記錄在本地,當第二次啟動App的時候,上報上一次的信息。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。