使用严苛模式打破Android4.0以上平台应用中UI主线程的“独断专行”

Android性能调优——严苛模式StrictMode 前情提要 由于在demo中涉及了在主线程的网络操作,当时在开发时仅简单搜索了相关异常的处理方法,于是书写了以下代码: StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy .Builder() .permitAll() .build(); StrictMode.setThreadPolicy(policy); 这段代码很好的解决了抛异常的问题,但当时 阅读详情

传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.youkuaiyun.com/leverage_1229

        最近单位来了一个Android4.1平台的360街景项目。在编写该项目demo的过程中,为了省事,打算直接在UI线程中访问网络数据源并生成Bitmap以填充相应的视图。访问网络模块的封装采用了HttpClient的方式进行构建。编写完工后执行程序,发现视图显示的还是本地的默认图样。在确认了网络权限已被开启的情况下,我开始怀疑是不是HttpClient封装的粒度过大,导致其适用范围受限的问题。于是干脆采用Java平台最底层的Socket套接字方式来实现网络访问,可是结果还是一样的,仍旧无法得到网络数据。经过调试发现,在客户端发出请求之后,根本无法连接到服务端,也就无法解析后续的服务端的响应内容了。

        以前在Android2.3.3平台上研发怎么没有这个现象?难道是Android4.0的单线程模式的“禁令”较之以往更为严格了。为了使应用程序具有更好的交互性和更少的延迟时间,强势要求开发人员在UI主线程中只能执行与UI相关的工作(如:更新视图、与用户交互等),其他方面的工作一律禁止执行。为了验证这个相反,在stackoverflow.com检索了相关议题,从一位Google工程师的解答中基本得到了印证。也就是说,如果你非要在UI主线程中执行其他工作(如:访问网络、文件操作等),其实有这种编程强迫症的人在项目初期还是很多的,笔者就是其中的一位。你需要为UI主线程所在的Activity设置线程策略,告知平台请赋予我在UI主线程中进行其他工作的权限。具体做法有如下:

        在你的Application、Activity或其它应用容器中添加如下代码:

 public void onCreate() {
     if (DEVELOPER_MODE) {
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads() // 捕捉读取磁盘
                 .detectDiskWrites() // 捕捉写入磁盘
                 .detectNetwork()   // 捕捉网络访问 或使用detectAll() 火力全开
                 .penaltyLog() // 捕捉LogCat日志
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());
     }
     super.onCreate();
 }

StrictMode类

        StrictMode是一个开发者工具类,从Android 2.3平台开始被引入。可以用于捕捉发生在应用程序UI主线程中耗时的IO操作、网络访问或方法调用;也可以用来改进应用程序,使得UI主线程在处理IO操作和访问网络时显得更平滑,避免其被阻塞,导致ANR警告。更多有关StrictMode的信息,请参见http://developer.android.com/reference/android/os/StrictMode.html。

        这种非常规的做法,是在项目初期和开发模式下为了达到更高的效率,而采取一种提高生产效率做法。在产品交付和运维时,我们还是要严格遵守Android平台进程与线程安全管理机制。接下来是在实际开发中应该遵循的两个原则:

UI主线程

        在UI主线程中,只处理与UI相关及用户交互的工作,耗时的工作一律交由后台工作线程去搭理。常见的耗时工作处理方式有:

AsyncTask;

Handler、MessageQueue、Looper;

ExecutorService(execute/submit)

工作线程

        在工作线程中,只做自己分内的事。决不干涉UI主线程的工作。在执行过程中如果存在涉及到UI的操作(如:更新视图、重绘等),一律将其转交给UI主线程进行处理。常见的转交方式有:

Activity.runOnUiThread(new Runnable(){...});

View.post(new Runnable(){...});

View.postDelay(Runnable(){...},long)

示例

        最后,提供AsyncMultiThreadActivity演示Android多线程与UI交互的方式,仅供读者参考使用。

public class AsyncMultiThreadActivity extends Activity {  
   
    private TextView txView;  
    private Button button;  
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) {  
        Log.i("RootyInfo", "oncreate");  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);      
           
        txView=(TextView)findViewById(R.id.textView1);  
        button=(Button)findViewById(R.id.button1);  
        button.setOnClickListener(new OnClickListener() {  
               
            @Override 
            public void onClick(View v) {
                   
                //创建一个用于展示前三种后台线程和UI线程交互的线程  
                new TestThread(MainActivity.this).start();  
                   
                //创建一个用于展示AsyncTask实现交互的TestAsyncTask  
                new TestAsyncTask().execute("Test"," AsyncTask");  
            }  
        });  
    }  
       
       
    class TestAsyncTask extends AsyncTask<String, Integer, String> {  
        //TestAsyncTask被后台线程执行后,被UI线程被调用,一般用于初始化界面控件,如进度条  
        @Override 
        protected void onPreExecute() {  

            super.onPreExecute();  
        }  
   
        //doInBackground执行完后由UI线程调用,用于更新界面操作  
        @Override 
        protected void onPostExecute(String result) {  

            txView.setText(result);  
            super.onPostExecute(result);  
        }  
   
        //在PreExcute执行后被启动AysncTask的后台线程调用,将结果返回给UI线程  
        @Override 
        protected String doInBackground(String... params) {  

            StringBuffer sb=new StringBuffer();  
            for (String string : params) {  
                sb.append(string);  
            }  
            return sb.toString();  
        }  
           
    }
  
    //用于线程间通信的Handler  
    class TestHandler extends Handler {  
           
        public TestHandler(Looper looper) {  
            super(looper);  

        }  
   
        @Override 
        public void handleMessage(Message msg) {  

            System.out.println("123");  
            txView.setText((String)msg.getData().get("tag"));  
            super.handleMessage(msg);  
        }  
           
    } 
 
    //后台线程类  
    class TestThread extends Thread {  
        Activity activity;  
        public TestThread(Activity activity) {       
            this.activity = activity;  
        }  
        @Override 
        public void run() {  
               
            // 演示Activity.runOnUIThread(Runnable)方法的实现  
            activity.runOnUiThread(new Runnable() {               
                @Override 
                public void run() {  

                    txView.setText("Test runOnUIThread");  
                }  
            });  
               
            // 演示Activity.runOnUIThread(Runnable)方法的实现  
            txView.post(new Runnable() {  
                   
                @Override 
                public void run() {  

                    txView.setText("Test View.post(Runnable)");  
                }  
            });  
               
            // 演示Activity.runOnUIThread(Runnable)方法的实现  
            txView.postDelayed(new Runnable() {  
                   
                @Override 
                public void run() {  

                    txView.setText("Test View.postDelay(Runnable,long)");  
                }  
            }, 1000);  
               
            // 演示Handler方法的实现  
            Message msg=new Message();  
            Bundle bundle=new Bundle();  
            bundle.putString("tag", "Test Handler");  
            msg.setData(bundle);              
            new TestHandler(Looper.getMainLooper()).sendMessage(msg);  
                       
            super.run();  
        }  
           
    }  
      
}
Android性能优化-StrictMode(严苛模式) 1.什么是严苛模式严苛模式是一个开发工具,能够检测程序中的违例,从而修复。最常用的地方就是主线程中disk的读写和network。目前能有两大策略,线程策略(ThreadPolicy)和Vm策略(VmPolicy)。2.如何使用在Application、Activity的onCreate的supper.onCreate之间配置。 public void onCreate() { if (D 阅读详情

相关推荐

Android严苛模式StrictMode使用详解

StrictMode类是Android 2.3 (API 9)引入的一个工具类,可以用来帮助开发者发现代码中的一些不规范的问题,以达到提升应用响应能力的目的

读书笔记 Pro Android 3 第2章 节选 StrictMode 严苛模式

Android 2.3提供一个称为严苛模式(StrictMode)的调试特性,Google称该特性已经使数百个Android上的Google应用程序受益。那它都做什么呢?它将报告与线程及虚拟机相关的策略违例。一旦检测到策略违例(policy violation),你将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。你可以强制用警告代替崩溃(crash),也可以仅将警告计入日志,让你的

Tonyfield的专栏 5060

芯片硅前验证技术与驱动工程师实战指南

硅前验证是芯片开发流程中的关键环节,通过pre-silicon simulation等技术手段在流片前验证设计正确性。其核心技术包括软件仿真、FPGA原型验证和硬件仿真器解决方案,涉及Linux驱动开发、芯片架构理解和波形分析等核心技能。作为连接芯片设计与系统集成的桥梁,硅前验证能早期发现设计缺陷,节省数百万美元流片成本。以Cadence Palladium为代表的硬件仿真器,通过专用服务器系统实现比纯软件方案快100-1000倍的仿真速度,为驱动工程师提供完整的外设模型验证环境。掌握硅前验证技术可显著提升

weixin_42522857的博客 324

Android:StrictMode(严苛模式)

从Android 2.3开始提供了一个新的类StrictMode,该类可以用于捕捉发生在应用程序主线程中耗时的磁盘、网络访问或函数调用,可以帮助开发者改进程序,使主线程处理UI和动画在磁盘读写和网络操作时变得更平滑,避免主线程被阻塞。 ANR窗口产生的原因是多种多样的。程序的主线程因为IO读写或网络阻塞而导致被阻塞了,外部存储设备被独占了或系统负荷(load)过高(即不是自己编写的程序的问题,可能

BAOLIANG196的博客 846

JWT实战:5分钟搞定Spring Boot集成JWT认证(含完整代码示例)

本文详细介绍了如何在Spring Boot中快速集成JWT认证,提供完整的代码示例和配置指南。通过JWT实现无状态认证,解决分布式系统中的会话管理问题,提升系统扩展性和安全性。涵盖令牌生成、验证、Spring Security整合及生产级优化方案。

weixin_29327525的博客 456

金蝶K3系统物料主数据后台表对应字段一览

我们说到物料表,一般是指t_icitem,但正确的说t_icitem并不是一张有,而是一张视图,不过我们对于数据库物料表中的大部分操作,都是通过此视图来完成。比如经常通过此视图,来成批修改数量,单价精度,是否启用批次等一些字段,有的时候,对于账套已经启用,并且已经有业务发生的物料,有一些关键属性也需要通过修改物料表t_icitem来进行。 当然修改的时候,需要考虑一些前提条件的。 比如说我有一个客户新建的账套,在月底结账时发现,要改一种成本核算方法,启用时用的是加权平法,现在想改成移动平均法,这样的情况,

hzfw2008的博客 1万+

android 严苛模式,Android严苛模式StrictMode使用详解

StrictMode类是Android 2.3 (API 9)引入的一个工具类,可以用来帮助开发者发现代码中的一些不规范的问题,以达到提升应用响应能力的目的。举个例子来说,如果开发者在UI线程中进行了网络操作或者文件系统的操作,而这些缓慢的操作会严重影响应用的响应能力,甚至出现ANR对话框。为了在开发中发现这些容易忽略的问题,我们使用StrictMode,系统检测出主线程违例的情况并做出相应的反应...

weixin_28795851的博客 663

风力发电机并网模型建立及仿真验证

传统能源日益匮乏,环境污染日趋严重,全球向安全、可靠和环保的可持续能源体系转型迫在眉睫,风电迎来了重要的发展契机。近年来,全球风电迅猛发展,我国已成为世界风电新增装机容量第一的国家。然而,随着风电规模的不断增大,风电场接入对系统影响不容忽视。随着变速恒频风力发电系统优越的性能突出和大容量电力电子技术的成熟,风速随机性引起的功率波动及故障情况下的动态响应,对电能质量,系统电压、频率的稳定性产生的影响需要深入研究。因而,本文结合实际项目,针对变速恒频风力发电系统建模,端口动态特性及对电网电能质量、运行稳定性的影

毕业设计区博客 1641

[置顶] 使用严苛模式打破Android4.0以上平台应用中UI主线程的“独断专行”

传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229         已经有好一段时间没有关注Android应用方面的事情了:)最近单位来了一个Android4.1平台的360街景项目。在编写该项目demo的过程中,为了省事,打算直接在UI线程中访问网络数据源并生成Bitmap以填充相应的视图。访问网络模块的封装采用了HttpClien...

weixin_34408717的博客 95

5G射频设计中N77&N79的PRX为什么需要3个SRS

首先,我们来逐个拆解一下这个神秘的“

weixin_43199439的博客 1324

NXP S32k3 MCAL EMIOS PWM配置

NXP s32k 配置 EMIOS PWM

Leon_0125的博客 2702

Android内存管理与性能优化面试真题

概念解析:LRU算法的⼯程实现 LruCache(Least Recently Used,最近最少使⽤)是Android提供的⼀个核⼼缓存⼯具类。它的设计理念⾮常符合⼈类直觉:“如果⼀个数据最近被访问过,那么它在未来被访问的概率12 / 38极⾼;反之,如果⼀个数据很久没被碰过,当内存吃紧时,它就应该第⼀个被踢出局。” 在源码层⾯,LruCache 的底层⼼脏是⼀个 LinkedHashMap。

qq_52269550的博客 689

YOLOv8极速瘦身实战:LAMP剪枝让模型又快又准

一个庞大的模型虽然强大,但在实际部署,尤其是资源受限的边缘设备(如无人机、移动电话、嵌入式系统)上,却面临着严峻的挑战:高昂的内存占用、巨大的计算量以及随之而来的高延迟和高能耗。本教程从LAMP剪枝的深刻理论出发,详细解释了它如何通过最小化最坏情况下的L2失真,并借助巧妙的数学简化,最终推导出一种高效、无超参数、层自适应的剪枝策略。它如同为臃肿的模型进行一次精准的“瘦身手术”,通过移除网络中冗余或不重要的权重、神经元甚至整个结构,来显著降低模型的参数量和计算量(FLOPs),从而实现推理加速和资源节约。

FJN110的博客 258

从救火到防火:亿级App客户端安全生产体系架构与工程实践

在软件工程领域,质量保障与风险防控是确保应用稳定性的核心。其基本原理在于通过系统化的手段,在软件开发生命周期的各个阶段建立防线,将问题拦截在早期。这套体系的技术价值在于,它能将被动的问题响应(救火)转变为主动的风险预防(防火),显著提升交付效率与用户体验。在应用场景上,尤其适用于用户体量大、迭代频繁的移动客户端。本文以【灰度发布】和【全链路可观测性】为关键切入点,深入解析如何构建一个覆盖代码提交、集成构建、发布与线上监控的纵深防御体系,实现从研发到运维的全面质量内建与风险可控。

Liusuzhi19610221的博客 1021

置顶必读(1) | 《YOLOv26实战:从入门到深度优化》专栏导读与完整目录导航(持续更新中)

🏆 本文收录于 《YOLOv26实战:从入门到深度优化》 专栏。 本专栏系统梳理并持续复现 YOLOv26 官方特性、核心改进、多任务支持、部署优化与行业落地,内容坚持 持续更新 + 深度拆解 + 工程落地导向,不仅讲“怎么用”,更讲“为什么这样设计、如何真正落地到项目中”。

**My Coding Family** 9万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

android 严苛模式,Android- 严苛模式(StrictMode)

写程序时,你应该始终假定下列两种情况:网络很慢(你正在试图连接的服务器甚至可能没有响应);文件系统的访问速度很慢。结论就是,不应该在主线程内进行网络操作或访问文件系统,因为缓慢的操作会拖累系统的响应能力。虽然在开发环境中,你可能永远不会遇到任何网络问题或任何文件系统的性能问题,但用户可能不像你那么幸运。注意SD卡并不都具有相同“速度”,如果应用在很大程度上依赖外部存储设备的性能,那么你应该确保在...

weixin_28738173的博客 210

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Android StrictMode 详解

Android 2.3提供一个称为严苛模式(StrictMode)的调试特性,Google称该特性已经使数百个Android上的Google应用程序受益。它将报告与线程及虚拟机相关的策略违例。一旦检测到策略违例(policy violation),将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。可以强制用警告代替崩溃(crash),也可以仅将警告计入日志,让你的应用继续执行 St

chenshun123的博客 2570

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Android严格模式

(3)StrictMode是建立在BlockGuard和CloseGuard之上的机制,Guard表示守卫,Block表示阻塞,在进行一些耗时操作时,譬如磁盘读写、网络操作,有一个守卫在监测着,它就是BlockGuard,如果这些耗时的操作导致主线程阻塞,BlockGuard就会发出通知,Close对应可打开的文件,在文件被打开后,也有一个守卫在监测着,它就是CloseGuard,如果没有关闭文件,则CloseGuard就会发出通知。比如文件流未关闭,打印的日志提示如下,可根据堆栈找到导致问题的地方。

dodod2012的专栏 948

Android 严苛模式(StrictMode)

ggh990640782的专栏 344

严苛模式(StrictMode)

Android 2.3提供一个称为严苛模式(StrictMode)的调试特性,Google称该特性已经使数百个Android上的Google应用程序受益。那它都做什么呢?它将报告与线程及虚拟机相关的策略违例。一旦检测到策略违例(policy violation),你将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。你可以强制用警告代替崩溃(crash),也可以仅将警告计入日志,让你的...

he91-com 286
上一篇: 某大型银行深化系统之十八:性能设计之三
下一篇: Android应用开发之版本更新你莫愁
innovation
博客等级 码龄14年 251粉丝 136原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值