版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中StrictMode如何使用
本篇文章給大家分享的是有關(guān)Android中StrictMode如何使用,在下覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著在下一起來看看吧。StrictMode具體能檢測(cè)什么嚴(yán)苛模式主要檢測(cè)兩大問題,一個(gè)是線程策略,即TreadPolicy,另一個(gè)是VM策略,即VmPolicy。ThreadPolicy線程策略檢測(cè)線程策略檢測(cè)的內(nèi)容有自定義的耗時(shí)調(diào)用使用detectCustomSlowCalls()開啟磁盤讀取操作使用detectDiskReads()開啟磁盤寫入操作使用detectDiskWrites()開啟網(wǎng)絡(luò)操作使用detectNetwork()開啟VmPolicy虛擬機(jī)策略檢測(cè)Activity泄露使用detectActivityLeaks()開啟未關(guān)閉的Closable對(duì)象泄露使用detectLeakedClosableObjects()開啟泄露的Sqlite對(duì)象使用detectLeakedSqlLiteObjects()開啟檢測(cè)實(shí)例數(shù)量使用setClassInstanceLimit()開啟工作原理
其實(shí)StrictMode實(shí)現(xiàn)原理也比較簡(jiǎn)單,以IO操作為例,主要是通過在open,read,write,close時(shí)進(jìn)行監(jiān)控。libcore.io.BlockGuardOs文件就是監(jiān)控的地方。以open為例,如下進(jìn)行監(jiān)控。@Override
public
FileDescriptor
open(String
path,
int
flags,
int
mode)
throws
ErrnoException
{
BlockGuard.getThreadPolicy().onReadFromDisk();
if
((mode
&
O_ACCMODE)
!=
O_RDONLY)
{
BlockGuard.getThreadPolicy().onWriteToDisk();
}
return
os.open(path,
flags,
mode);
}其中onReadFromDisk()方法的實(shí)現(xiàn),代碼位于StrictMode.java中。public
void
onReadFromDisk()
{
if
((mPolicyMask
&
DETECT_DISK_READ)
==
0)
{
return;
}
if
(tooManyViolationsThisLoop())
{
return;
}
BlockGuard.BlockGuardPolicyException
e
=
new
StrictModeDiskReadViolation(mPolicyMask);
e.fillInStackTrace();
startHandlingViolationException(e);
}常見用法
嚴(yán)格模式的開啟可以放在Application或者Activity以及其他組件的onCreate方法。為了更好地分析應(yīng)用中的問題,建議放在Application的onCreate方法中。
其中,我們只需要在app的開發(fā)版本下使用StrictMode,線上版本避免使用StrictMode,這里定義了一個(gè)布爾值變量DEV_MODE來進(jìn)行控制。private
boolean
DEV_MODE
=
true;
public
void
onCreate()
{
if
(DEV_MODE)
{
StrictMode.setThreadPolicy(new
StrictMode.ThreadPolicy.Builder()
.detectCustomSlowCalls()
//API等級(jí)11,使用StrictMode.noteSlowCode
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
//
or
.detectAll()
for
all
detectable
problems
.penaltyDialog()
//彈出違規(guī)提示對(duì)話框
.penaltyLog()
//在Logcat
中打印違規(guī)異常信息
.penaltyFlashScreen()
//API等級(jí)11
.build());
StrictMode.setVmPolicy(new
StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
//API等級(jí)11
.penaltyLog()
.penaltyDeath()
.build());
}
super.onCreate();
}
其中Android3.0引入的方法包括detectCustomSlowCalls()和noteSlowCode(),它們都是用來檢測(cè)應(yīng)用中執(zhí)行緩慢代碼的或者潛在的緩慢代碼。查看報(bào)告結(jié)果
嚴(yán)格模式有很多種報(bào)告違例的形式,但是想要分析具體違例情況,還是需要查看日志,終端下過濾StrictMode就能得到違例的具體stacktrace信息。adb
logcat
|
grep
StrictMode當(dāng)然也可以選擇彈窗形式來簡(jiǎn)明提醒開發(fā)者彈窗警告ThreadPolicy詳解StrictMode.ThreadPolicy.Builder主要方法如下detectNetwork()用于檢查UI線程中是否有網(wǎng)絡(luò)請(qǐng)求操作檢測(cè)UI線程中網(wǎng)絡(luò)請(qǐng)求案例:public
class
MainActivity
extends
AppCompatActivity
implements
View.OnClickListener
{
Button
btnTest;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.setThreadPolicy(new
StrictMode.ThreadPolicy.Builder()
.detectNetwork()
.penaltyLog()
.build());
btnTest
=
(Button)
findViewById(R.id.btn_test);
btnTest.setOnClickListener(this);
}
@Override
public
void
onClick(View
v)
{
int
id
=
v.getId();
switch
(id)
{
case
R.id.btn_test:
postNetwork();
break;
}
}
/**
*
網(wǎng)絡(luò)連接的操作
*/
private
void
postNetwork()
{
try
{
URL
url
=
new
URL("");
HttpURLConnection
conn
=
(HttpURLConnection)
url.openConnection();
conn.connect();
BufferedReader
reader
=
new
BufferedReader(new
InputStreamReader(
conn.getInputStream()));
String
lines
=
null;
StringBuffer
sb
=
new
StringBuffer();
while
((lines
=
reader.readLine())
!=
null)
{
sb.append(lines);
}
}
catch
(Exception
e)
{
e.printStackTrace();
}
}
}運(yùn)行后,觸發(fā)的警告如下detectDiskReads()和detectDiskWrites()是磁盤讀寫檢查磁盤讀寫檢查案例:public
class
MainActivity
extends
AppCompatActivity
implements
View.OnClickListener
{
Button
btnTest;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.setThreadPolicy(new
StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()
.detectDiskReads()
.penaltyLog()
.build());
btnTest
=
(Button)
findViewById(R.id.btn_test);
btnTest.setOnClickListener(this);
}
@Override
public
void
onClick(View
v)
{
int
id
=
v.getId();
switch
(id)
{
case
R.id.btn_test:
writeToExternalStorage();
break;
}
}
/**
*
文件系統(tǒng)的操作
*/
public
void
writeToExternalStorage()
{
File
externalStorage
=
Environment.getExternalStorageDirectory();
File
mbFile
=
new
File(externalStorage,
"castiel.txt");
try
{
OutputStream
output
=
new
FileOutputStream(mbFile,
true);
output.write("".getBytes());
output.flush();
output.close();
}
catch
(FileNotFoundException
e)
{
e.printStackTrace();
}
catch
(IOException
e)
{
e.printStackTrace();
}
}
}運(yùn)行后,觸發(fā)的警告如下noteSlowCall針對(duì)執(zhí)行比較耗時(shí)的檢查
StrictMode從API11開始允許開發(fā)者自定義一些耗時(shí)調(diào)用違例,這種自定義適用于自定義的任務(wù)執(zhí)行類中,比如我們有一個(gè)進(jìn)行任務(wù)處理的類,為TaskExecutor。public
class
TaskExecutor
{
public
void
execute(Runnable
task)
{
task.run();
}
}
先需要跟蹤每個(gè)任務(wù)的耗時(shí)情況,如果大于500毫秒需要提示給開發(fā)者,noteSlowCall就可以實(shí)現(xiàn)這個(gè)功能,如下修改代碼public
class
TaskExecutor
{
private
static
long
SLOW_CALL_THRESHOLD
=
500;
public
void
executeTask(Runnable
task)
{
long
startTime
=
SystemClock.uptimeMillis();
task.run();
long
cost
=
SystemClock.uptimeMillis()
-
startTime;
if
(cost
>
SLOW_CALL_THRESHOLD)
{
StrictMode.noteSlowCall("slowCall
cost="
+
cost);
}
}
}執(zhí)行一個(gè)耗時(shí)2000毫秒的任務(wù)TaskExecutor
executor
=
new
TaskExecutor();
executor.executeTask(new
Runnable()
{
@Override
public
void
run()
{
try
{
Thread.sleep(2000);
}
catch
(InterruptedException
e)
{
e.printStackTrace();
}
}
});
得到的違例日志,注意其中~duration=20ms并非耗時(shí)任務(wù)的執(zhí)行時(shí)間,而我們的自定義信息msg=slowCallcost=2000才包含了真正的耗時(shí)。penaltyDeath(),當(dāng)觸發(fā)違規(guī)條件時(shí),直接Crash掉當(dāng)前應(yīng)用程序。penaltyDeathOnNetwork(),當(dāng)觸發(fā)網(wǎng)絡(luò)違規(guī)時(shí),Crash掉當(dāng)前應(yīng)用程序。penaltyDialog(),觸發(fā)違規(guī)時(shí),顯示對(duì)違規(guī)信息對(duì)話框。penaltyFlashScreen(),會(huì)造成屏幕閃爍,不過一般的設(shè)備可能沒有這個(gè)功能。penaltyDropBox(),將違規(guī)信息記錄到dropbox系統(tǒng)日志目錄中(/data/system/dropbox),你可以通過如下命令進(jìn)行插件:adb
shell
dumpsys
dropbox
dataappstrictmode
--printpermitCustomSlowCalls()、permitDiskReads()、permitDiskWrites()、permitNetwork:如果你想關(guān)閉某一項(xiàng)檢測(cè),可以使用對(duì)應(yīng)的permit*方法。VMPolicy詳解StrictMode.VmPolicy.Builder主要方法如下detectActivityLeaks()用戶檢查Activity的內(nèi)存泄露情況內(nèi)存泄露檢查案例:public
class
MainActivity
extends
AppCompatActivity
implements
View.OnClickListener
{
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.setVmPolicy(new
StrictMode.VmPolicy.Builder()
.detectActivityLeaks()
.penaltyLog()
.build()
);
new
Thread()
{
@Override
public
void
run()
{
while
(true)
{
SystemClock.sleep(1000);
}
}
}.start();
}
}我們反復(fù)旋轉(zhuǎn)屏幕就會(huì)輸出提示信息(重點(diǎn)在instances=2;limit=1這一行)
這時(shí)因?yàn)椋覀冊(cè)贏ctivity中創(chuàng)建了一個(gè)Thread匿名內(nèi)部類,而匿名內(nèi)部類隱式持有外部類的引用。而每次旋轉(zhuǎn)屏幕是,Android會(huì)新創(chuàng)建一個(gè)Activity,而原來的Activity實(shí)例又被我們啟動(dòng)的匿名內(nèi)部類線程持有,所以不會(huì)釋放,從日志上看,當(dāng)先系統(tǒng)中該Activty有4個(gè)實(shí)例,而限制是只能創(chuàng)建1各實(shí)例。我們不斷翻轉(zhuǎn)屏幕,instances的個(gè)數(shù)還會(huì)持續(xù)增加。detectLeakedClosableObjects()用于資源沒有正確關(guān)閉時(shí)提醒//
資源引用沒有關(guān)閉檢查案例
public
class
MainActivity
extends
AppCompatActivity
implements
View.OnClickListener
{
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.setVmPolicy(new
StrictMode.VmPolicy.Builder()
.detectLeakedClosableObjects()
.penaltyLog()
.build()
);
File
newxmlfile
=
new
File(Environment.getExternalStorageDirectory(),
"castiel.txt");
try
{
newxmlfile.createNewFile();
FileWriter
fw
=
new
FileWriter(newxmlfile);
fw.write("猴子搬來的救兵WooYun");
//fw.close();
我們?cè)谶@里特意沒有關(guān)閉
fw
}
catch
(IOException
e)
{
e.printStackTrace();
}
}
}運(yùn)行后觸發(fā)警告如下detectLeakedSqlLiteObjects()和detectLeakedClosableObjects()的用法類似,只不過是用來檢查SQLiteCursor或者其他SQLite對(duì)象是否被正確關(guān)閉detectLeakedRegistrationObjects()用來檢查BroadcastReceiver或者ServiceConnection注冊(cè)類對(duì)象是否被正確釋放setClassInstanceLimit(),設(shè)置某個(gè)類的同時(shí)處于內(nèi)存中的實(shí)例上限,可以協(xié)助檢查內(nèi)存泄露檢測(cè)內(nèi)存泄露案例public
class
MainActivity
extends
AppCompatActivity
implements
View.OnClickListener
{
private
static
class
CastielC
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 《月有陰晴圓缺》課件
- 2025年信陽藝術(shù)職業(yè)學(xué)院馬克思主義基本原理概論期末考試模擬題及答案解析(奪冠)
- 2025年上思縣招教考試備考題庫帶答案解析(必刷)
- 2024年鄂城鋼鐵廠職工大學(xué)馬克思主義基本原理概論期末考試題帶答案解析
- 2024年聶榮縣幼兒園教師招教考試備考題庫帶答案解析
- 2025年會(huì)同縣幼兒園教師招教考試備考題庫帶答案解析
- 2025年和平縣幼兒園教師招教考試備考題庫帶答案解析(必刷)
- 2024年縉云縣幼兒園教師招教考試備考題庫附答案解析(奪冠)
- 2025年唐縣幼兒園教師招教考試備考題庫含答案解析(奪冠)
- 保山市2025-2026學(xué)年(上期)高三期末考試歷史試卷(含答案解析)
- 陜西省西安市工業(yè)大學(xué)附屬中學(xué)2025-2026學(xué)年上學(xué)期八年級(jí)期末數(shù)學(xué)試題(原卷版+解析版)
- 電工素質(zhì)培訓(xùn)課件
- 2026年陜西省森林資源管理局局屬企業(yè)公開招聘工作人員備考題庫及參考答案詳解一套
- 講解員發(fā)聲技巧培訓(xùn)
- TCTA 011-2026 智能水尺觀測(cè)系統(tǒng)操作規(guī)程
- 律師事務(wù)所年度業(yè)績(jī)考核方案
- 2025年6月江蘇揚(yáng)州經(jīng)濟(jì)技術(shù)開發(fā)區(qū)區(qū)屬國有企業(yè)招聘23人筆試參考題庫附帶答案詳解(3卷)
- 四川省2025年高職單招職業(yè)技能綜合測(cè)試(中職類) 護(hù)理類試卷(含答案解析)
- 三體系基礎(chǔ)培訓(xùn)
- DL∕T 5210.5-2018 電力建設(shè)施工質(zhì)量驗(yàn)收規(guī)程 第5部分:焊接
- CJJT67-2015 風(fēng)景園林制圖標(biāo)準(zhǔn)
評(píng)論
0/150
提交評(píng)論