zoukankan      html  css  js  c++  java
  • App优化 StrictMode 严格模式

    StrictMode简介

            StrictMode最常用来捕捉应用程序的主线程,它将报告与线程及虚拟机相关的策略违例。一旦检测到策略违例policy violation,你将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。除了主线程,我们还可以在Handler,AsyncTask,AsyncQueryHandler,IntentService等API中使用StrictMode。

    示例代码  StrictMode文档


    检查策略

    StrictMode的线程策略主要用于检测磁盘IO和网络访问,而虚拟机策略主要用于检测内存泄漏现象。Android已经在磁盘IO访问和网络访问的代码中加入了StrictMode。当监视的线程发生策略的违例时,就可以获得警告,例如写入LogCat,显示一个对话框,闪下屏幕,写入DropBox日志文件,或让应用崩溃。最通常的做法是写入LogCat或让应用崩溃。下面的代码展示了如何使用StrictMode的检查策略:

    public void onCreate() {  
         if (DEVELOPER_MODE) {  
             StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()  //线程策略
                     .detectDiskReads()  //detect [dɪˈtɛkt] vt.查明,发现; 洞察; 侦察,侦查;
                     .detectDiskWrites()  
                     .detectNetwork()   
                     // or .detectAll() for all detectable problems 
                     .penaltyDialog()  //penalty [ˈpɛnəlti] n.刑罚; 惩罚; 害处
                     .penaltyLog()  
                     .penaltyDropBox()  //DropBox下拉框
                     .build());  
             
             StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()  //虚拟机策略
                     .detectLeakedSqlLiteObjects()  
                     .detectLeakedClosableObjects()  
                     .penaltyLog()  
                     .penaltyDeath()  
                     .build());  
         }  
         super.onCreate();  
     }  

    使用方法        

     如果不指定检测函数,也可以用detectAll()来替代。penaltyLog()表示将警告输出到LogCat,你也可以使用其他或增加新的惩罚(penalty)函数,例如使用penaltyDeath()的话,一旦StrictMode消息被写到LogCat后应用就会崩溃。具体支持的监视方法见:StrictMode.ThreadPolicy.Builder 与 StrictMode.VmPolicy.Builder


    在正式版本中,我们并不希望使用StrictMode来让用户的应用因为一个警告而崩溃,所以在应用正式发布时,需要移出这些监视。你可以通过删除代码来实现,不过这里提供一个更好的方式来解决这个问题,即使用AndroidMainifest文件中的debuggable属性来实现,代码如下所示:

    android:debuggable="true"  

    PS:可能在gradle中这么配置也行

    android {    
    	buildTypes {
    		debug {
    			debuggable true
    		}
    	}
    }

    在代码中,使用方法如下所示:

    // Return if this application is not in debug mode
    if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {   
        // Do StrictMode setup here   
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()   
            .detectLeakedSqlLiteObjects()   
            .penaltyLog()   
            .penaltyDeath()   
            .build());   
    }  


    实例

     我们在测试代码的主线程中去访问网络,这样就一定会触发StrictMode的线程监测,代码如下所示:

    public class MainActivity extends Activity {
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
    				.detectDiskReads()
    				.detectDiskWrites()
    				.detectNetwork()
    				.penaltyDialog()
    				.penaltyLog()
    				.penaltyDropBox()
    				.build());
    		super.onCreate(savedInstanceState);
    		
    		TextView mTextView = new TextView(this);
    		setContentView(mTextView);
    		
    		InputStream inputStream = null;
    		try {
    			HttpResponse httpResponse = new DefaultHttpClient().execute(new HttpGet("http://www.baidu.com"));
    			HttpEntity httpEntity = httpResponse.getEntity();
    			if (httpResponse.getStatusLine().getStatusCode() == 200) {
    				inputStream = httpEntity.getContent();
    				mTextView.setText(new BufferedReader(new InputStreamReader(inputStream)).readLine());
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if (inputStream != null) inputStream.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }

    运行代码,并将Log信息保存到本地,在Log中,我们可以搜索D/StrictMode关键字,如下所示:

    D/StrictMode: StrictMode policy violation; ~duration=5131 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=183 violation=2
    	  at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1157)
    	  at libcore.io.BlockGuardOs.open(BlockGuardOs.java:182)
    	  at libcore.io.IoBridge.open(IoBridge.java:480)
    	  at java.io.FileInputStream.<init>(FileInputStream.java:76)
    	  at java.io.FileInputStream.<init>(FileInputStream.java:103)
    	  at android.content.res.HwResources.readDefaultConfig(HwResources.java:1172)
    	  at android.content.res.HwResources.loadDrawable(HwResources.java:574)
    	  at android.content.res.Resources.getDrawable(Resources.java:809)
    	  at android.content.Context.getDrawable(Context.java:403)
    	  at com.android.internal.widget.ToolbarWidgetWrapper.setIcon(ToolbarWidgetWrapper.java:321)
    	  at com.android.internal.widget.ActionBarOverlayLayout.setIcon(ActionBarOverlayLayout.java:741)
    	  at com.android.internal.policy.impl.PhoneWindow.setDefaultIcon(PhoneWindow.java:1661)
    	  at android.app.Activity.initWindowDecorActionBar(Activity.java:2174)
    	  at android.app.Activity.setContentView(Activity.java:2189)
    	  at com.imooc.strictmodetest.MainActivity.onCreate(MainActivity.java:36)
    	  at android.app.Activity.performCreate(Activity.java:6102)
    	  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
    	  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2403)
    	  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
    	  at android.app.ActivityThread.access$1200(ActivityThread.java:165)
    	  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1373)
    	  at android.os.Handler.dispatchMessage(Handler.java:102)
    	  at android.os.Looper.loop(Looper.java:135)
    	  at android.app.ActivityThread.main(ActivityThread.java:5593)
    	  at java.lang.reflect.Method.invoke(Native Method)
    	  at java.lang.reflect.Method.invoke(Method.java:372)
    	  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:967)
    	  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762)

    主要看第一行

    D/StrictMode: StrictMode policy violation; ~duration=5131 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=183 violation=2

    这行Log中可以显示出StrictMode提示的原因,通过这里的TraceLog我们就可以来找到优化的方法。

    除了在Logcat中查看StrictMode的日志信息,如果你使用了penaltyDropbox()方法,那么你还可以通过如下所示的命令来调用DropBoxManager观察StrictMode日志:

    adb shell dumpsys dropbox data_app_strictmode --print

    同时,如果使用了penaltyDialog()方法,在应用中还会弹出如下所示的提示框:


    暂停监测

    如果在程序运行中无法避免的会违反StrictMode中的一些定义好的策略,而我们又希望能够暂时忽略这些策略的监视,我们可以使用permitXXXXX方法来暂停这些内容的监测,在做完需要忽略的监测之后,再启用监测,代码如下所示:
    StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();  
    StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(old)  
            .permitDiskWrites()  
            .build());  
    //doSomethingWriteToDisk();  
    StrictMode.setThreadPolicy(old);  

    2017-10-20





  • 相关阅读:
    最近的一些心理活动
    object_c函数多个返回值
    nslayoutConstraint
    判断一些常用的东西
    color 的一些处理
    最近的心理活动
    加载不同的nib文件
    Be a person
    按钮居左显示
    SQLite错误码
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/7698657.html
Copyright © 2011-2022 走看看