LeakCanary的使用及Application类的使用

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 plain copy
  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 plain copy
  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 并添加依赖

LeakCanary的使用及Application类的使用_第1张图片

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中看到

LeakCanary的使用及Application类的使用_第2张图片

你可能感兴趣的:(LeakCanary的使用及Application类的使用)