为什么这个用于回调的匿名内部类实例不会导致活动泄漏
我假设您在这里的意思是它不会导致内存泄漏,但它肯定会,因为您正在实例化匿名的范围是.Callback
Activity
如果您在 Android 中实例化一个内部类,然后将对此实例的引用传递给其他某个组件,则只要此组件是可访问的,那么内部类的实例也将是可访问的。例如,请考虑以下情况:Activity
class MemorySink {
static private List<Callback> callbacks = new ArrayList<>();
public static void doSomething(Callback callback){
callbacks.add(callback);
}
}
如果从某些活动创建了 的实例并将其传递给 ,当其中一个被销毁时,系统将不再使用该实例,则预计垃圾回收器将释放该实例。但是,如果这里引用了 a,并且引用了该引用,则即使在销毁后,该实例也会保留在内存中。砰,内存泄漏。Callback
doSomething(callback)
Activity
MemorySink
Callback
Activity
Activity
所以你说你的样本没有导致内存泄漏,我首先建议你试试,创建一个简单的“MainActivity”,里面有2个按钮,可能还有一些图像来增加内存占用量。在按以下方式在第一个按钮上设置侦听器:MemorySink
Activity
onCreate
findViewById(R.id.firstButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, MainActivity.class));
MemorySink.doSomething(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
finish();
}
});
您刚刚使用 创建了内存泄漏。每次您单击该实例中的按钮时,都会被销毁,并创建一个新实例。但是,的旧实例将保留在内存中。我邀请您单击该按钮多次,然后转储内存(在Android Studio中使用Android Profiler),或使用LeakCanary。Callback
MainActivity
MainActivity
MainActivity
因此,我们创建了一个内存泄漏,与 OP 中的相同类相同。现在,让我们将此方法添加到:Callback
MemorySink
public static void releaseAll() {
callbacks.clear();
}
并从 上的另一个按钮调用它。如果您多次按下第一个按钮(最好是当您有图像)时,即使您手动触发垃圾回收(Android Profile),您也会看到内存使用量上升。然后单击第二个按钮,释放所有引用,触发垃圾回收,内存下降。不再有内存泄漏。MainActivity
MainActivity
Callback
因此,问题不在于是否可以或不能创建内存泄漏,它肯定可以。问题是你在哪里通过它。在这种情况下,不会造成内存泄漏,所以你说,但根本不能保证这总是会发生。在这种情况下,您需要确定 的实现,才能说它不会产生内存泄漏。Callback
Callback
OkHttpClient
OkHttpClient
我的建议是始终假设,如果您要传递对某个外部类的引用,则会发生内存泄漏。Activity