<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 13.1 使用CrashHandler來獲取應用的Crash信息 (1)應用發生Crash在所難免,但是如何采集crash信息以供后續開發處理這類問題呢?利用Thread類的`setDefaultUncaughtExceptionHandler`方法!`defaultUncaughtHandler`是Thread類的靜態成員變量,所以如果我們將自定義的`UncaughtExceptionHandler`設置給Thread的話,那么當前進程內的所有線程都能使用這個UncaughtExceptionHandler來處理異常了。 ~~~ public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) { Thread.defaultUncaughtHandler = handler; } ~~~ (2)作者實現了一個簡易版本的UncaughtExceptionHandler類的子類`CrashHandler`,[源碼傳送門](https://github.com/singwhatiwanna/android-art-res/blob/master/Chapter_13/CrashTest/src/com/ryg/crashtest/CrashHandler.java) CrashHandler的使用方式就是在Application的`onCreate`方法中設置一下即可 ~~~ //在這里為應用設置異常處理程序,然后我們的程序才能捕獲未處理的異常 CrashHandler crashHandler = CrashHandler.getInstance(); crashHandler.init(this); ~~~ ##13.2 使用multidex來解決方法數越界 (1)在Android中單個dex文件所能夠包含的最大方法數是`65536`,這包含Android Framework、依賴的jar以及應用本身的代碼中的所有方法。如果方法數超過了最大值,那么編譯會報錯`DexIndexOverflowException`。 有時方法數沒有超過最大值,但是安裝在低版本手機上時應用異常終止了,報錯`Optimization failed`。這是因為應用在安裝的時候,系統會通過`dexopt`程序來優化dex文件,在優化的過程中dexopt采用一個固定大小的緩沖區來存儲應用中所有方法的信息,這個緩沖區就是`LinearAlloc`。LinearAlloc緩沖區在新版本的Android系統中大小是8MB或者16MB,但是在Android 2.2和2.3中卻只有5MB,當待安裝的應用的方法數比較多的時候,盡管它還沒有達到最大方法數,但是它的存儲空間仍然有可能超過5MB,這種情況下dexopt就會報錯導致安裝失敗。 (2)如何解決方法數越界的問題呢??Google在2014年提出了簡單方便的`multidex`的解決方案。 在Android 5.0之前使用multidex需要引入`android-support-multidex.jar`包,從Android 5.0開始,系統默認支持了multidex,它可以從apk中加載多個dex。Multidex方案主要針對AndroidStudio和Gradle編譯環境。 使用Multidex的步驟: 1.在`build.gradle`文件中添加`multiDexEnabled true` ~~~ android { ... defaultConfig { ... multiDexEnabled true // [添加的配置] enable multidex support } ... } ~~~ 2.添加對multidex的依賴 ~~~ compile 'com.android.support:multidex:1.0.0' ~~~ 3.在代碼中添加對multidex的支持,這里有三種方案: ① 在AndroidManifest文件中指定Application為`MultiDexApplication` ~~~ <application android:name="android.support.multidex.MultiDexApplication" ... </application> ~~~ ② 讓應用的Application繼承自`MultiDexApplication` ③ 重寫Application的`attachBaseContext`方法,這個方法要先于`onCreate`方法執行 ~~~ public class TestApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); // } } ~~~ 采用上面的配置之后,如果應用的方法數沒有越界,那么Gradle并不會生成多個dex文件;如果方法數越界后,Gradle就會在apk中打包2個或者多個dex文件,具體會打包多少個dex文件要看當前項目的代碼規模。在有些情況下,可能需要指定主dex文件中所要包含的類,這個可以通過`--main-dex-list`選項來實現這個功能。 ~~~ afterEvaluate { println "afterEvaluate" tasks.matching { it.name.startsWith('dex') }.each { dx -> def listFile = project.rootDir.absolutePath + '/app/maindexlist.txt' println "root dir:" + project.rootDir.absolutePath println "dex task found: " + dx.name if (dx.additionalParameters == null) { dx.additionalParameters = [] } dx.additionalParameters += '--multi-dex' dx.additionalParameters += '--main-dex-list=' + listFile dx.additionalParameters += '--minimal-main-dex' } } ~~~ `--multi-dex`表明當方法數越界時生成多個dex文件,`--main-dex-list`指定了要在主dex中打包的類的列表,`--minimal-main-dex`表明只有`--main-dex-list`所指定的類才能打包到主dex中。multidex的jar包中的9個類必須要打包到主dex中,其次不能在Application中成員以及代碼塊中訪問其他dex中的類,否個程序會因為無法加載對應的類而中止執行。 (3)Multidex方案可能帶來的問題: 1.應用啟動速度會降低,因為應用啟動的時候會加載額外的dex文件,所以要避免生成較大的dex文件; 2.需要做大量的兼容性測試,因為Dalvik LinearAlloc的bug,可能導致使用multidex的應用無法在Android 4.0以前的手機上運行。 ## 13.3 Android的動態加載技術 (1)動態加載技術又稱插件化技術,將應用插件化可以減輕應用的內存和CPU占用,還可以在不發布新版本的情況下更新某些模塊。不同的插件化方案各有特色,但是都需要解決三個基礎性問題:資源訪問,Activity生命周期管理和插件ClassLoader的管理。 (2)宿主和插件:宿主是指普通的apk,插件是經過處理的dex或者apk。在主流的插件化框架中多采用特殊處理的apk作為插件,處理方式往往和編譯以及打包環節有關,另外很多插件化框架都需要用到代理Activity的概念,插件Activity的啟動大多數是借助一個代理Activity來實現的。 (3)資源訪問:宿主程序調起未安裝的插件apk,插件中凡是R開頭的資源都不能訪問了,因為宿主程序中并沒有插件的資源,通過R來訪問插件的資源是行不通的。 Activity的資源訪問是通過`ContextImpl`來完成的,它有兩個方法`getAssets()`和`getResources()`方法是用來加載資源的。 具體實現方式是通過反射,調用`AssetManager`的`addAssetPath`方法添加插件的路徑,然后將插件apk中的資源加載到`Resources`對象中即可。 (4)Activity生命周期管理:有兩種常見的方式,反射方式和接口方式。反射方式就是通過反射去獲取Activity的各個生命周期方法,然后在代理Activity中去調用插件Activity對應的生命周期方法即可。 反射方式代碼繁瑣,性能開銷大。接口方式將Activity的生命周期方法提取出來作為一個接口,然后通過代理Activity去調用插件Activity的生命周期方法,這樣就完成了插件Activity的生命周期管理。 (5)插件ClassLoader的管理:為了更好地對多插件進行支持,需要合理地去管理各個插件的`DexClassLoader`,這樣同一個插件就可以采用同一個ClassLoader去加載類,從而避免了多個ClassLoader加載同一個類時所引起的類型轉換錯誤。 其他詳細信息看作者插件化框架[singwhatiwanna/dynamic-load-apk](https://github.com/singwhatiwanna/dynamic-load-apk) ## 13.4 反編譯初步 1.主要介紹使用`dex2jar`和`jd-gui`反編譯apk和使用`apktool`對apk進行二次打包,比較簡單,略過不總結。 ## 第14章 JNI和NDK編程 本章主要是介紹JNI和NDK編程入門知識,比較簡答,略過不總結。 如果感興趣NDK開發可以閱讀我之前總結的[Android NDK和OpenCV整合開發系列文章](http://hujiaweibujidao.github.io/blog/2013/11/18/android-ndk-and-opencv-developement/)。 ## 第15章 Android性能優化 (1)2015年Google關于Android性能優化典范的專題視頻?[Youtube視頻地址](https://www.youtube.com/playlist?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE) (2)布局優化 1.刪除布局中無用的組件和層級,有選擇地使用性能較低的ViewGroup; 2.使用`<include>`、`<merge>`、`<viewstub>`等標簽:`<include>`標簽主要用于布局重用,`<merge>`標簽一般和`<include>`配合使用,它可以減少布局中的層級;`<viewstub>`標簽則提供了按需加載的功能,當需要的時候才會將ViewStub中的布局加載到內存,提供了程序的初始化效率。 3.`<include>`標簽只支持`android:layout_`開頭的屬性,`android:id`屬性例外。 4.`ViewStub`繼承自View,它非常輕量級且寬高都為0,它本身不參與任何的布局和繪制過程。實際開發中,很多布局文件在正常情況下不會顯示,例如網絡異常時的界面,這個時候就沒有必要在整個界面初始化的時候加載進行,通過ViewStub可以做到在需要的時候再加載。 如下面示例,`android:id`是ViewStub的id,而`android:inflatedId`是布局的根元素的id。 ~~~ <ViewStub android:id="@+id/xxx" android:inflatedId="@+id/yyy" android:layout="@layout/zzz" ... </ViewStub> ~~~ (3)繪制優化 1.在`onDraw`中不要創建新的布局對象,因為`onDraw`會被頻繁調用; 2.`onDraw`方法中不要指定耗時任務,也不能執行成千上萬次的循環操作。 (4)內存泄露優化 1.可能導致內存泄露的場景很多,例如靜態變量、單例模式、屬性動畫、AsyncTask、Handler等等 (5)響應速度優化和ANR日志分析 1.ANR出現的情況:Activity如果`5s`內沒有響應屏幕觸摸事件或者鍵盤輸入事件就會ANR,而BroadcastReceiver如果`10s`內沒有執行完操作也會出現ANR。 2.當一個進程發生了ANR之后,系統會在`/data/anr`目錄下創建一個文件`traces.txt`,通過分析這個文件就能定位ANR的原因。 (6)ListView和Bitmap優化 1.ListView優化:采用`ViewHolder`并避免在`getView`方法中執行耗時操作;根據列表的滑動狀態來繪制任務的執行頻率;可以嘗試開啟硬件加速來使ListView的滑動更加流暢。 2.Bitmap優化:根據需要對圖片進行采樣,詳情看[Android開發藝術探索》讀書筆記 (12) 第12章 Bitmap的加載和Cache](http://hujiaweibujidao.github.io/blog/2015/11/30/Art-of-Android-Development-Reading-Notes-12/)。 (7)線程優化 1.采用線程池,詳情看[《Android開發藝術探索》讀書筆記 (11) 第11章 Android的線程和線程池](http://hujiaweibujidao.github.io/blog/2015/12/03/Art-of-Android-Development-Reading-Notes-11/)。 (8)其他優化建議 1.不要過多使用枚舉,枚舉占用的內存空間要比整型大; 2.常量請使用`static final`來修飾; 3.使用一些Android特有的數據結構,比如`SparseArray`和`Pair`等,他們都具有更好的性能; 4.適當使用軟引用和弱引用; 5.采用內存緩存和磁盤緩存; 6.盡量采用靜態內部類,這樣可以避免潛在的由于內部類而導致的內存泄露。 (9)MAT是功能強大的內存分析工具,主要有`Histograms`和`Dominator Tree`等功能
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看