发表于: 2018-11-24 18:55:23

0 733


一、今天完成的事情

学习MVP模式

按照 MVC 的分层,Activity 和 Fragment(后面只说 Activity)应该属于 View 层,用于展示 UI 界面,以及接收用户的输入,此外还要承担一些生命周期的工作。Activity 是在 Android 开发中充当非常重要的角色,特别是它的生命周期的功能,所以开发的时候我们经常把一些业务逻辑直接写在 Activity 里面,这非常直观方便,代价就是 Activity 会越来越臃肿,Activity 不仅承担了 View 的角色,还承担了一部分的 Controller 角色,这样一来 V 和 C 就耦合在一起了,虽然这样写方便,但是如果业务调整的话,要维护起来就难了,而且在一个臃肿的 Activity 类查找业务逻辑的代码也会非常困难,所以看起来有必要在 Activity 中,把 View 和 Controller 抽离开来,而这就是 MVP 模式的工作了。

MVP 模式的核心思想是把 Activity 中的 UI 逻辑抽象成 View 接口,把业务逻辑抽象成 Presenter 接口,Model 类还是原来的 Model。

MVP 模式的优点

    分离了视图逻辑和业务逻辑,降低了耦合;

    Activity 只处理生命周期的任务,代码变得更加简洁;

    视图逻辑和业务逻辑分别抽象到了 View 和 Presenter 的接口中去,提高代码的可阅读性;

    Presenter 被抽象成接口,可以有多种具体的实现,所以方便进行单元测试;

    把业务逻辑抽到 Presenter 中去,避免后台线程引用着 Activity 导致 Activity 的资源无法被系统回收从而引起      内存泄露和 OOM。

我试着用MVP模式把之前做的播放器重写了一下

播放本地视频模块,目录结构

public interface ILocalVideoView {
   void queryLocalVideoResult(boolean result);
   void onProgressBarVisibility(int visibility);
   void recyclerViewItemClick(String source);
}


public interface ILocalVideoPresenter {
   void queryLocalVideo(Context context, LocalVideoAdapter adapter);
   void setProgressBarVisibility(int visibility);
   void onItemClick(int position);
}


public class LocalVideoPresenterCompl implements ILocalVideoPresenter {

   ILocalVideoView iLocalVideoView;
   LocalVideo localVideo;
   List<LocalVideo> list;

   public LocalVideoPresenterCompl(ILocalVideoView iLocalVideoView) {
       this.iLocalVideoView = iLocalVideoView;
       initLocalVideo();
       list = new ArrayList<LocalVideo>();
   }

   @Override
   public void queryLocalVideo(Context context, LocalVideoAdapter adapter) {
       list.clear();
       list = localVideo.getLocalVideoList(context);
       boolean result = false;
       if (list != null && list.size() > 0) {
           adapter.setData(list);
           result = true;
       }
       iLocalVideoView.queryLocalVideoResult(result);
   }

   @Override
   public void setProgressBarVisibility(int visibility) {
       iLocalVideoView.onProgressBarVisibility(visibility);
   }

   @Override
   public void onItemClick(int position) {
       String source = list.get(position).getPath();
       iLocalVideoView.recyclerViewItemClick(source);
   }

   private void initLocalVideo() {
       localVideo = new LocalVideo(0, "", "", "", "",
               "", "", "", "");
   }
}


public class LocalVideoFragment extends Fragment implements ILocalVideoView, LocalVideoAdapter.OnItemClickListener {

   private static final String TAG = "LocalVideoFragment";

   private static final int TAKE_VIDEO = 1;

   private ILocalVideoPresenter iLocalVideoPresenter;

   private static LocalVideoAdapter localVideoAdapter;

   private static ProgressBar progressBar;

   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState) {
       View view = inflater.inflate(R.layout.fragment_local_video, container, false);
       iLocalVideoPresenter = new LocalVideoPresenterCompl(this);
       initView(view);
       initLocalVideo();
       return view;
   }

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       //指明fragment愿意添加item到选项菜单(否则, fragment将接收不到对 onCreateOptionsMenu()的调用)
       setHasOptionsMenu(true);
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
       menu.clear();
       super.onCreateOptionsMenu(menu, inflater);
       inflater.inflate(R.menu.local_video_menu, menu);
   }

   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
       switch (item.getItemId()) {
           case R.id.take_video:
               takeVideo();
               break;
           case R.id.refresh:
               initLocalVideo();
               break;
           default:
               break;
       }
       return true;
   }


   @Override
   public void onItemClick(int position) {
       iLocalVideoPresenter.onItemClick(position);
   }

   /*
   初始化控件
    */
   public void initView(View view) {
       progressBar = (ProgressBar) view.findViewById(R.id.bar_progress);
       iLocalVideoPresenter.setProgressBarVisibility(View.GONE);
       RecyclerView videoRV = (RecyclerView) view.findViewById(R.id.rv_video);
       LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
       videoRV.setLayoutManager(linearLayoutManager);
       localVideoAdapter = new LocalVideoAdapter(getContext());
       localVideoAdapter.setOnItemClickListener(this);
       videoRV.setAdapter(localVideoAdapter);
   }

   //初始化视频
   public void initLocalVideo() {
       iLocalVideoPresenter.setProgressBarVisibility(View.VISIBLE);
       iLocalVideoPresenter.queryLocalVideo(getContext(), localVideoAdapter);
   }

   @Override
   public void queryLocalVideoResult(boolean result) {
       if (result) {
           localVideoAdapter.notifyDataSetChanged();
           iLocalVideoPresenter.setProgressBarVisibility(View.GONE);
       } else {
           Toast.makeText(getContext(), "没有更多视频", Toast.LENGTH_SHORT).show();
           iLocalVideoPresenter.setProgressBarVisibility(View.GONE);
       }
   }

   @Override
   public void onProgressBarVisibility(int visibility) {
       progressBar.setVisibility(visibility);
   }

   @Override
   public void recyclerViewItemClick(String source) {
       Intent intent = new Intent(getActivity(), PlayVideoActivity.class);
       intent.putExtra("source", source);
       startActivity(intent);
   }


   /*
   拍摄视频
    */
   public void takeVideo() {
       Log.i(TAG, "takeVideo: 录视频");
       Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
       if (takeVideoIntent.resolveActivity(getActivity().getPackageManager()) != null) {
           startActivityForResult(takeVideoIntent, TAKE_VIDEO);
       } else {
           Log.i(TAG, "takeVideo: 错误");
       }
   }

   @Override
   public void onActivityResult(int requestCode, int resultCode, Intent data) {
       //如果希望结果传回Fragment,必须加上下面这一句
       super.onActivityResult(requestCode, resultCode,data);
       switch (requestCode) {
           case TAKE_VIDEO:
               if (resultCode == RESULT_OK) {
                   initLocalVideo();
                   Toast.makeText(getContext(), "拍摄成功", Toast.LENGTH_SHORT).show();
               } else {
                   Toast.makeText(getContext(), "拍摄失败", Toast.LENGTH_SHORT).show();
               }
               break;
           default:
               break;
       }
   }

}



三、遇到的问题    

四、收获

初步学习了MVP设计模式,今后会逐步转移到这种设计模式上来,并继续深入学习。




返回列表 返回列表
评论

    分享到