Android开发中的一些经验总结

计划用这篇文章把目前我在Android领域的一些看到的、用到的、想到的经验和技巧总结一下。


1. WeakReference和AsyncTask的美妙结合

为了避免开发者在UI线程上做耗时操作,Android提供了不少异步API,其中之一就是AsyncTask。而对于某些频繁操作数据库的应用(例如,Phonebook)而言,需要一种异步的并且低耗资源的(低耗是两个方面的事情,要么是你占有的多点,但是能快速释放;要么是你本身就占有的少。这两种都可以保证其它应用有资源可用)组件。所以,那就来个WeakAsyncTask吧,唔,美妙的产物,既保证占有资源的快速释放,又保证操作是异步进行。

那为什么不是soft reference呢?

这个,来看看weak和soft两者的区别:

 

    * A SoftReference should be cleared and enqueued as late as possible, that is, in case the VM is in danger of running out of memory.

    * A WeakReference may be cleared and enqueued as soon as is known to be weakly-referenced.

不用问嘛,哪里能等到vm内存快光光的时候再去释放早已不用的资源啊,那个时候可能手机的UI看起来就卡卡的了。。

下面来看段代码:

 

Java代码   收藏代码
  1. public abstract class WeakAsyncTask<Params, Progress, Result, WeakTarget> extends  
  2.         AsyncTask<Params, Progress, Result> {  
  3.     protected WeakReference<WeakTarget> mTarget;  
  4.   
  5.     public WeakAsyncTask(WeakTarget target) {  
  6.         mTarget = new WeakReference<WeakTarget>(target);  
  7.     }  
  8.   
  9.     /** {@inheritDoc} */  
  10.     @Override  
  11.     protected final void onPreExecute() {  
  12.         final WeakTarget target = mTarget.get();  
  13.         if (target != null) {  
  14.             this.onPreExecute(target);  
  15.         }  
  16.     }  
  17.   
  18.     /** {@inheritDoc} */  
  19.     @Override  
  20.     protected final Result doInBackground(Params... params) {  
  21.         final WeakTarget target = mTarget.get();  
  22.         if (target != null) {  
  23.             return this.doInBackground(target, params);  
  24.         } else {  
  25.             return null;  
  26.         }  
  27.     }  
  28.   
  29.     /** {@inheritDoc} */  
  30.     @Override  
  31.     protected final void onPostExecute(Result result) {  
  32.         final WeakTarget target = mTarget.get();  
  33.         if (target != null) {  
  34.             this.onPostExecute(target, result);  
  35.         }  
  36.     }  
  37.   
  38.     protected void onPreExecute(WeakTarget target) {  
  39.         // No default action  
  40.     }  
  41.   
  42.     protected abstract Result doInBackground(WeakTarget target, Params... params);  
  43.   
  44.     protected void onPostExecute(WeakTarget target, Result result) {  
  45.         // No default action  
  46.     }  
  47. }  

 而通常,weaktarget经常会以activity为参数,这样的话,就更为贴切的。因为context的错误引用而导致的内存溢出问题也是挺常见的。

 


2. Sqlite机制导致的饿死(ANR)
我们知道,Android的数据库是用的sqlite,而且sqlite是全局的,也就是说,对于一个Android系统实例而言,所有的程序将会共用一个sqlite database。这里就会有一个有意思的事情发生:当某个应用A正在进行某个长耗时的数据库操作时,另外一些应用B在此期间也需要进行数据库操作,但是数据库被A独占,B只能等,等着等着,超过5秒了,好吧,B被ANR了。

事实上,这种情况不总出现。前提是A的操作属于独占式的操作,B在主线程上进行数据库操作。解决方法自然也分为两种,一种是A换用批量操作API:ContentProviderOperation,用ContentProviderOperation.Builder.withYieldAllowed (true)来允许当前的数据库操作可以被挂机;另外一种是B不要在主线程里进行数据库操作。

说道这里,我更加明白了google I/O视频上那个大哥为啥说"never, never, never do slow things on UI thread"了,因为没准哪天,你就被别人ANR了。。

  

3.如何解决ANR

一个朋友去一家智能手机公司面试开发时被问到如何解决ANR的问题。正好,公司的arc前两天对解决ANR进行一些经验分享。(总结的不一定全)

1.ANR有哪几种?

从ActivityManagerService的实现可以看到,ANR有四种,分别对应Android的四个fundermetals。这个也不难理解:所有fundermetal都会在main thread上运行,如果超过了响应的间隔,那么就会ANR。另外JNI调用native函数时也会发生无响应,不过我觉得应该不算单独的一种,它只是未响应发生在了native里,而不是vm里。

2.ANR是什么?

从ActivityManagerService可以看到,作为一个manager类,要去检测所管理的对象是否处于可相应状态,一个不错的方式就是给那个对象发消息,并等待回调。事实上,就是这么做的。每隔一段时间,manager会发消息给所有fundamental,这个消息格式固定,同时带一个delay time,譬如说activity的delay time就是5000ms,当消息发出之后,5000ms之内没有收到相应,那么manager就要把那个activity ANR掉。对于broadcast receiver、provider和service也是同样的,只是delay time不一样。

以Activity为例,几个负责Activity生命周期的回调方法(以on开头的那几个),被调用后,5000ms内没有返回,那么就ANR鸟。另外还有key dispatch ANR,也就是说,当用户点击了进行了某些操作产生key event了,那么应用就必须在规定时间处理key event,如果超时,会立刻ANR。

3.ANR的导致原因

我叙述一下google I/O 2010上一个presentation上说的:就是性能问题。我们知道,一般情况下,Android系统的瓶颈经常在I/O操作,无论是本地还是网络,经常会导致程序看起来不那么顺畅,如果达到某个时间没有响应,那么就ANR鸟。我猜测,

4.如何避免ANR

"Never never never do slow things on main thread".我引用了那个presentation的原话。

5.如何解决ANR的问题

上面介绍了ANR的一些基本知识,但是在现实问题中,ANR的问题经常会比较难解决。而且每一种ANR在logcat的信息中都会有不同的。如果要了解不同ANR的特点,就需要些多个实例来观察log信息。这里需要关注的几个信息是,线程、内存、CPU、异常堆栈等信息。google貌似提供了工具来dump发生ANR时的系统及APP信息。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值