我正在使用静态处理程序内的弱参考来避免内存泄漏,但是,有时此参考被无效,我不明白为什么。
静态处理程序是在一个存储库中定义的,该存储库类具有在后台执行操作的方法,接收回调以通知呼叫者:
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
}
});
}
}
您可以看到我正在为回调创建一个匿名类,但是没有人持有对它的参考。
这是弱参考被无效的原因吗?
谢谢。
这是与弱参考相关的"经典"错误。
如果可观察到的观察者唯一的参考,并且该引用较弱,则可以清除并收集观察者。
由于您正在使用匿名类,因此可观察的唯一参考将被清除。
作为旁注 - 在我对Android开发的整个经历中,每当我使用弱参考文献看到开发人员时,这总是是一种代码气味。通常,这表明要么开发人员不了解弱参考的工作方式,要么不信任自己的代码。
一个好的经验法则是,您永远不要使用弱参考。
编辑:
我认为Handler
通常是反模式。您可以在此Reddit线程中阅读有关此信息的更多信息。那里还有一个线程,我在其中帮助一个开发人员,看看他如何在代码库中摆脱HandlerThread
。
另一方面,杰克·沃顿(Jake Wharton(不同意我的陈述。
拿起您想要的东西,但是,总的来说,我想说的是静态Handler
肯定是反平底入的。
如果您担心AndroidStudion警告,请记住Google负责AsyncTask
和Loaders
。此警告不仅没有用,而且实际上是不好的。他们应该把它做到you should not use static Hadlers
。
如果您只需要将工作卸载到BG线程,然后在UI线程上获得回调,那么使用RXJAVA之类的东西会更好。甚至邪恶的AsyncTask
。
我想您正在使用AsyncQueryHandler
来访问ContentProvider
。这是一种非常有争议的方法。如果您不需要与其他应用共享数据,则使用为您处理多线程的一些ORM可能会更好。