这将是一篇关于如何在我最后回答您的问题之前构建 MVP 项目的长篇文章。
我只是在这里报告 MVP 结构如何根据我自己的答案构建 MVP 项目。
我经常将业务逻辑代码放在模型层中(不要与数据库中的模型混淆)。我经常重命名XManager
以避免混淆(例如ProductManager
,MediaManager
...),因此演示者类仅用于保持工作流程。
经验法则是没有或至少限制在演示者类中导入 android 包。这个最佳实践支持您更轻松地测试演示者类,因为演示者现在只是一个普通的 java 类,所以我们不需要 android 框架来测试这些东西。
例如,这是我的 mvp 工作流程。
视图类:这是您存储所有视图(例如按钮、文本视图...)的地方,您可以在该层上为这些视图组件设置所有侦听器。同样在此视图上,您稍后为演示者实现定义一个侦听器类。您的视图组件将调用此侦听器类的方法。
class ViewImpl implements View {
Button playButton;
ViewListener listener;
public ViewImpl(ViewListener listener) {
// find all view
this.listener = listener;
playButton.setOnClickListener(new View.OnClickListener() {
listener.playSong();
});
}
public interface ViewListener {
playSong();
}
}
Presenter 类:这是您在其中存储视图和模型以供以后调用的地方。演示者类也将实现上面定义的 ViewListener 接口。演示者的重点是控制逻辑工作流程。
class PresenterImpl extends Presenter implements ViewListener {
private View view;
private MediaManager mediaManager;
public PresenterImpl(View, MediaManager manager) {
this.view = view;
this.manager = manager;
}
@Override
public void playSong() {
mediaManager.playMedia();
}
}
Manager类:这里是核心业务逻辑代码。也许一个演示者会有很多经理(取决于视图的复杂程度)。通常我们Context
通过一些注入框架来获取类,例如Dagger
.
Class MediaManagerImpl extends MediaManager {
// using Dagger for injection context if you want
@Inject
private Context context;
private MediaPlayer mediaPlayer;
// dagger solution
public MediaPlayerManagerImpl() {
this.mediaPlayer = new MediaPlayer(context);
}
// no dagger solution
public MediaPlayerManagerImpl(Context context) {
this.context = context;
this.mediaPlayer = new MediaPlayer(context);
}
public void playMedia() {
mediaPlayer.play();
}
public void stopMedia() {
mediaPlayer.stop();
}
}
最后:将这些东西放在活动中,片段中......这是您初始化视图,管理器并将所有内容分配给演示者的地方。
public class MyActivity extends Activity {
Presenter presenter;
@Override
public void onCreate() {
super.onCreate();
IView view = new ViewImpl();
MediaManager manager = new MediaManagerImpl(this.getApplicationContext());
// or this. if you use Dagger
MediaManager manager = new MediaManagerImpl();
presenter = new PresenterImpl(view, manager);
}
@Override
public void onStop() {
super.onStop();
presenter.onStop();
}
}
您会看到每个演示者、模型、视图都由一个接口包装。这些组件将通过接口调用。这种设计将使您的代码更健壮,并且更易于以后修改。
简而言之,在您的情况下,我提出这样的设计:
class ViewImpl implements View {
Button button;
TextView textView;
ViewListener listener;
public ViewImpl(ViewListener listener) {
// find all view
this.listener = listener;
button.setOnClickListener(new View.OnClickListener() {
textView.setText(resource_id);
});
}
}
如果逻辑视图比较复杂,例如设置值的一些条件。所以我将把逻辑放入DataManager
获取文本。例如:
class Presenter {
public void setText() {
view.setText(dataManager.getProductName());
}
}
class DataManager {
public String getProductName() {
if (some_internal_state == 1) return getResources().getString(R.string.value1);
if (some_internal_state == 2) return getResources().getString(R.string.value2);
}
}
因此,您永远不会将与 android 相关的东西放入演示者类中。您应该将其移至View
班级或DataManager
班级,具体取决于上下文。
这是一篇很长的文章,详细讨论了 MVP 以及如何解决您的具体问题。希望这有帮助:)