完整的Android MVP开发之旅

开发背景
最近是在做一个与健身相关的APP,里面有训练器模块基本功能是按照特点动作的演示和描述来引导用户完成训练。在第一个版本时由于没接触过些类项目与功能花了几周的时间大概1500行代码才完成这个功能,
当时虽然我已经尽量让代码表现的清晰,但是可以想像到当一个Activity中包含这么多代码是什么感觉。自己维护起来都难受。

先谈设计
有了前一次设计经验此次开发使用MVP、模块化、面向接口等概念,将整个训练器分为控制器、数据模型、音频、视图、可训练对象五个模块分别用以下接口表示:

  • ITrainerController
  • ITrainerModel
  • IAudioFlow
  • ITrainerView
  • ITrainable

去掉一些抽象类后接口图如下:

设计以上接口后引入MVP概念使用ITrainerController做为Presenter,ITrainerModel做Model,ITrainerView做View下面介绍主要模块。

控制器
可以用在MVC和MVP中这取决于用哪种开发模式,在我开发的项目控制器用来控制训练器的运行管理训练器的生命周期如训练、暂停、休息、完成等状态协调ITrainerModel、ITrainerView、IAudioFlow等各个模块。
在使用过程中控制器并不止一个这也是抽象出一个接口的原因,ITrainerController接口继承IPresenter接口使其能做为Presenter使用。

数据模型
数据模型中包含大量的ITrainable对象,对内组织数据对外提供数据支持。对数据的组织方式主要分两种:

  • 从本地数据库
  • 从网络获取

在训练器中可能是正常的训练或是一次训练测试而训练数据和测试数据又有一些差异但它们的数据都被当做ITrainable,测试数据是不需要保存的只需要从服务器拉取后按要求完成就行而训练是会产生本地记录的。
针对不同数据组织方式提供不同的数据模型这是有必要的。

音频
音频比较多样化像训练过程中包含动作名、时间、单位词、提醒等音频这些音频都是分开的不同的音频文件。Android主要有两种实现方式:

  • SoundPool
  • MediaPlayer

首先说SoundPool优点自然就是免去了加载、管理音频等过程但是它并不适应我们的训练器,主要原因是缺少准备、完成后的一些回调而在训练器运行过程中这些过程必不可少比如在播放完一段预备开始后音频这时我们才能进行正式的训练。
最后是采用MediaPlayer,但是在使用过程又要考虑到音频的集中管理与资源的释放免不了多封装一次。设计时我将全部音频逻辑放在Android Service中Activity通过bind AudioService来使用音频,将音频逻辑放入AudioService这样可以音频完
全独立起来使其能在后台播放并且也可以提高进程优先级。

在设计中AudioService仅仅播放与管理音频和资源并不具备音频播放的逻辑功能。由于不同的训练方式音频的播放逻辑也有不同之处所以在此设计IAudioFlow接口来负责音频逻辑。

训练视图
Android常用Activity作为视图,通过实现ITrainerView接口来完成训练视图的显示。视图中不包含任何业务逻辑代码。

再谈实现
说到实现其实这并不是最需要关注的内容,因为上面提供了很全面的接口而我们的模块又是使用的接口所以不管如何实现那些功能并不会对各个模块之间产生大的影响除非功能实现与实际要求相差太多。这里我只详细说一下音频模块的实现。

音频实现
音频模块又可分为音频管理与音频业务逻辑。音频管理就是加载、播放、回收资源等功能,音频业务逻辑主要处理在正确的状态下应该播放什么样的音频。将整个音频管理模块放在Android Service中与业务逻辑完全分离。音频模块涉及以下类与接口:

  • AudioService: 音频服务器继承Android Service
  • IAudioService: 音频抽象接口包含播放、暂停等事件
  • MediaPlayerHolder: 持有MediaPlayer管理MediaPlayer生命同期
  • IAudioFlow: 为不同的训练内容提供音频逻辑
  • AudioServiceImpl: 实现IAudioService

基本使用流程是首先通过绑定AudioService的onBind方法返回IAudioService的实现类供IAudioFlow使用,IAudioFlow持有IAudioService实现后加载训练音频然后供ITrainerController使用。在AudioServiceImpl中会维持一个音频优化级队列,
上面提到因为音频都是不在一个文件中的所有需要在使用时将它们连接起来形成一段音频。通过优先级队列结合MediaPlayer播放完成时回调可以将多个音频组合在一起形成需要的音频。由于音频的播放越来越多MediaPlayer的回收利用特别重
要在AudioServiceImpl同样也具备MediaPlayer的回收与利用功能。这个功能实现是通过MediaPlayerHolder来处理的,通过MediaPlayerHolder的静态get方法获取MediaPlayerHolder如果回收池中有空闲的MediaPlayerHolder则拿来用没有时则
新建一个,同样也在一个音频播放完成后调用MediaPlayerHolder的recycle来进行回收利用。

模块整合
为减少依赖模块之间的整合需提供管理或帮助类,新建TrainerHelper来创建模块实现类其中包含一个Mode枚举来列举训练模式。

public class TrainerHelper {

  public enum Mode{TEST, TRAINING, EXAM}

  private static Mode mode;

  public static void setMode(Mode m){
    mode = m;
  }

  public static ITrainerController createPresenter(ITrainerView view, Bundle createArgs){
    return new TrainerPresenter(view,createArgs);
  }

  public static ITrainerModel createTrainerModel(ITrainerController controller){
    return = new DefaultTrainerModel(bundle);;
  }

  public static IAudioFlow createTrainerAudioFlow(ITrainerController controller){
    return new DefaultAudioFlow(controller);
  }

}

总结
成功的设计与架构能减少大量的工作时间,利用接口可让开发人员更加注重功能上的实现同时隔离各个模块之间的依赖。下次产品经理再改需求或再整出个训练模式时咱也能从容应对。

由于本人水平有限如有错误,请大家谅解。

(0)

相关推荐

  • 浅谈Android官方MVP架构解读

    综述 对于MVP (Model View Presenter)架构是从著名的MVC(Model View Controller)架构演变而来的.而对于Android应用的开发中本身可视为一种MVC架构.通常在开发中将XML文件视为MVC中的View角色,而将Activity则视为MVC中的Controller角色.不过更多情况下在实际应用开发中Activity不能够完全充当Controller,而是Controller和View的合体.于是Activity既要负责视图的显示,又要负责对业务逻辑的

  • Android MVP模式ListView中嵌入checkBox的使用方法

    MVP模式 ListView中嵌入checkBox的使用 本文写的是一个小demo,如何在ListView中嵌入checkBox配合使用,本篇文章与前面的嵌入Button类似,同样的采用MVP模式的写代码,本次案例中会有几个小细节,我将会在案例中介绍. 程序基本框架如下: View层: MainActivity.java public class MainActivity extends AppCompatActivity implements ViewInter<MyBean>{ //Lis

  • Android中mvp模式使用实例详解

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller. 在MVC里,View是可以直接访问

  • Android开发:浅谈MVP模式应用与内存泄漏问题解决

    最近博主开始在项目中实践MVP模式,却意外发现内存泄漏比较严重,但却很少人谈到这个问题,促使了本文的发布,本文假设读者已了解MVP架构. MVP简介 M-Modle,数据,逻辑操作层,数据获取,数据持久化保存.比如网络操作,数据库操作 V-View,界面展示层,Android中的具体体现为Activity,Fragment P-Presenter,中介者,连接Modle,View层,同时持有modle引用和view接口引用 示例代码 Modle层操作 public class TestModle

  • Android如何从实现到封装一个MVP详解

    前言 MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.下面这篇文章主要给大家介绍了关于Android从实现到封装MVP的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. MVP之间的联系 大概简单的解释就是M->module处理数据,V->Act显示界面,P->M和V沟通的渠道,即P用来将数据和界面联系到一起,这样子界面和数据就可以完全独立开来,Ac

  • 详解Android MVP开发模式

    本文主要讲解MVP开发模式以及具体实例. 一.简介 MVP(Model View Presenter)模式是著名的MVC(Model View Controller)模式的一个演化版本,目前它在Android应用开发中越来越重要了.初看起来我们会感觉增加了很多类接口代码看起来更加清晰. MVP模式可以分离显示层和逻辑层,所以功能接口如何工作与功能的展示可以实现分离,MVP模式理想化地可以实现同一份逻辑代码搭配不同的显示界面.不过MVP不是一个结构化的模式,它只是负责显示层而已,任何时候都可以在自

  • 详解Android中的MVP架构分解和实现

    1.概述 传统的Android开发架构一般是MVC模式, Model:业务逻辑和实体模型 View:对应于布局文件 Controllor:对应于Activity 单独从逻辑看起来非常好,与我们做Web开发时,开发模式类似,但在实际开发中,View对应于布局文件,实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,Activity既像View又像Controller(MVVP架构中包括数据绑定),导致Activity中职责太重,耦合度大.修改和维护起来非常麻烦. 2.MV

  • 详解MVP模式在Android开发中的应用

    一.MVP介绍  随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责.为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP(Model-View-Presenter)模式应运而生. 在MVP模式里通常包含4个要素: (1)View:负责绘制UI元素.与用户进行交互(在Android中体现为Activity); (2)View interface:需要View实现的接口,Vie

  • Android MVP模式实战教程

    一.什么是MVP 在网上找了些资料,整理如下: MVP是模型(Model).视图(View).主持人(Presenter)的缩写,分别代表项目中3个不同的模块. 模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等: 视图(View):负责界面数据的展示,与用户进行交互: 主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来. 如下图所示,View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁

  • 完整的Android MVP开发之旅

    开发背景 最近是在做一个与健身相关的APP,里面有训练器模块基本功能是按照特点动作的演示和描述来引导用户完成训练.在第一个版本时由于没接触过些类项目与功能花了几周的时间大概1500行代码才完成这个功能, 当时虽然我已经尽量让代码表现的清晰,但是可以想像到当一个Activity中包含这么多代码是什么感觉.自己维护起来都难受. 先谈设计 有了前一次设计经验此次开发使用MVP.模块化.面向接口等概念,将整个训练器分为控制器.数据模型.音频.视图.可训练对象五个模块分别用以下接口表示: ITrainer

  • Android编程开发之TextView文字显示和修改方法(附TextView属性介绍)

    本文实例讲述了Android编程开发之TextView文字显示和修改方法.分享给大家供大家参考,具体如下: 一. 新建一个Activity 和 Layout 首先在layout文件夹中新建一个activity_main.xml,在新建工程的时候一般默认会新建此xml文件,修改其代码如下: activity_main.xml 代码 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" x

  • Android程序开发之Fragment实现底部导航栏实例代码

    流行的应用的导航一般分为两种,一种是底部导航,一种是侧边栏. 说明 IDE:AS,Android studio; 模拟器:genymotion; 实现的效果,见下图. 具体实现 为了讲明白这个实现过程,我们贴出来的代码多一写,这样更方便理解 [最后还会放出完整的代码实现] .看上图的界面做的比较粗糙,但实现过程的骨架都具有了,想要更完美的设计,之后自行完善吧 ^0^. 布局 通过观察上述效果图,发现任意一个选项页面都有三部分组成: 顶部去除ActionBar后的标题栏: 中间一个Fragment

  • Android WebView开发之WebView与Native交互

    目录 前言 一.JS调用Native的三种方式 完整源码 二.Native调用WebView的两种方案 完整源码 前言 附GitHub源码:WebViewExplore 一.JS调用Native的三种方式 1.通过WebView的addJavascriptInterface进行对象映射 需要注意的是这种调用方式,如果你的 minSdkVersion <=16那么需要考虑到4.2之前的漏洞问题. mWebView.addJavascriptInterface(new JsCallAndroidIn

  • android应用开发之spinner控件的简单使用

    Android的控件有很多种,其中就有一个Spinner的控件,这个控件其实就是一个下拉显示列表.Spinner是位于 android.widget包下的,每次只显示用户选中的元素,当用户再次点击时,会弹出选择列表供用户选择,而选择列表中的元素同样来自适配器.Spinner是View类的一个子类. 先看spinner的效果图: 代码: MainActivity package com.mecury.spinnertest; import java.util.ArrayList; import a

  • Android编程开发之TextView控件用法(2种方法)

    本文实例讲述了Android编程开发之TextView控件用法.分享给大家供大家参考,具体如下: 这里我们会讲讲常用控件的使用. 在今后的大多数章节里面也是一样的,我们会具体的说说某些控件的用法.因为只要把这些控件组合在一起它们就是一个应用了. 好吧我们直接看看这个控件怎么用. 细心的同学会发现,其实这个控件的内容是定义在values文件夹里面的strings.xml中的. 那么我们只需要给它加一段代码: 复制代码 代码如下: <string name="test">Wel

  • Android编程开发之seekBar采用handler消息处理操作的方法

    本文实例讲述了Android编程开发之seekBar采用handler消息处理操作的方法.分享给大家供大家参考,具体如下: 该案例简单实现进度条可走,可拖拽的功能,下面请看源码: 布局文件: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout

  • Android编程开发之TextView单击链接弹出Activity的方法

    本文实例讲述了Android编程开发之TextView单击链接弹出Activity的方法.分享给大家供大家参考,具体如下: 话不多说直接上码: 核心源码: package com.example.textview4; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.SpannableString; import android.tex

  • Android编程开发之EditText实现输入QQ表情图像的方法

    本文实例讲述了Android编程开发之EditText实现输入QQ表情图像的方法.分享给大家供大家参考,具体如下: 实现效果如下: 将QQ表情图像放到res下的drawable-hdpi文件夹下: 布局文件: <EditText android:id="@+id/edittext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:

  • Android编程开发之在Canvas中利用Path绘制基本图形(圆形,矩形,椭圆,三角形等)

    本文实例讲述了Android编程开发之在Canvas中利用Path绘制基本图形的方法.分享给大家供大家参考,具体如下: 在Android中绘制基本的集合图形,本程序就是自定义一个View组件,程序重写该View组件的onDraw(Canvase)方法,然后在该Canvas上绘制大量的基本的集合图形. 直接上代码: 1.自定义的View组件代码: package com.infy.configuration; import android.content.Context; import andro

随机推荐