Android内存优化——常见内存泄露及优化方案.pdf

所需积分/C币:46 2019-07-04 11:28:04 251KB PDF

主要处理一些有关Android内存泄露案例以及解决方案,比如我们常见的单例模式、listView的的优化
class Info i public Info(Activity activity)i Info作为 Activity的静态成员,并且持有 Activity的引用,但是 sInfo作为静态变量,生命周期 肯定比 Activity长。所以当 Activity退出后, sInfo仍然引用了 Activity, Activity不能被回收, 这就导致了内存泄露 在 Android开发中,静态持有很多时候都有可能因为其使用的生命周期不一致而导致内存泄露, 所以我们在新建静态持有的变量的时候需要多考虑一下各个成员之间的引用关系,并且尽量少地 使用静态持有的变量,以避免发生內存泄露。当然,我们也可以在适当的时候训静态量重置为nu‖ 使其不再持有引用,这样也可以避免内存泄露 非静态内部类导致内存泄露 非静态内部类(包括匿名内部类)默认就会持有外部类的引用,当非静态内部类对象的生命周期 比外部类对象的生命周期长时,就会导致内存泄露。 非静态内部类导致的内存泄露在 Android开发中有一种典型的场景就是使用 Handler,很多开发 者在使用 Handler是这样写的 public class MainActivity extends AppCompatActivity i @Override protected void onCreate( Bundle savedInstanceState)t super onCreate(savedInstanceState) setContentview(R layout activity main)i start; private void start() Message msg Message obtain; msg. what = 1; hAndler sendMessage(msg)i private Handler mHandler new Handleroi public void handleMessage(Message msg)t if(msg. what 做应 }; 也许有人会说, hAndler并未作为静态变量持有 Activity引用,生命周期可能不会比 Activity长, 应该不一定会导致内存泄露呢,显然不是这样的! 熟悉 Handler消息机制的都知道, hAndler会作为成员变量保存在发送的消息msg中,即msg持有 hAndler的引用,而 hAndler是 Activity的非静态内部类实例,即 hAndler持有 Activity的引 用,那么我们就可以理解为mg间接持有 Activity的引用。msg被发送后先放到消息队列 MessageQueue中,然后等待 Looper的轮询处理( MessageQueue和 Looper都是与线程相关联的, MessageQueue是 Looper引用的成员变量,而 Looper是保存在 Threadloca1中的)。那么当 Activity 退出后,msg可能仍然存在于消息对列 MessageQueue中未处理或者正在处理,那么这样就会导致 Activity无法被回收,以致发生 Activity的内存泄露。 通常在 Android开发中如果要使用内部类,但又要规避内存泄露,一般都会采用静念内部类+弱 引的方式。 public class MainActivity extends AppCompatActivity t ivate handler meand lo protected void onCreate( Bundle savedInstanceState)i super onCreate(savedInstancestate); setContentview(R layout activity_ main)i hAndler new MyHandler(this); private void start t ssage msg= Message obtain(; sg. what 1 hAndler sendMessage(msg)i private WeakReference<MainActivity> activityweakReferencej public MyHandler (MainActivity activity) i activityWeakReference new WeakReference<>(activity); public void handleMes sage( Message msg)t MainActivity activity activityWeakReference get() nu11){ if (msg. What = 1)[ 做相应逻 hAndler通过弱引用的方式持有 Activity,当GC执行垃圾回收时,遇到 Activity就会回收并释 放所占据的内存单元。这样就不会发生内存泄露了。 上面的做法确实避免了 Activity导致的内存泄露,发送的msg不再已经没有持有 Activity的引用 了,但是msg还是有可能存在消息队列 MessageQueue中,所以更妤的是在 Activity销毀时就将 hAndler的回调和发送的消息给移除掉 @Overrideprotected void onDestroy()i super, onDestroy (; hAndler. removeCallbacksAndMessages(null; 非静态内部类造成内存泄露还有一种情况就是使用 Thread或者 AsyncTask。 比如在Atty中直接new一个子线程 Thread public class MainActivity extends AppCompatActivity i @Override protected void oncreate(Bundle savedInstancestate)i super onCreate(savedInstanceState); setContentView(r layout activity main) new Thread(new Runnable()i @Override public void run()t /模拟柳应耗时逻辉 try t Thread. sleep(2000): I catch (InterruptedException e)t e printstackTrace(; f). start() 或者直接新建 AsyncTask异步任务: public class MainActivity extends AppCompatActivity i @Override protected void onCreate( Bundle savedInstancestate)t super onCreate(savedInstancestate)i setContentview(R layout activity main); Override protected Void doIn Background(void.. params)i 模拟相应耗时逻 try t Thread. sleep(2000 f catch (InterruptedException e) eprintstackTrace(); return null 很多初学者都会像上面这样新建线程和异步仼务,妹不知这样的写法非常地不友好,这种方式新 建的子线程 Thread和 AsyncTask都是匿名内部类对象,默认就隐式的持有外部 ActivIty的引用, 导致 Activity内存泄露。要遥免内存泄露的话还是需要像上面 Handle一样使用静态内部类+弱 应用的方式(代码就不列了,参考上面 Hanlder的正确写法)。 未取消注册或回调导致内存泄露 比如我们在 Activity中注册广播,如果在 Activity销毁后不取消注册,那么这个刚播会一直存在 系统中,同上面所说的非静态内部类一样持有 Activity引用,导致内存泄露。因此注册广播后在 Activity销毁后一定要取消注册。 public class MainActivity extends AppCompatActivity i @Override protected void onCreate(Bundle savedInstancestate)t super oncreate(savedInstancestate); setcontentvieW(R layout activity main) this registerReceiver(mReceiver, new IntentFilter()) private BroadcastReceiver mReceiver new BroadcastReceivero f @Override public void on Receive(Contextcontext, Intent intent)t 接伙到广播需要做的逻辑 @Override protected void onDestroy()t super onDestroy (i this unregisterReceiver(rEceiver)i 在注册观察则模式的时候,如果不及时取消也会造成内存泄露。比如使用Ret⌒o千it+R×Java注册网 络请求的观察者回调,同样作为匿名内部类持有外部引用,所以需要记得在不用或者销毁的时候 取消注册。 Timer和 Timertask导致内存泄露 Timer和 Timertask在 Android中通常会被用来做一些计时或循环任务,比如实现无限轮播的 public class MainActivity extends AppCompatActivity f helP ViewPagel private PagerAdapter aDapter rivate Timer mTil ivate Timer task mTimertask tected void onCreate(Bundle savedInstancestate)t super onCreate(savedInstancestate) etContentvieW(R layout activity_ main)i mTimer. schedule(mTimerTask, 3000, 3000); mViewPager =(ViewPager) findviewById(R id view_pager aDapter new viewPager Adapter oi tAdapter(mAdapter); tImer new Timer(; mTimerTask new TimerTasko public void run()t MainActivity. this runonUiThread(new Runnable(i override public void runo f loopviewpager() ate void loopViewpager()i if(mAdapter get Count()>0) int curPos mViewPager. getcurrentItemo); curPos =(++curPos)% mAdapter get Count() mViewPager. setCurrentItem(curPos); private void stopLoopViewPager()t if (mTimer ! null)f mTimer. cancel() tImer. purge; mAimer null if (mTimerTask !=null) mTimertask. cancel; mTimertask null

...展开详情
试读 12P Android内存优化——常见内存泄露及优化方案.pdf
img
华海渡
  • GitHub

    绑定GitHub第三方账户获取
  • 签到新秀

    累计签到获取,不积跬步,无以至千里,继续坚持!

关注 私信 TA的资源

上传资源赚积分,得勋章
    最新推荐
    Android内存优化——常见内存泄露及优化方案.pdf 46积分/C币 立即下载
    1/12
    Android内存优化——常见内存泄露及优化方案.pdf第1页
    Android内存优化——常见内存泄露及优化方案.pdf第2页
    Android内存优化——常见内存泄露及优化方案.pdf第3页
    Android内存优化——常见内存泄露及优化方案.pdf第4页

    试读已结束,剩余8页未读...

    46积分/C币 立即下载 >