- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章完整的Android MVP开发之旅由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
开发背景 最近是在做一个与健身相关的app,里面有训练器模块基本功能是按照特点动作的演示和描述来引导用户完成训练。在第一个版本时由于没接触过些类项目与功能花了几周的时间大概1500行代码才完成这个功能, 当时虽然我已经尽量让代码表现的清晰,但是可以想像到当一个activity中包含这么多代码是什么感觉。自己维护起来都难受.
先谈设计 有了前一次设计经验此次开发使用mvp、模块化、面向接口等概念,将整个训练器分为控制器、数据模型、音频、视图、可训练对象五个模块分别用以下接口表示:
去掉一些抽象类后接口图如下:
设计以上接口后引入mvp概念使用itrainercontroller做为presenter,itrainermodel做model,itrainerview做view下面介绍主要模块.
控制器 可以用在mvc和mvp中这取决于用哪种开发模式,在我开发的项目控制器用来控制训练器的运行管理训练器的生命周期如训练、暂停、休息、完成等状态协调itrainermodel、itrainerview、iaudioflow等各个模块。 在使用过程中控制器并不止一个这也是抽象出一个接口的原因,itrainercontroller接口继承ipresenter接口使其能做为presenter使用.
数据模型 数据模型中包含大量的itrainable对象,对内组织数据对外提供数据支持。对数据的组织方式主要分两种:
在训练器中可能是正常的训练或是一次训练测试而训练数据和测试数据又有一些差异但它们的数据都被当做itrainable,测试数据是不需要保存的只需要从服务器拉取后按要求完成就行而训练是会产生本地记录的。 针对不同数据组织方式提供不同的数据模型这是有必要的.
音频 音频比较多样化像训练过程中包含动作名、时间、单位词、提醒等音频这些音频都是分开的不同的音频文件。android主要有两种实现方式:
首先说soundpool优点自然就是免去了加载、管理音频等过程但是它并不适应我们的训练器,主要原因是缺少准备、完成后的一些回调而在训练器运行过程中这些过程必不可少比如在播放完一段预备开始后音频这时我们才能进行正式的训练。 最后是采用mediaplayer,但是在使用过程又要考虑到音频的集中管理与资源的释放免不了多封装一次。设计时我将全部音频逻辑放在android service中activity通过bind audioservice来使用音频,将音频逻辑放入audioservice这样可以音频完 全独立起来使其能在后台播放并且也可以提高进程优先级.
在设计中audioservice仅仅播放与管理音频和资源并不具备音频播放的逻辑功能。由于不同的训练方式音频的播放逻辑也有不同之处所以在此设计iaudioflow接口来负责音频逻辑.
训练视图 android常用activity作为视图,通过实现itrainerview接口来完成训练视图的显示。视图中不包含任何业务逻辑代码.
再谈实现 说到实现其实这并不是最需要关注的内容,因为上面提供了很全面的接口而我们的模块又是使用的接口所以不管如何实现那些功能并不会对各个模块之间产生大的影响除非功能实现与实际要求相差太多。这里我只详细说一下音频模块的实现.
音频实现 音频模块又可分为音频管理与音频业务逻辑。音频管理就是加载、播放、回收资源等功能,音频业务逻辑主要处理在正确的状态下应该播放什么样的音频。将整个音频管理模块放在android service中与业务逻辑完全分离。音频模块涉及以下类与接口:
基本使用流程是首先通过绑定audioservice的onbind方法返回iaudioservice的实现类供iaudioflow使用,iaudioflow持有iaudioservice实现后加载训练音频然后供itrainercontroller使用。在audioserviceimpl中会维持一个音频优化级队列, 上面提到因为音频都是不在一个文件中的所有需要在使用时将它们连接起来形成一段音频。通过优先级队列结合mediaplayer播放完成时回调可以将多个音频组合在一起形成需要的音频。由于音频的播放越来越多mediaplayer的回收利用特别重 要在audioserviceimpl同样也具备mediaplayer的回收与利用功能。这个功能实现是通过mediaplayerholder来处理的,通过mediaplayerholder的静态get方法获取mediaplayerholder如果回收池中有空闲的mediaplayerholder则拿来用没有时则 新建一个,同样也在一个音频播放完成后调用mediaplayerholder的recycle来进行回收利用.
模块整合 为减少依赖模块之间的整合需提供管理或帮助类,新建trainerhelper来创建模块实现类其中包含一个mode枚举来列举训练模式.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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);
}
}
|
总结 成功的设计与架构能减少大量的工作时间,利用接口可让开发人员更加注重功能上的实现同时隔离各个模块之间的依赖。下次产品经理再改需求或再整出个训练模式时咱也能从容应对.
由于本人水平有限如有错误,请大家谅解.
最后此篇关于完整的Android MVP开发之旅的文章就讲到这里了,如果你想了解更多关于完整的Android MVP开发之旅的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是docker的新手,我正在尝试将Angular示例项目“Tour of heros”进行docker化,您可以在这里找到: https://angular.io/generated/zips/to
当我点击“结束游览”按钮时,我无法再次开始 Bootstrap 游览。我搜索了所有 documentation ,但我还没有找到解决方案。 最佳答案 也试试 tour.restart()。我刚刚问了同
我正在浏览Tour C++中的Aliases模板。我不明白下面的代码以及如何使用它? template class Vector { public: using value_type = T;
我已经实现了intro.js到我的网站。但我只想在第一次访问时开始旅行。可能是通过使用cookie..网站是用html而不是php制作的.. 最佳答案 JavaScript cookie 是一种解决方
我想使用Knockout.js与 Bootstrap Tour 。特别是,我想将一些数据绑定(bind)点击处理程序附加到游览步骤中的按钮。 我创建了一个像这样的简单游览: var tour = ne
我正在学习着名的 Angular 教程,英雄之旅,但我正在努力迈出一步。 关于 sixth course, HTTP ,我们正在使用一种工具来模拟对 API 的 API 调用。 我想我遵循了所有步骤,
我正在做 Go 之旅,这部分是“slice 就像对数组的引用”。我根本没有更改此代码,所以我很好奇为什么它会耗尽内存。 最佳答案 不应该崩溃,可能是旅游网站有一段时间出了问题......目前任何方式,
A Tour of Go #23 : package main import ( "fmt" "math" ) func pow(x, n, lim float64) float64
无法将其分解为更小的示例...所以我使用 std::multimap 来存储一些值...这是一个简单的多项式类。 问题是最后一个函数,它将两个多项式相乘。当它与它们相乘时,它会产生一个具有多项式的多项
环境:Angular 5+ 来源:https://angular.io/tutorial 在 heroes.component.ts 类中有一个带冒号的赋值,如下所示: export class He
代码 let interestingNumbers = [ "Prime": [2, 3, 5, 7, 11, 13], "Fibonacci": [1, 1, 2, 3, 5, 8]
在 Bootstrap 演练中,我们有下一个和上一个按钮。在此点击下一步按钮,我们进入下一步。 但我想添加条件,如果该输入字段为空,则演练不应移至下一步,它应仅停留在当前步骤。 引用代码如下: rec
我是一名优秀的程序员,十分优秀!