我在静态处理程序中使用弱引用来避免内存泄漏,但是,有时这个引用无效,我无法理解为什么。
静态处理程序在存储库类中定义,该类具有在后台执行操作的方法,接收回调以在调用者完成时通知调用方:
public class MyRepository {
public void performOperation(ContentResolver cr, RepositoryCallback callback) {
MyHandler handler = new MyHandler(cr, callback);
handler.startQuery(...)
}
interface RepositoryCallback {
void onSuccess(MyModel model);
}
// Handler class code here
}
处理程序的代码如下:
private static class MyHandler extends AsyncQueryHandler {
private final WeakReference<RepositoryCallback> weakCallback;
public MyHandler(ContentResolver cr, RepositoryCallback callback) {
super(cr);
this.weakCallback = new WeakReference<>(callback);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
RepositoryCallback callback = this.weakCallback.get();
if (callback != null) { // --> Here sometimes it is null
// Do some stuff with the cursor to create MyModel
callback.onSuccess(model);
}
}
}
出于某种原因,this.weakCallback.get()
有时会为空,我试图理解原因。
活动代码如下所示:
public class MyActivity extends AppCompatActivity {
public void loadModel() {
showLoadingView();
myRepository.performOperation(context.getContentResolver(), new RepositoryCallback() {
@Override
public void onSuccess(MyModel model) {
hideLoadingView();
// Do something with model
}
});
}
}
正如您所看到的,我为回调创建了一个匿名类,但没有人持有对它的引用。
这是弱引用无效的原因吗?
感谢。
答案 0 :(得分:1)
那是&#34; classic&#34;与弱引用相关的错误。
如果Observable只保留对Observer的引用,并且此引用很弱,则可以将其清除并将Observer置为垃圾回收。
由于您正在使用匿名类,因此Observable将保留对它的唯一引用,因此它将被清除。
作为旁注 - 在我对Android开发的整个体验中,每当我看到devs使用弱引用时,它总是代码味道。通常它表明开发人员不了解弱引用的工作方式,或者他们不相信自己的代码。
一个好的经验法则是你绝不应该使用弱引用。
修改强>
我认为Handler
一般都是反模式。您可以在this Reddit thread中详细了解相关信息。还有一个主题,我帮助一个开发人员看看他如何摆脱代码库中的HandlerThread
。
另一方面,杰克沃顿不同意我的陈述。
从那里得到你想要的东西,但是,一般来说,我会说静态Handler
肯定是反模式。
如果您担心AndroidStudion警告,请记住Google负责AsyncTask
和Loaders
。这个警告不仅没用,而且实际上很糟糕。他们应该you should not use static Hadlers
。
如果你需要的是将工作卸载到BG线程然后在UI线程上获得回调那么你会更喜欢像RxJava这样的东西。甚至是邪恶的AsyncTask
。
我猜您正在使用AsyncQueryHandler
来访问ContentProvider
。这是一个非常有争议的方法。如果您不需要与其他应用程序共享数据,最好使用一些为您处理多线程的ORM。