性能優(yōu)化工具(一)-StrictMode

一、簡介:

StrictMode類是Android 2.3 (API 9)引入的一個工具類,可以用來幫助開發(fā)者發(fā)現(xiàn)代碼中的一些不規(guī)范的問題,以達(dá)到提升應(yīng)用響應(yīng)能力的目的。舉個例子來說,如果開發(fā)者在UI線程中進(jìn)行了網(wǎng)絡(luò)操作或者文件系統(tǒng)的操作,而這些緩慢的操作會嚴(yán)重影響應(yīng)用的響應(yīng)能力,甚至出現(xiàn)ANR對話框。為了在開發(fā)中發(fā)現(xiàn)這些容易忽略的問題,我們使用StrictMode,系統(tǒng)檢測出主線程違例的情況并做出相應(yīng)的反應(yīng),最終幫助開發(fā)者優(yōu)化和改善代碼邏輯。

二、官網(wǎng)文檔:StrictMode使用文檔
三、用途:

使用嚴(yán)格模式,系統(tǒng)檢測出主線程違例的情況會做出相應(yīng)的反應(yīng),如日志打印,彈出對話框亦或者崩潰等。換言之,嚴(yán)格模式會用不同的策略對應(yīng)用的違例細(xì)節(jié)做監(jiān)控,通過一定的方式暴露給開發(fā)者方便優(yōu)化與改善。

四、使用:

通常在Activity或者自定義的Application類的onCreate方法中啟動StrictMode(自定義application無效,不知道是不是配置問題)

// DEVELOPER_MODE代表只在調(diào)試模式下啟用StrictMode

if (DEVELOPER_MODE) {

   StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()

           .detectDiskReads()

           .detectDiskWrites()

           .detectNetwork()   // or .detectAll() for all detectable problems

           .penaltyLog()

           .build());

   StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()

           .detectLeakedSqlLiteObjects()

           .detectLeakedClosableObjects()

           .penaltyLog()

           .penaltyDeath()

           .build());

}

StrictMode通過策略方式來讓你自定義需要檢查哪些方面的問題,主要有兩種策略:

ThreadPolicy:線程方面的策略

VmPolicy:VM方面的策略

ThreadPolicy策略:

StrictMode.ThreadPolicy.Builder主要方法如下:

    detectNetwork():用于檢查UI線程中是否有網(wǎng)絡(luò)請求

    detectDiskReads()和detectDiskWrites():是磁盤讀寫檢查

    detectCustomSlowCalls():主要用于幫助開發(fā)者發(fā)現(xiàn)UI線程中調(diào)用的哪些方法執(zhí)行的比較慢,要和StrictMode.noteSlowCall配合使用,只有通過  StrictMode.noteSlowCall標(biāo)記“可能會”執(zhí)行比較慢的方法,只有標(biāo)記過的方法才能被檢測到,日志中會記錄方法的執(zhí)行時間(注意:只有在主線程中執(zhí)行的方法才會顯示執(zhí)行時間,在其他線程中執(zhí)行的方法,就算是使用StrictMode.noteSlowCall標(biāo)記,在日志中也不會打印執(zhí)行時間)

VMPloicy策略:

StrictMode.VmPolicy.Builder()主要方法如下:

detectActivityLeaks() 用戶檢查 Activity 的內(nèi)存泄露情況

detectLeakedClosableObjects() 和 detectLeakedSqlLiteObjects(),資源沒有正確關(guān)閉時回觸發(fā),detectLeakedSqlLiteObjects() 和 detectLeakedClosableObjects()的用法類似,只不過是用來檢查 SQLiteCursor 或者 其他 SQLite 對象是否被正確關(guān)閉

detectLeakedRegistrationObjects() 用來檢查 BroadcastReceiver 或者 ServiceConnection 注冊類對象是否被正確釋放

setClassInstanceLimit(),設(shè)置某個類的同時處于內(nèi)存中的實例上限,可以協(xié)助檢查內(nèi)存泄露

懲罰:

penaltyDeath():當(dāng)觸發(fā)違規(guī)條件時,直接Crash掉當(dāng)前應(yīng)用程序

penaltyDeathOnNetwork():當(dāng)觸發(fā)網(wǎng)絡(luò)違規(guī)時,Crash掉當(dāng)前應(yīng)用程序

penaltyDialog():觸發(fā)違規(guī)時,顯示對違規(guī)信息對話框

penaltyFlashScreen():會造成屏幕閃爍,不過一般的設(shè)備可能沒有這個功能

penaltyDropBox():將違規(guī)信息記錄到 dropbox 系統(tǒng)日志目錄中(/data/system/dropbox),你可以通過如下命令進(jìn)行插件

adb shell dumpsys dropbox dataappstrictmode --print

permitCustomSlowCalls()、permitDiskReads ()、permitDiskWrites()、permitNetwork: 如果你想關(guān)閉某一項檢測,可以使用對應(yīng)的permit*方法

最后:我們也可以在Android設(shè)備的設(shè)置(Settings)中啟用StrictMode(親測沒有什么效果):

開發(fā)者選項 > 啟用嚴(yán)格模式

最后分享一個小例子:

public class MainActivity extends AppCompatActivity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .build());

        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                writeToExternalStorage();
            }
        });
    }

    /**
     * 文件系統(tǒng)的操作
     */
    public void writeToExternalStorage() {
            try {
                File externalStorage = Environment.getExternalStorageDirectory();

                File mbFile = new File(externalStorage, "xxx.txt");
                if (mbFile.exists()){
                    mbFile.createNewFile();
                }
            OutputStream output = new FileOutputStream(mbFile, true);
            output.write("www.wooyun.org".getBytes());
            output.flush();
            output.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用penaltyLog():

D/StrictMode: StrictMode policy violation; ~duration=3 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=65567 violation=1
                                                                         at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1253)
                                                                         at java.io.FileOutputStream.<init>(FileOutputStream.java:220)
                                                                         at com.perf.strictmodedemo.MainActivity.writeToExternalStorage(MainActivity.java:44)
                                                                         at com.perf.strictmodedemo.MainActivity$1.onClick(MainActivity.java:28)
                                                                         at android.view.View.performClick(View.java:5619)
                                                                         at android.view.View$PerformClick.run(View.java:22298)
                                                                         at android.os.Handler.handleCallback(Handler.java:754)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                         at android.os.Looper.loop(Looper.java:165)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:6365)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:883)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)

使用penaltyDialog():

筆者使用后感覺,StrictMode適合作為一些基礎(chǔ)規(guī)范問題排查。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容