LeakCanary的使用及Application类的使用

来源:互联网 发布:vb编程软件中文下载 编辑:程序博客网 时间:2024/05/30 04:04

Application类

Application和Activity,Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个Application对象,用来存储系统的一些信息。

Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个,所以Application可以说是单例(singleton)模式的一个类。

通常我们是不需要指定一个Application的,系统会自动帮我们创建,如果需要创建自己的Application,那也很简单!创建一个类继承Application并在AndroidManifest.xml文件中的application标签中进行注册(只需要给application标签增加name属性,并添加自己的 Application的名字即可)

启动Application时,系统会创建一个PID,即进程ID,所有的Activity都会在此进程上运行。那么我们在Application创建的时候初始化全局变量,同一个应用的所有Activity都可以取到这些全局变量的值,换句话说,我们在某一个Activity中改变了这些全局变量的值,那么在同一个应用的其他Activity中值就会改变。

Application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以可以通过Application来进行一些,如:数据传递、数据共享和数据缓存等操作。

应用场景:

在Android中,可以通过继承Application类来实现应用程序级的全局变量,这种全局变量方法相对静态类更有保障,直到应用的所有Activity全部被destory掉之后才会被释放掉。

LeakCanary的使用

简单粗暴的方法:

LeakCanary作为一个简单粗暴的工具,用法也相当简单

在build.gradle中引入LeakCanary

[java] view plaincopy
  1. debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'  
  2.     releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'  


一个是debug包,一个是release包的,从引入包的结构也能看出端倪

由于LeakCanary是测试整个app的内存泄露情况,所以你需要在你的application中启动它

[java] view plaincopy
  1. package com.zimo.guo;  
  2.   
  3. import android.app.Application;  
  4.   
  5. import com.squareup.leakcanary.LeakCanary;  
  6.   
  7. /** 
  8.  * Created by zimo on 15/8/7. 
  9.  */  
  10. public class MyApplication extends Application {  
  11.   
  12.     @Override  
  13.     public void onCreate() {  
  14.         super.onCreate();  
  15.         LeakCanary.install(this);  
  16.     }  
  17. }  

ok,现在就可以测试程序中的内存泄露情况,直观明了

中规中矩的方法:

参考:https://github.com/SOFTPOWER1991/leakcanarySample_androidStudio

1.将leakCanary import as module 并添加依赖


2.新建一个Application

/* * Copyright (C) 2015 Square, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package my.test.com.leakcanarydemo;import android.app.Application;import android.content.Context;import android.os.StrictMode;import com.squareup.leakcanary.LeakCanary;import com.squareup.leakcanary.watcher.RefWatcher;import static android.os.Build.VERSION.SDK_INT;import static android.os.Build.VERSION_CODES.GINGERBREAD;public class ExampleApplication extends Application {    public static RefWatcher getRefWatcher(Context context) {        ExampleApplication application = (ExampleApplication) context                .getApplicationContext();        return application.refWatcher;    }    private RefWatcher refWatcher;    @Override    public void onCreate() {        super.onCreate();        enabledStrictMode();        refWatcher = LeakCanary.install(this);    }    private void enabledStrictMode() {        if (SDK_INT >= GINGERBREAD) {            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() //                    .detectAll() //                    .penaltyLog() //                    .penaltyDeath() //                    .build());        }    }}
3.修改Manifest +声明2个service和一个activity

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="my.test.com.leakcanarydemo">    <application        android:name=".ExampleApplication"        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <service            android:name="com.squareup.leakcanary.internal.HeapAnalyzerService"            android:enabled="false"            android:process=":leakcanary" />        <service            android:name="com.squareup.leakcanary.DisplayLeakService"            android:enabled="false" />        <activity            android:name="com.squareup.leakcanary.internal.DisplayLeakActivity"            android:enabled="false"            android:icon="@drawable/__leak_canary_icon"            android:label="@string/__leak_canary_display_activity_label"            android:taskAffinity="com.squareup.leakcanary"            android:theme="@style/__LeakCanary.Base">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <activity            android:name=".Main2Activity"            android:label="@string/title_activity_main2"            android:theme="@style/AppTheme.NoActionBar"></activity>    </application></manifest>
4.在入口Activity中 写下如下代码:

RefWatcher refWatcher = ExampleApplication.getRefWatcher(this);refWatcher.watch(this);
5.写一个会发生泄露的Activity

package my.test.com.leakcanarydemo;import android.os.Bundle;import android.support.design.widget.FloatingActionButton;import android.support.design.widget.Snackbar;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.Toolbar;import android.view.View;import com.squareup.leakcanary.watcher.RefWatcher;public class Main2Activity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main2);        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);        setSupportActionBar(toolbar);        new Thread(){            @Override            public void run() {                super.run();                while(true)                {                }            }        }.start();    }}
当按下back后 

会在logcat中看到如下:

12-30 11:54:28.093 17194-18495/my.test.com.leakcanarydemo D/LeakCanary: In my.test.com.leakcanarydemo:1.0:1.
                                                                        * my.test.com.leakcanarydemo.Main2Activity has leaked:
                                                                        * GC ROOT thread my.test.com.leakcanarydemo.Main2Activity$1.this$0 (named 'Thread-5930')
                                                                        * leaks my.test.com.leakcanarydemo.Main2Activity instance

在 leaks Activity中看到


0 0