去除Android Studio内存泄漏警告Do not pla
2022-09-28 本文已影响0人
还是做个码农
当你使用单例类时,Android Studio出现了Do not place Android context classes in static fields; this is a memory leak的内存泄漏警告。
public class TestManager {
private Context mContext;
private TestManager() {
}
public void init(Context context) {
mContext = context.getApplicationContext();
Log.d("test", "init " + mContext);
}
public static TestManager getInstance() {
return Holder.INSTANCE;
}
private static class Holder {
private static final TestManager INSTANCE = new TestManager();
}
}
image.png
明明用了context.getApplicationContext()为什么还会出现警告呢?其实初始化init时传入Context这种做法是不恰当的,正确应该在构造方法就传入Application Context,但是单例类的构造方法是是私有的,无法对外传入Context,怎么办呢?引用一个全局静态的Application Context。
开发过程中应尽量避免传入Context对象,单例类中的Context对象必须为Application Context,保证在整个应用生命周期内引用。如下的写法可以去掉Android Studio内存泄漏的警告:
public class TestManager {
private Context mContext;
private TestManager() {
mContext = AppConfigure.getApplicationContext();
}
public void init() {
Log.d("test", "init " + mContext);
}
public static TestManager getInstance() {
return Holder.INSTANCE;
}
private static class Holder {
private static final TestManager INSTANCE = new TestManager();
}
}
这样Android Studio就不会出现内存泄漏的警告了,当然可以不用AppConfigure 类来获取Application Context,可以通过在自定义Application中声明一个公共静态全局的Context供其他类引用。
AppConfigure 类的代码如下:
public class AppConfigure {
private static volatile Application application;
public static synchronized void configure(Application application) {
AppConfigure.application = application;
}
public static <T extends Application> T getApplication() {
try {
if (application == null) {
synchronized (AppConfigure.class) {
if (application == null) {
@SuppressLint("PrivateApi") Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method method = activityThreadClass.getMethod("currentActivityThread");
Object localObject = method.invoke(null, (Object[]) null);
Field appField = activityThreadClass.getDeclaredField("mInitialApplication");
appField.setAccessible(true);
application = (Application) appField.get(localObject);
if (application == null) {
Method method2 = activityThreadClass.getMethod("getApplication");
application = (Application) method2.invoke(localObject, (Object[]) null);
}
}
}
}
// noinspection unchecked
return (T) application;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static Context getContext() {
return getApplicationContext();
}
public static Context getApplicationContext() {
return getApplication();
}
}