iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Android项目中哪些情况会出现内存泄漏
  • 420
分享到

Android项目中哪些情况会出现内存泄漏

android内存泄漏roi 2023-05-31 08:05:47 420人浏览 安东尼
摘要

今天就跟大家聊聊有关Android项目中哪些情况会出现内存泄漏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1、单例造成的内存泄漏Android的单例模式非常受开发者的喜爱,不过使用

今天就跟大家聊聊有关Android项目中哪些情况会出现内存泄漏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

1、单例造成的内存泄漏

Android的单例模式非常受开发者的喜爱,不过使用的不恰当的话也会造成内存泄漏。因为单例的静态特性使得单例的生命周期和应用的生命周期一样长,这就说明了如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。

public class SingleInstance {  private static SingleInstance instance;  private Context context;  private SingleInstance(Context context) {    this.context = context;  }  public synchronized static SingleInstance getInstance(Context context) {    if (instance != null) {      instance = new SingleInstance(context);    }    return instance;  }}

这是一个普通的单例模式,大家都知道,静态变量最大的特点是什么,常驻内存,也就是说如果你的APP的进程没有没杀死,它就一直在内存中。当创建这个单例的时候,由于需要传入一个Context,所以这个Context的生命周期的长短至关重要:如果传入的是Activity的Context:当这个Context所对应的Activity退出时,由于该Context和Activity的生命周期一样长(Activity间接继承于Context),所以当前Activity退出时它的内存并不会被回收,因为单例对象持有该Activity的引用。

所以正确的单例应该为这种姿势:

public class SingleInstance {  private static SingleInstance instance;  private Context context;  private SingleInstance(Context context) {    this.context = context.getApplicationContext();  }  public synchronized static SingleInstance getInstance(Context context) {    if (instance != null) {      instance = new SingleInstance(context);    }    return instance;  }}

这样不管传入什么Context最终将使用Application的Context,而单例的生命周期和应用的一样长,这样就防止了内存泄漏。

2、非静态内部类(比如内部类、匿名内部类)创建静态实例造成的内存泄漏

有的时候我们可能会在启动频繁的Activity中,为了避免重复创建相同的数据资源,会出现这种写法:

public class MainActivity extends AppCompatActivity {  private InnerClass innerClass;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    if(innerClass == null){      innerClass = new InnerClass();    }  }  class InnerClass{  }}

这样就在Activity内部创建了一个非静态内部类的单例,每次启动Activity时都会使用该单例的数据,这样虽然避免了资源的重复创建,不过这种写法却会造成内存泄漏,因为非静态内部类默认会持有外部类的引用,而又使用了该非静态内部类创建了一个静态的实例,该实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该Activity的引用,导致Activity的内存资源不能正常回收。

正确的做法为:将该内部类设为静态内部类或将该内部类抽取出来封装成一个单例,如果需要使用Context,请使用ApplicationContext 。

3、Handler造成的内存泄漏

Handler的使用造成的内存泄漏问题应该说最为常见了,平时在处理网络任务或者封装一些请求回调等api都应该会借助Handler来处理,对于Handler的使用代码编写一不规范即有可能造成内存泄漏,如下示例:

public class MainActivity extends AppCompatActivity {  private Handler mHandler = new Handler() {    @Override    public void handleMessage(Message msg) {      //...    }  };  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    loadData();  }  private void loadData(){    //...request    Message message = Message.obtain();    mHandler.sendMessage(message);  }}

这种创建Handler的方式会造成内存泄漏,由于mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏,所以另外一种做法为,用软引用:

public class MainActivity extends AppCompatActivity {  private MyHandler mHandler = new MyHandler(this);  private TextView mTextView ;  private static class MyHandler extends Handler {    private WeakReference<Context> reference;    public MyHandler(Context context) {      reference = new WeakReference<>(context);    }    @Override    public void handleMessage(Message msg) {      MainActivity activity = (MainActivity) reference.get();      if(activity != null){        activity.mTextView.setText("");      }    }  }  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mTextView = (TextView)findViewById(R.id.textview);    loadData();  }  private void loadData() {    //...request    Message message = Message.obtain();    mHandler.sendMessage(message);  }}

创建一个静态Handler内部类,然后对Handler持有的对象使用弱引用,这样在回收时也可以回收Handler持有的对象,这样虽然避免了Activity泄漏,不过Looper线程的消息队列中还是可能会有待处理的消息,所以我们在Activity的Destroy时或者Stop时应该移除消息队列中的消息,更准确的做法如下:

public class MainActivity extends AppCompatActivity {  private MyHandler mHandler = new MyHandler(this);  private TextView mTextView ;  private static class MyHandler extends Handler {    private WeakReference<Context> reference;    public MyHandler(Context context) {      reference = new WeakReference<>(context);    }    @Override    public void handleMessage(Message msg) {      MainActivity activity = (MainActivity) reference.get();      if(activity != null){        activity.mTextView.setText("");      }    }  }  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mTextView = (TextView)findViewById(R.id.textview);    loadData();  }//加载网络数据的回调  private void loadData() {    //...request    Message message = Message.obtain();    mHandler.sendMessage(message);  }  @Override  protected void onDestroy() {    super.onDestroy();    //移除消息队列和回调    mHandler.removeCallbacksAndMessages(null);  }}

使用mHandler.removeCallbacksAndMessages(null);是移除消息队列中所有消息和所有的Runnable。当然也可以使用mHandler.removeCallbacks();或mHandler.removeMessages();来移除指定的Runnable和Message。

当然简单点,也可以直接这样

 @Override  protected void onDestroy() {    super.onDestroy();    //移除消息队列和回调    mHandler.removeCallbacksAndMessages(null);  }

测试,有效。

4、线程造成的内存泄漏

对于线程造成的内存泄漏,也是平时比较常见的,如下这两个示例可能每个人都这样写过:

//——————test1    new AsyncTask<Void, Void, Void>() {      @Override      protected Void doInBackground(Void... params) {        SystemClock.sleep(10000);        return null;      }    }.execute();//——————test2    new Thread(new Runnable() {      @Override      public void run() {        SystemClock.sleep(10000);      }    }).start();

上面的异步任务和Runnable都是一个匿名内部类,因此它们对当前Activity都有一个隐式引用。如果Activity在销毁之前,任务还未完成, 那么将导致Activity的内存资源无法回收,造成内存泄漏。正确的做法还是使用静态内部类的方式,如下:

static class MyAsyncTask extends AsyncTask<Void, Void, Void> {    private WeakReference<Context> weakReference;    public MyAsyncTask(Context context) {      weakReference = new WeakReference<>(context);    }    @Override    protected Void doInBackground(Void... params) {      SystemClock.sleep(10000);      return null;    }    @Override    protected void onPostExecute(Void aVoid) {      super.onPostExecute(aVoid);      MainActivity activity = (MainActivity) weakReference.get();      if (activity != null) {        //...      }    }  }  static class MyRunnable implements Runnable{    @Override    public void run() {      SystemClock.sleep(10000);    }  }//——————  new Thread(new MyRunnable()).start();  new MyAsyncTask(this).execute();

这样就避免了Activity的内存资源泄漏,当然在Activity销毁时候也应该取消相应的任务AsyncTask::cancel(),避免任务在后台执行浪费资源。

5、资源未关闭造成的内存泄漏

对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。

看完上述内容,你们对Android项目中哪些情况会出现内存泄漏有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网精选频道,感谢大家的支持。

--结束END--

本文标题: Android项目中哪些情况会出现内存泄漏

本文链接: https://www.lsjlt.com/news/224480.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android项目中哪些情况会出现内存泄漏
    今天就跟大家聊聊有关Android项目中哪些情况会出现内存泄漏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1、单例造成的内存泄漏Android的单例模式非常受开发者的喜爱,不过使用...
    99+
    2023-05-31
    android 内存泄漏 roi
  • Android开发中什么情况下会出现内存泄漏
    今天就跟大家聊聊有关Android开发中什么情况下会出现内存泄漏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。 android中一个对象已经不需要了,但是其他对象还持有他的...
    99+
    2023-05-31
    android 情况下 roi
  • Java中什么情况会导致内存泄漏
    这篇文章主要讲解了“Java中什么情况会导致内存泄漏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java中什么情况会导致内存泄漏”吧!概念内存泄露:指程序中动态分配内存给一些临时对象,但对...
    99+
    2023-06-16
  • JavaScript中引发内存泄漏的情况有哪些
    JavaScript中引发内存泄漏的情况有哪些?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。JavaScript的特点1.JavaScript主要用来向HTML页面添加交互...
    99+
    2023-06-14
  • java项目中出现内存泄漏如何解决
    本篇文章为大家展示了java项目中出现内存泄漏如何解决,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向...
    99+
    2023-06-14
  • JavaScript中内存泄漏的几种情况总结
    目录1.循环引用2.定时器未清除3.DOM元素未正确删除4.全局变量未清除5.闭包未正确使用6.事件未正确解绑7.大量数据未及时清理8.使用了第三方库或框架JavaScript 中的...
    99+
    2023-05-19
    JavaScript发生内存泄漏情况 JavaScript内存泄漏解决方法 JavaScript内存泄漏
  • 浅谈JavaScript中内存泄漏的几种情况
    目录一、内存泄漏是什么?二、垃圾回收机制1、标记清除2、引用计数三、常见的内存泄漏的情况1、意外的全局变量2、定时器造成的内存泄露3、闭包4、没有清理对DOM元素的引用5、事件监听(...
    99+
    2023-05-18
    JavaScript 内存泄漏
  • java中出现内存溢出的情况有哪些
    今天就跟大家聊聊有关java中出现内存溢出的情况有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序...
    99+
    2023-06-14
  • java常见内存泄露情况有哪些
    在Java中,常见的内存泄露情况有以下几种:1. 对象无法被回收:当一个对象不再被引用,但是它仍然被某些其他对象引用,导致垃圾回收器...
    99+
    2023-08-31
    java
  • Node.js中出现内存泄漏的原因有哪些
    本篇文章给大家分享的是有关Node.js中出现内存泄漏的原因有哪些,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。内存泄漏(Memory  Leak)指由于疏忽或错误造...
    99+
    2023-06-17
  • Android内存泄漏的原因有哪些
    Android内存泄漏的原因有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在Android开发中,最容易引发的内存泄漏问题的是Context。比如Activity的Con...
    99+
    2023-06-17
  • android内存泄漏的方式有哪些
    Android内存泄漏的方式有以下几种: 非静态内部类的引用:当非静态内部类被声明为静态,它的生命周期将和外部类相同,从而避免了...
    99+
    2023-10-23
    android
  • java常见内存泄露的情况有哪些
    Java常见的内存泄漏情况包括: 对象未被正确释放:当一个对象不再被使用时,如果没有正确释放它所占用的内存,那么该对象就会造成内...
    99+
    2024-02-29
    java
  • java项目中什么情况下HashCode会出现重复
    java项目中什么情况下HashCode会出现重复?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。java的缺省算法:  public int&...
    99+
    2023-05-31
    java hashcode 情况下
  • java内存溢出的情况有哪些
    Java内存溢出指的是程序在运行过程中申请的内存超过了Java虚拟机(JVM)所能提供的最大内存限制,导致程序无法正常运行。以下是几...
    99+
    2023-10-27
    java
  • Android 5.1应用中 WebView出现内存泄漏如何解决
    今天就跟大家聊聊有关Android 5.1应用中 WebView出现内存泄漏如何解决,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。问题背景在排查项目内存泄漏过程中发现了一些由WebV...
    99+
    2023-05-31
    android webview 内存泄漏
  • android内存泄漏的解决方式有哪些
    解决Android内存泄漏的方式有以下几种:1. 避免使用静态变量:静态变量的生命周期与应用程序的生命周期相同,如果不及时释放,会导...
    99+
    2023-09-09
    android
  • Android内存泄漏导致的原因有哪些
    这篇文章主要介绍“Android内存泄漏导致的原因有哪些”,在日常操作中,相信很多人在Android内存泄漏导致的原因有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android内存泄漏导致的原因有哪些...
    99+
    2023-07-05
  • java中出现内存泄漏如何解决
    java中出现内存泄漏如何解决?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Java有哪些集合类Java中的集合主要分为四类:1、List列表:有序的,可重复的...
    99+
    2023-06-14
  • Java中出现内存泄漏与溢出如何解决
    这篇文章将为大家详细讲解有关Java中出现内存泄漏与溢出如何解决,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、浅析内存泄露( memory leak):是指程序在申请内存后,无法释放已申...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作