精通安卓性能优化-第一章(八)

懒汉式初始化(Lazy initializations)

延迟确实有它的好处。一个通常情况是在一个component的onCreate()方法去执行所有的初始化。这样做意味着onCreate()需要更长时间返回值。这在你的应用activity里面非常重要:因为onStart()在onCreate()执行完之前不会被调用到(同样onResume()不会在onStart()返回之前执行),会使得应用需要更多的时间去启动,可能会让用户失望。

比如,安卓的android.view.ViewStub使用懒汉初始化思想,用来在运行时inflate资源。当view stub可见的时候,被相应的infalted资源替换掉,并且可以被资源回收机制回收。

因为内存的分配需要时间,等到一个对象确实需要的时候才去分配它是一个好的选择。当一个对象很可能根本不需要的时候,对它进行懒汉式分配的好处是很明显的。基于Listing 1-13,Listing 1-14给出了懒汉式初始化的一个实例。为了避免经常去检查对象是否是null,考虑工厂模式。

Listing 1-14 懒汉式分配Cache

int n = 100;
if (cache == null) {
    // createCache()分配了cache对象,可能会在许多地方调用
    cache = createCache();
}

BigInteger fN = cache.get(n);
if (null == fN) {
    fN = Fibonacci.computeRecursivelyWithCache(n);
    cache.put(n, fN);
}

参考第8章去学习怎么在布局文件中使用android.view.ViewStub和怎么样去懒汉式inflate资源。

StrictMode

在开发应用程序的时候,你需要经常假设如下两件事情存在:
(1) 网络很慢(你试图去连接的服务器甚至都没有回应)
(2) 文件系统的访问很慢

作为结果,不要在应用的主线程去做任何网络或者文件系统访问的尝试,因为耗时操作会影响到响应。即使在你的开发环境中可能不会遇到任何的网络问题或者文件系统性能问题,但是你的用户可能没有你这么好运。

NOTE:不是所有的SD卡有同样的速度。如果你的应用很依赖于外部存储的性能,你需要保证使用不同厂商的SD卡去测试应用。

Android提供了一个工具帮助开发者在应用中检测这样的问题。StrictMode是这样一个工具,尽最大可能去检测不好的行为。通常,当应用开始的时候你需要开启StrictMode,比如, 当onCreate()方法被调用,如Listing 1-15所示。

Listing 1-15 在应用中开启StrictMode

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        StrictMode.setTreadPolicy(new StrictMode.ThreadPolicy.Builder()
        .detectCustomSlowCalls()	// API 11,使用StrictMode.noteSlowCode
        .detectDiskReads()
        .detectDiskWrites()
        .detectNetwork()
        .penaltyLog()
        .penaltyFlashScreen()    // API 11
        .build()
        );
        
        // 不是真正的性能相关,但是如果你使用StrictMode,最好也定义一个VM policy
        StrictMode.setVmPolicy(
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
        .detectLeakedSqlLiteObjects()
        .detectLeakedClosableObjects()    // API 11
        .setClassInstanceLimit(Class.forName("com.apress.proandroid.SomClass"), 100) // API 11
        .penaltyLog()
        .build()
        );
        
    }
}

StrictMode在安卓2.3引入,在3.0的时候添加了很多功能,所以你需要保证你的target安卓版本正确,保证你的应用在合适的平台执行,如Listing 1-12所示。
需要注意的是,在安卓3.0引入的一些方法包括detectCustomSlowCall()和noteSlowCall(),都用来检测应用中耗时或者潜在的耗时代码。Listing 1-16演示了如何标记你的代码比如潜在的耗时操作。

Listing 1-16 Marking Your Own Code as Potentially Slow

public class Fibonacci {
    public static BigInteger computeRecursivelyWithCache(int n) {
        StrictMode.noteSlowCall("computeRecursivelyWithCache");    // 可以是任何的打印内容
        SparseArray<BigInteger> cache = new SparseArray<BigInteger>();
        return computeRecursivelyWithCache(n, cache);
    }
    
    ...
}

如果StrictMode线程策略被配置成检测耗时调用,在主线程对耗时操作computeRecursivelyWithCache进行调用将会导致如下的log:

StrictMode policy violation; ~duration=21121 ms:
android.os.StrictMode$StrictModeCustomViolation: policy=31 violation=8 msg=computeRecursivelyWithCache

安卓提供一些辅助方法使得允许在主线程临时读写硬盘更加简单,如Listing 1-17所示。

Listing 1-17 修改线程策略允许临时读写硬盘

StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();    // 从硬盘读取something
StrictMode.setThreadPolicy(oldPolicy);

没有方法用来临时允许网络访问,没有任何理由在主线程允许这样的访问甚至是临时的,因为没有合理的方式去知道这个访问是否是快速的。有人可能会争论同样没有合理的方式去知道是否硬盘访问是快速的,但是那是另外一个争论。

NOTE:仅仅在开发过程中开启StrictMode,记得发布你的应用的时候禁用它。这样是正确的,更加需要注意的是设置策略的时候使用detectAll()方法,因为将来的版本可能会去检测更多的不好行为。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值