在我的应用中,我使用ContentProvider
并使用LoaderManager.LoaderCallbacks<Cursor>.
片段(查看)
public class ArticleCatalogFragment extends BaseFragment
implements ArticleCatalogPresenter.View,
LoaderManager.LoaderCallbacks<Cursor> {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return onCreateArticleCatalogLoader(args);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
data.registerContentObserver(new LoaderContentObserver(new Handler(), loader));
updateUI(data);
}
private Loader onCreateArticleCatalogLoader(Bundle args) {
int categoryId = args.getInt(CATEGORY_ID);
Loader loader = new ArticleCatalogLoader(this.getActivity(), categoryId);
return loader;
}
}
从MVP的角度来看,我需要:
演示
public class ArticleCatalogPresenter extends BasePresenter
implements LoaderManager.LoaderCallbacks<Cursor> {
View view;
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return onCreateArticleCatalogLoader(args);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
data.registerContentObserver(new LoaderContentObserver(new Handler(), loader));
view.updateUI(data);
}
private Loader onCreateArticleCatalogLoader(Bundle args) {
int categoryId = args.getInt(CATEGORY_ID);
Loader loader = new ArticleCatalogLoader(context, categoryId); // need Context
return loader;
}
interface View {
updateUI(Cursor data)
}
}
所以,我需要在Presenter中使用上下文。
有一些细微差别:
Presenter了解上下文 - 这很糟糕,Presenter不应该 了解Android。
在Presenter中使用上下文可能会导致内存泄漏。
我现在担心如何避免内存泄漏等问题,以及如何在Presenter中最好地传递Context,使用Application Context或Activity / Fragment?
答案 0 :(得分:3)
向Presenter添加上下文并不好,因为演示者负责业务逻辑。要处理上下文,您需要拥有片段/活动 在接口的帮助下使用Callbacks,它将说明在处理视图时activity / fragment需要执行哪些操作。 片段/活动负责提供上下文。
示例:
interface BaseContract {
interface BaseView {
//Methods for View
void onDoSomething();
}
interface BasePresenter {
void doSomething();
}
}
class BaseMainPresenter implements BaseContract.BasePresenter {
BaseContract.BaseView view;
BaseMainPresenter(BaseContract.BaseView view) {
this.view = view;
}
@Override
public void doSomething() {
if (view != null)
view.onDoSomething();
}
}
class DemoClass implements BaseContract.BaseView {
//Create object of Presenter
/****
* Example :
* BaseMainPresenter baseMainPresenter = new BaseMainPresenter(this);
*/
@Override
public void onDoSomething() {
//Deal with Context here.
}
}
答案 1 :(得分:0)
只是不要将您的演示者注册为Android特定的回调目标(例如BroadcastReceiver
,LoaderManager.LoaderCallbacks
等)。处理视图(片段或活动)中的回调方法,并将所有相关数据传递给演示者。
如果您需要Context
来创建对象,请让您的视图创建此对象(因为它具有对Context
的引用)。在你的情况下,电话
Loader loader = new ArticleCatalogLoader(context, categoryId)
应该重构为
view.createLoaderForCategory(categoryId)
答案 2 :(得分:0)
像这样的代码
Loader loader = new ArticleCatalogLoader(context, categoryId);
导致不可测试的代码。你应该避免创建&#34; business&#34;代码中的对象,让任何其他人为你做(任何DI框架,如Dagger 2比自己处理它更好)
话虽如此,你的问题是DI很久以前解决的问题。您是否需要任何对象的全新实例?使用Provider
Provider
是一个&#34;提供&#34;的对象。对象的实例。所以没有
Loader loader = new ArticleCatalogLoader(context, categoryId);
你会有
Loader loader = loaderProvider.get(categoryId);
所以你唯一需要的就是这样:
public class ArticleCatalogPresenter ... {
...
private final Provider<Loader> loaderProvider;
public ArticleCatalogPresenter(Provider<Loader> loaderProvider, ...) {
this.loaderProvider = loaderProvider;
...
}
private Loader onCreateArticleCatalogLoader(Bundle args) {
int categoryId = args.getInt(CATEGORY_ID);
Loader loader = loaderProvider.get(categoryId); // no context needed anymore!
return loader;
}
}
答案 3 :(得分:0)
public class ArticleCatalogPresenter extends BasePresenter implements LoaderManager.LoaderCallbacks<Cursor> { View view; ... private Loader onCreateArticleCatalogLoader(Bundle args) { int categoryId = args.getInt(CATEGORY_ID); Loader loader = new ArticleCatalogLoader(context, categoryId); // need Context return loader; } }
因此,您希望 Presenter 中的context
构建ArticleCatalogLoader
的新实例。正确?
如果是,请通过构造函数将实例传递给 Presenter 。因此,当您要构建Presenter对象时,在Activity或DI容器中,执行以下操作:
ArticleCatalogPresenter articleCatalogPresenter=new ArticleCatalogPresenter(articleCatalogView,new ArticleCatalogLoader(context,categoryId));
这样,您的Presenter将不依赖于context
,并且完全可以测试。
关于您对内存泄漏的担忧,您可以通过在视图中聆听onStop()
然后调用 Presenter 中的相应方法来轻松避免这种情况取消任何网络请求或context
相关任务。
我写了MVP library,这有助于节省MVP所需的样板量,以防止内存泄漏。