简体   繁体   English

Android MVP中start()和stop()的最佳做法?

[英]Best practices for start() and stop() in Android MVP?

I have some questions regarding the Presenter's start() , stop() method. 我对演示者的start()stop()方法有一些疑问。 What would you normally put into these methods to prevent memory leaks or any potential problem. 您通常会采用什么方法来防止内存泄漏或任何潜在的问题。

For example, I have an Activity that host a VideoView . 例如,我有一个托管VideoViewActivity The videoPath passed to the Activity will be passed to the Presenter to a VideoUtility to trim the original video into a shorter one before getting passed back to the Activity to be played with the VideoView . 传递给ActivityvideoPath将传递给PresenterVideoUtility以将原始视频修剪成较短的视频,然后再传递回Activity以与VideoView一起播放。

Here's the confusion: I don't know where is the appropriate place to call the trimVideo() method as it essentially only need to happen once (unlike in the Android Architect Blueprint , the task is updated with latest data, and thus it's put in the onResume() ). 这是一个困惑:我不知道在哪里调用trimVideo()方法是合适的地方,因为它基本上只需要发生一次(不同于Android Architect Blueprint中的任务会使用最新数据进行更新,因此将其放入onResume() )。

Please see the code snippet below: 请参见下面的代码片段:

VideoEditorContract: VideoEditorContract:

public interface VideoEditorContract {
  interface View extends BaseView<Presenter> {
      void playTrimVideo(String trimmedVideoPath);
  }

  interface Presenter extends BasePresenter {
  }
}

VideoEditorActivityBase: VideoEditorActivityBase:

public class VideoEditorActivityBase extends AppCompatActivity implements VideoEditorContract.View {
  private VideoEditorContract.Presenter mPresenter;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_video_editor);

    String videoPath = getIntent().getStringExtra(RequestCode.EXTRA_VIDEO_PATH);

    mPresenter = new VideoEditorPresenter(videoPath, this);
  }

  @Override
  public void onResume(){
    super.onResume();
    mPresenter.start();
  }

  @Override
  public void playTrimVideo(String trimmedVideoPath) {
    final VideoView vv = findViewById(R.id.act_video_editor_videoView);
    vv.setVideoPath(trimmedVideoPath);
    vv.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            vv.start();
        }
    });
  }

  @Override
  public void setPresenter(VideoEditorContract.Presenter presenter) {
    //do nothing as this activity has already init a presenter
  }
}

VideoEditorPresenter: VideoEditorPresenter:

public class VideoEditorPresenter implements VideoEditorContract.Presenter {
  private final VideoEditorContract.View mVideoEditorView;

  @NonNull
  private String mVideoPath;

  public VideoEditorPresenter(@NonNull String videoPath, @NonNull VideoEditorContract.View videoEditorView) {
    mVideoPath = checkNotNull(videoPath);
    mVideoEditorView = checkNotNull(videoEditorView, "videoEditorView cannot be null!");
    mVideoEditorView.setPresenter(this);
    //trimVideo(); //should I do it here since this task is only need to be done once
  }

  @Override
  public void start() {
    //trimVideo(); //I can do it here but then I need to introduce a control variable; not sure if this is the best practice
  }

  private void trimVideo() {
    //trim video stuff
  }
   // Currently it doesn't have a stop() method. But if it have one,
   // what should I put in it? Releasing and clean up the 
   // VideoUtility I suppose?
}

I got the answer from Francesco Cervone in Medium about this matter (his article is also an excellent resource on MVP, btw. Very well in tune with the Android Architect Blueprint). 我从Medium的 Francesco Cervone获得了有关此问题的答案(顺便说一句,他的文章也是MVP的极佳资源。与Android Architect Blueprint相得益彰)。 I leave the relevant bit here for future reader. 我将相关内容留给以后的读者。

Hi, thank you. 嗨,谢谢你。

Well, I think that the video should be trimmed in the Presenter#start(). 好吧,我认为应该在Presenter#start()中修剪视频。 Then, after the video has been trimmed, the presenter should call view.playTrimmedVideo(). 然后,在修剪视频之后,演示者应调用view.playTrimmedVideo()。 You shouldn't do anything in the presenter constructor. 您不应该在Presenter构造函数中做任何事情。

I suppose the video “editing” is something expensive, so you should do that in a separate thread (using for example an async task). 我认为视频“编辑”是很昂贵的,因此您应该在单独的线程中执行此操作(例如,使用异步任务)。 You need to implement the Presenter#stop() method because you have to cancel ongoing operations if there are any, unless you retain the presenter. 您需要实现Presenter#stop()方法,因为如果有正在进行的操作,则必须取消正在进行的操作,除非保留演示者。

You said that the trimVideo should be called just once. 您说trimVideo应该只调用一次。 You could cache/persist in some way the result of trimVideo so that if the video has been already trimmed, you use it. 您可以通过某种方式缓存/持久保存trimVideo的结果,以便在视频已被修剪的情况下使用它。

I hope I answered your question. 希望我回答了你的问题。

"Could you elaborate more on why shouldn't we put anything in the Presenter's constructor? I've seen the Presenter's bare minimal constructor in a couple of places but I don't understand the reason behind it." “您能详细说明为什么我们不应该在Presenter的构造函数中放置任何内容吗?我已经在几个地方看到了Presenter的最小构造函数,但我不明白其背后的原因。”

First, it's a responsibility problem: you are going to create an instance of Presenter, and I don't think that the video editing is something that belongs to the construction of that object. 首先,这是一个责任问题:您将要创建一个Presenter实例,并且我认为视频编辑不属于该对象的构造。

Second, you don't know when the presenter is being instantiated, so you shouldn't execute expensive tasks in the constructor. 其次,您不知道演示者何时实例化,因此您不应在构造函数中执行昂贵的任务。 If you use some dependency injection framework, the construction of the Presenter would be managed by the framework itself and it needs to be efficient. 如果使用某些依赖项注入框架,则Presenter的构建将由框架本身管理,并且需要高效。 The construction of other objects could depend on the presenter one. 其他对象的构造可能取决于演示者之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM