【发布时间】:2017-04-10 04:43:31
【问题描述】:
当用户单击视图上的按钮时,我发现自己需要播放声音文件。
MediaPlayer 需要创建上下文。
MediaPlayer初始化代码放什么最好?
我应该将上下文传递给演示者方法并在那里播放吗?
或者只在视图上播放就可以了。
【问题讨论】:
-
一个活动就是一个上下文
-
你应该在里面写这个活动。否则presenter没有任何意义
当用户单击视图上的按钮时,我发现自己需要播放声音文件。
MediaPlayer 需要创建上下文。
MediaPlayer初始化代码放什么最好?
我应该将上下文传递给演示者方法并在那里播放吗?
或者只在视图上播放就可以了。
【问题讨论】:
Context 是 MVP 中 Android View 层的一部分,所以Presenter 一定对此一无所知,您不应该将其传递给presenter。
您必须向View 接口添加一个方法,并在您的android 视图组件(即Activity 或Fragment)中实现它,并使用它们在View 层中执行操作作为播放声音。
Presenter 必须请求 UI 事件,View 必须处理它!
这是一个使用 Dagger、RxJava 和 Retrofit 的 MVP 示例,它可能会帮助您了解更多信息关于 Android 中的 MVP:
【讨论】:
我经常将业务逻辑代码放在模型层中(不要与数据库中的模型混淆)。我经常重命名为XManager 以避免混淆(例如ProductManager、MediaManager ...),因此演示者类仅用于保持工作流程。
经验法则是在presenter类中没有或至少限制import android package。这个最佳实践支持您更轻松地测试演示者类,因为演示者现在只是一个普通的 java 类,所以我们不需要 android 框架来测试这些东西。
例如,这是我的 mvp 工作流程。
View 类:这是您存储所有视图(例如按钮、文本视图...)的地方,您可以在该层上为这些视图组件设置所有侦听器。同样在此视图上,您稍后为演示者实现定义一个侦听器类。您的视图组件将调用此侦听器类的方法。
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类:这里是核心业务逻辑代码。也许一个演示者会有很多经理(取决于视图的复杂程度)。我们经常通过Dagger等一些注入框架得到Context类。
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();
}
}
最后:把这些东西放在Activities、Fragments中……这里是你初始化view、manager并将所有东西分配给presenter的地方。
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();
}
}
您会看到每个演示者、模型、视图都由一个接口包装。这些组件将通过接口调用。这种设计将使您的代码更加健壮,并且更易于以后修改。
这是一个很长的帖子来回答你的问题。我认为这很合适,因为每个人都有自己的 MVP 实现(核心流程相同,但少数派不同)。所以我在这里介绍一个我在工作中经常使用的工作流程。希望你看到这个有用:)
【讨论】:
如果你需要一个通用的上下文,你可以扩展应用程序,声明一个静态上下文变量,然后你可以把这个上下文放到你的演示者中。
【讨论】: