企业自己做网站的成本,泰安人才网最新消息,网络营销推广方法案例分析,wordpress中文免费企业模板下载一、非静态内部类造成的内存泄漏
造成原因#xff1a;非静态内部类默认会持有外部类的引用#xff0c;如果内部类的生命周期超过了外部类就会造成内存泄漏。
场景#xff1a;当Activity销毁后#xff0c;由于内部类中存在异步耗时任务还在执行#xff0c;导致Activity实…一、非静态内部类造成的内存泄漏
造成原因非静态内部类默认会持有外部类的引用如果内部类的生命周期超过了外部类就会造成内存泄漏。
场景当Activity销毁后由于内部类中存在异步耗时任务还在执行导致Activity实例一直被内部类持有无法被回收造成内存泄漏
例如
//TestActivity
button.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View view) {new Thread(new Runnable() {Overridepublic void run() {try {//模拟耗时Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}).start();}});此时点击返回键关闭当前Activity,页面正常回退但匿名内部类中还有耗时任务执行如果耗时任务执行完之后要刷新页面还会造成异常导致app闪退。
解决办法不使用匿名内部类并且使用static关键字修饰内部类static修饰的内部类不持有外部类的引用也自然不会造成上面的内存泄漏如果内部类中需要使用外部类的资源可以使用弱引用的方式持有外部类。
优化后的代码如下
button.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View view) {new Thread(new MyRunnable()).start();}});static class MyRunnable implements Runnable{Overridepublic void run() {try {//模拟耗时Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}二、静态成员变量造成的内存泄漏
造成原因静态成员变量的生命周期 应用程序的生命周期,如果该静态成员应用的变量生命周期 改静态变量则会造成内存泄漏
场景静态成员变量持有了一个耗费资源过多的实例Activity,Fragment)
例如
public class Person {private static Activity mActivity;Person(Activity activity){mActivity activity;}
}此时点击返回键关闭当前Activity,但Person类中的mActivity静态变量持有当前Activity的引用导致改Activity对象本该被回收而没被回收导致内存泄漏
解决办法
尽量避免 Static 成员变量引用资源耗费过多的实例如Context如果必须使用Context,可以使用Application的Context使用弱引用代替强引用持有
三、单例模式造成的内存泄漏
造成原因单例模式由于其具有静态特性导致其生命周期 应用程序生命周期如果单例中持有别的类的实例就会造成内存泄漏
场景单例模式中持有一个耗费资源过多的实例Context
例如
public class SingleInstance{private static SingleInstance instance;private Context mContext;private SingleInstance(Context context) {this.mContext context; // 传递的是Activity的context}public SingleInstance getInstance(Context context) {if (instance null) {instance new SingleInstance(context);}return instance;}
}此时由于单例中持有传入的Activity实例倒是该Activity关闭时资源得不到回收从而造成内存泄漏
解决办法
使用Application的Context代替Activity的Contex
四、Handler造成的内存泄漏
造成原因当使用非静态内部类包含匿名内部类创建Handler时Handler会持有外部类的对象如果Handler中还有消息没执行完此时创建Handler的Activity关闭就会造成内存泄漏。通常由于子线程持有handler的引用因为要发消息给handler来更新界面,handler又持有activity的引用从而导致activity不能正常被回收造成内存泄漏
场景Activity中通过一个子线程异步请求网络数据请求成功后更新当前页面。
例如
//MainActivity.javaprivate Handler mHandler new Handler(Looper.getMainLooper()){Overridepublic void handleMessage(Message msg) {//更新页面}};//成功获取到网络数据更新页面private void handleData(String data){Message message Message.obtain();message.obj data;mHandler.sendMessage(message);
}解决办法
1、静态内部类弱引用
static class MyHandler extends Handler {WeakReferenceActivity mReference;MyHandler(Activity activity) {mReference new WeakReferenceActivity(activity);}Overridepublic void handleMessage(Message msg) {final Activity activity mReference.get();if (activity ! null) {//更新页面}}
}2、activity销毁时及时清理消息
Override
protected void onDestroy() {super.onDestroy();if (mHandler ! null) {mHandler.removeCallbacksAndMessages(null);}
}五、多线程造成的内存泄漏
造成原因上面一和四其实也是多线程造成内存泄漏的场景主要是子线程中持有外部类(例如Activity)的引用让后子线程的生命周期又和Activity不同步从而造成activity被销毁时子线程中的任务还在执行从而导致activity的资源迟迟得不到回收造成内存泄漏。
六、集合类造成的内存泄漏
造成原因当我们把一些对象的引用加入到集合对象例如常用的ArrayList,当我们不需要改对象时没有从集合中清理掉改对象的引用这样集合就会越来越大如果集合时static的那问题就更严重了。
场景学生管理系统中需要统计学生信息使用一个集合存储学生信息信息统计完成把信息存入数据库后就不需要学生对象信息了但是没及时清理掉集合导致学生对象得不到回收造成内存泄漏
例如
// 通过 循环申请Person 对象并放入集合
ListPerson personList new ArrayList();for (int i 0; i 10; i) {Person p new Person();personList.add(p);
// 虽释放了集合元素引用的本身pnull
// 但集合List仍然吃药后该对象引用所以依然不可回收该对象p null;
}解决办法在不使用改集合时清理集合并把集合置为空
// 释放personList
personList.clear();
personListnull;七、WebView造成的内存泄漏
造成原因WebView中可能会进行大量的网络请求加载大量的资源从而使得内存占用过高当我们推出承载Webview的Activity时没有正确的释放WebView中的资源导致内存泄漏。
例如新闻列表页面使用WebView加载一个h5页面此时会进行大量网络请求加载新闻图片内容当我们回退该页面时加载的资源没正确释放导致内存泄漏
解决方案不使用xml定义webview,通过代码的形式传入Application的Context然后在承载webview的页面销毁时释放webview的资源
//代码初始化Webview
mWebViewnew WebView(getApplicationContext());
LinearLayout linearLayout findViewById(R.id.webview);
linearLayout.addView(mWebView);Override
protected void onDestroy() {if( mWebView!null) {// 如果先调用destroy()方法则会命中if (isDestroyed()) return;这一行代码需要先onDetachedFromWindow()再// destory()ViewParent parent mWebView.getParent();if (parent ! null) {((ViewGroup) parent).removeView(mWebView);}mWebView.stopLoading();// 退出时调用此方法移除绑定的服务否则某些特定系统会报错mWebView.getSettings().setJavaScriptEnabled(false);mWebView.clearHistory();mWebView.clearView();mWebView.removeAllViews();mWebView.destroy();}super.on Destroy();
}八、资源未释放造成的内存泄漏
造成原因对于资源的使用如 广播BraodcastReceiver、文件流File、数据库游标Cursor、图片资源Bitmap等若在Activity销毁时无及时关闭 / 注销这些资源则这些资源将不会被回收从而造成内存泄漏
解决方案 在Activity销毁时 及时关闭 / 注销资源
关闭资源代码如下
// 对于 广播BraodcastReceiver注销注册
unregisterReceiver()// 对于 文件流File关闭流
InputStream / OutputStream.close()// 对于数据库游标cursor使用后关闭游标
cursor.close// 对于 图片资源BitmapAndroid分配给图片的内存只有8M若1个Bitmap对象占内存较多当它不再被使用时应调用recycle()回收此对象的像素所占用的内存最后再赋为null
Bitmap.recycle()
Bitmap null;// 对于动画属性动画
// 将动画设置成无限循环播放repeatCount “infinite”后
// 在Activity退出时记得停止动画参考连接WebView内存泄漏–解决方法小结 - 简书 (jianshu.com)
https://juejin.cn/post/6844904067534159880