文件名称:
Android内存优化——常见内存泄露及优化方案.pdf
开发工具:
文件大小: 251kb
下载次数: 0
上传时间: 2019-07-04
详细说明:主要处理一些有关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 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
(系统自动生成,下载前可以参看下载内容)
下载文件列表
相关说明
- 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
- 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度。
- 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
- 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
- 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
- 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.