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
由于LeakCanary是测试整个app的内存泄露情况,所以你需要在你的application中启动它
中规中矩的方法:
参考: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中看到