android studio内存分析初探

Android内存分析demo

1.前言

    这段时间打算换工作,所以没有负责新的项目,主要为已有项目加注释和文档,刚好空余了点时间就想对以前项目遇到的一个问题做
一个分析,项目有一个需求是acticity保持不被销毁,结果在低配置手机上出现了问题.
    刚好这几天看到android studio在1.5开始支持进行内存分析,所以对这方面知识做个梳理

2.一些思考

    不知道大家有没有考虑过一个问题,在android中actiity service这种可以保持长时间运行的组件是不允许new对象的,而
广播如果你运行超过10秒就会出现anr异常,所以也就没这方面的问题.我觉得有一方面的考录就是为了使组件之间相互隔离,从而就可以
使用隐式意图启动.
    结合这一点,那么我们对内存分析的意义出发点就可以确定的,我们知道,一个对象能不能被回收取决于有没有引用指向它,当然
还要考虑循环引用的问题,这一点垃圾回收算法也会认为是可回收的.所以我们队内存泄露的检测就有了一个大概的路劲了.

3.内存分析的流程

    既然我们知道了activity是不允许new的,那么当我们启动一个activity的时候,这个activity的引用是应用层框架所持有的,
理论上,当我们activity的destory方法执行后,如果这个activity没有销毁,那么我们就可以认为发生了这个activity发生了内存泄露.
    既然activit发生了内存泄露,那么这个activity对象就没办法被回收,里面的view、比如说mvp中presenter层所引用的对象
,model层对象也就都没办法被回收,这样的代价难免有点大.所以我们这里分析主要从activity开始。

4.开工

先卡看我们的项目目录结构

这里写图片描述

在这里我们采用的是mvp。

  • M MODEL,这里我们主要进行数据的处理,比如说从网络、数据库
  • V View,这里是用户界面了,这里我们专注于动作,比如说从用户界面获取用户名,获取密码,
  • P Presenter,在这里我们专注于逻辑,用于连接view和model我们可以看看我们presenter层的代码。
    这里写图片描述
    代码很少,检测用户名、密码成功就执行登录,同时回调view界面的preparLogin()方法用于显示登录前的提醒
    而view层每一个方法都专注于一类事情比如说我们这里
    这里写图片描述
    再来看看我们实现类
    public class LoginActivity extends AppCompatActivity implements ILoginActivity {

      private TextView userName;
      private TextView password;
      private Button loginButton;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_login);
          userName = (TextView) findViewById(R.id.email);
          password = (TextView) findViewById(R.id.password);
          loginButton = (Button) findViewById(R.id.email_sign_in_button);
          final Presenter presenter = new Presenter(this, this);
    
          loginButton.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  presenter.login();
              }
          });
    
    
      }
    
      @Override
      public String getUserName() {
          return userName.getText().toString();
      }
    
      @Override
      public String getPassword() {
          return password.getText().toString();
      }
    
      @Override
      public boolean checkUserName() {
          if (getUserName().length() > 0) {
              return true;
          } else {
              Toast.makeText(this, "用户名不合法", Toast.LENGTH_SHORT).show();
              return false;
          }
      }
    
      @Override
      public boolean checkPassword() {
          if (getUserName().length() > 0) {
              return true;
          } else {
              Toast.makeText(this, "密码不合法", Toast.LENGTH_SHORT).show();
              return false;
          }
      }
    
      @Override
      public void preparLogin() {
          Toast.makeText(this, "显示进度条", Toast.LENGTH_SHORT).show();
      }
    
      @Override
      public void LoginFinish() {
          Toast.makeText(this, "关闭进度条" + "进入主页", Toast.LENGTH_SHORT).show();
          Intent intent = new Intent(this, MainActivity.class);
          startActivity(intent);
          finish();
      }
    
      @Override
      public void LoginFailed(String massage) {
          Toast.makeText(this, "登录失败了,失败原因是" + massage, Toast.LENGTH_SHORT).show();
    
      }
    

    }
    大概思路,用户点击登录,判断用户名密码,如果用户名或者密码不合法进行提醒,如果合法登录,登录成功进入主页,同时关闭页面
    model层只有一个asyncTask延时5秒返回登录成功我们不在阐述了。

handle导致内存泄露

引起activity出现内存泄露的原因有很多,这里我们看一个我们比较容易模拟的问题

这里写图片描述
上面图中我们可以看到,代码出现警告了,提示我们使用静态的,原来我们非静态的内部类会持有外部类的引用,而handel我们发送
了一个延时消息,handle要成功执行handleMassage方法,那么必然的消息队列中会持有handle的引用,从而就造成的activity
不能被成功销毁,。

我们结合memory monitor来看看我们的代码

*   1.进入loginActivity点击登录,登录成功进入主页,同时finish当前页面。
*   2.这时候我们到下面页面,点击箭头所指向的小车,手动的启动一次垃圾回收 

这里写图片描述

这里写图片描述
这里写图片描述
* 1.导出java堆的详细日志
* 2 and 3.按照包名找到我们的activity
* 4.这个loginActivity.class只有一个实例,但是我们已经finish()同时在测试前启动了垃圾回收,照理说他应该被回收
* 5.既然activity没有被回收,我们看看谁持有他的引用,android.os.messageQueue,是一个消息队列引用着他,
也就是我们的handel,当然关于handel的运行原理大家可以移步

handler详解

总结

当然了,以上只是我们的一个初步探索,在我们实际生产环境中可能要结合我们的业务逻辑,以及内存分配时间轴比如说短时间内内存急剧
升高然后又急剧下降,也就是内存抖动了,那么久意味着内存在快速的分配,同时快速的被回收。或者某些情况下内存居高不下等等原因进行
分析。

代码地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值