一、这个App整体的架构划分:

分为四大模块:
 
1.app模块
2.common模块
3.domain模块
4.model模块
 
 
app模块的依赖:
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':domain')
...
}
它依赖domain,领域层模块。在app模块中,应用了MVP模式,把一个activity中的View和Presenter划分掉。
 
domain模块的依赖:
dependencies {
    compile project (':common')
    compile project (':model')
...
}
它依赖model模块。领域逻辑代码放在这个模块;需要获取数据,获取数据的实现代码则放在module模块;它依赖common,通用的功能,整个应用共用的代码,放在common模块中。
 
 
model模块的依赖:
dependencies {
    compile project(':common')
....
}
这个模块只依赖common模块。model模块提供数据获取,修改功能。
 
common模块的依赖:
dependencies {
    compile 'com.squareup:otto:1.3.5'
    compile 'com.google.dagger:dagger:2.0'
    compile 'org.glassfish:javax.annotation:10.0-b28'
}
它不依赖domain,app,model模块。它使用第三方类库,来给其它模块提供功能。使用Dagger依赖注入框架,进行依赖注入;使用otto类库,来实现总线方式的通信。
 
二、整个执行流程简要分析
 
app模块:
MoviesActivity,MoviesPresenter。
 
domain模块:
ConfigurationUsecase, GetMoviesUsecaseController。
 
module模块:
RestMovieSource。
 
模块之间的通信,协作使用Bus总线来实现。比如,module模块,接受了数据查询的请求,查询完毕之后,它就通过总线post出去;然后,app模块或者domain模块,使用总线订阅了某个事件,那么订阅该事件的方法就会被回调。
 
 
三、依赖注入框架,注入流程
 
1.依赖注入流程
在MoviesActivity中,声明了一个带有注解@Inject的成员,@Inject MoviesPresenter mMoviesPresenter。这就表明当前类需要注入一个依赖mMoviesPresenter。
 
2.在MoviesActivity中,执行方法initializeDependencyInjector():
private void initializeDependencyInjector() {

MoviesApp app = (MoviesApp) getApplication();

DaggerBasicMoviesUsecasesComponent.builder()
     .appComponent(app.getAppComponent())
     .basicMoviesUsecasesModule(new BasicMoviesUsecasesModule())
     .build().inject(this);
}

package com.hackvg.android.di.components;

import com.hackvg.android.di.modules.BasicMoviesUsecasesModule;
import com.hackvg.android.di.scopes.PerActivity;
import com.hackvg.android.views.activities.MoviesActivity;

import dagger.Component;

@PerActivity
@Component(dependencies = AppComponent.class, modules = BasicMoviesUsecasesModule.class)
public interface BasicMoviesUsecasesComponent {

void inject (MoviesActivity moviesActivity);
}

}

initializeDependencyInjector()方法,会生成所有相关的依赖,根据一个对象图生成依赖。编译该项目,Dagger会为BasicMoviesUsecasesComponent生成一个类DaggerBasicMoviesUsecasesComponent。在创建了Component实例后,传入需要的外部参数,AppComponent.class,BasicMoviesUsecasesModule.class,然后,再调用其中的inject方法就可以了。
 
@PerActivity注解表明该Component的存在的范围与当前Activity一致。
 
Dagger生成Component中的依赖的流程:
1.BasicMoviesUsecasesModule,描述了依赖 ConfigurationUsecase, ConfigurationUsecase的生成

package com.hackvg.android.di.modules;

import com.hackvg.domain.ConfigurationUsecase;
import com.hackvg.domain.ConfigurationUsecaseController;
import com.hackvg.domain.GetMoviesUsecase;
import com.hackvg.domain.GetMoviesUsecaseController;
import com.hackvg.model.rest.RestMovieSource;
import com.squareup.otto.Bus;

import dagger.Module;
import dagger.Provides;

@Module
public class BasicMoviesUsecasesModule {

@Provides ConfigurationUsecase provideConfigurationUsecase (Bus bus, RestMovieSource moviesSource) {
     return new ConfigurationUsecaseController(moviesSource, bus);
}

@Provides GetMoviesUsecase provideMoviesUsecase (Bus bus, RestMovieSource movieSource) {
      return new GetMoviesUsecaseController(movieSource, bus);
}
}

2.生成上述两个依赖,需要提供参数Bus, RestMovieSource,那么,根据Dagger规定,这两个参数也要执行依赖注入。这两个依赖由AppComponent.Class来提供:
该AppComponent实例是单例的,它提供了两个依赖的生成Bus, RestMovieSource。
 
AppComponent:

package com.hackvg.android.di.components;

import com.hackvg.android.di.modules.ApplicationModule;
import com.hackvg.android.di.modules.DomainModule;
import com.hackvg.model.rest.RestMovieSource;
import com.squareup.otto.Bus;

import javax.inject.Singleton;

import dagger.Component;

@Singleton
@Component(modules = {
ApplicationModule.class,
DomainModule.class,
})

public interface AppComponent {

Bus bus();
RestMovieSource restMovieSource();
}

DomainModule:描述了依赖Bus,RestMoviesSource的生成。

package com.hackvg.android.di.modules;

import com.hackvg.model.rest.RestMovieSource;
import com.squareup.otto.Bus;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

@Module
public class DomainModule {

@Provides @Singleton Bus provideBus () {
return new Bus();
}

@Provides @Singleton RestMovieSource provideDataSource (Bus bus) { return new RestMovieSource(bus); }

}

 
参考资料:
https://github.com/saulmm/Material-Movies
 

一个App架构例子分析--UI层使用MVP模式;各层之间使用Otto实现通信的更多相关文章

  1. 014_HDFS存储架构、架构可靠性分析、副本放置策略、各组件之间的关系

    1.HDFS存储架构

  2. Web框架之Django_03 路由层了解(路有层 无名分组、有名分组、反向解析、路由分发 视图层 JsonResponse,FBV、CBV、文件上传)

    摘要: 路由层 无名分组 有名分组 反向解析 路由分发 名称空间 伪静态网页.虚拟环境 视图层 JsonResponse FBV 与 CBV(function base views与class bas ...

  3. 成都app开发:架构一个App需要学会哪些技术呢?

    成都亿合科技小编为您分享: 随着APP应用的流行,越来越多的人想自己学习怎么开发APP应用,那架构一个APP需要学些什么技术呢?首先要了解App都有哪些类型,不同的类型适用于哪些需求,用户可以根据自己 ...

  4. 一个强大的LogParser的UI工具--logparserlizard简介(开源IIS日志分析工具)

    原文地址:http://blog.csdn.net/downmoon/article/details/4509513 日志分析,特别是IIS日志,一般人都会想到LogParser工具,的确很强.但是命 ...

  5. mvc项目架构搭建之UI层的搭建

    项目架构搭建之UI层的搭建 Contents 系列一[架构概览] 0.项目简介 1.项目解决方案分层方案 2.所用到的技术 3.项目引用关系 系列二[架构搭建初步] 4.项目架构各部分解析 5.项目创 ...

  6. App架构经验总结(转)

    原文链接: http://keeganlee.me/post/architecture/20160303 架构因人而异,不同的架构师大多会有不同的看法:架构也因项目而异,不同的项目需求不同,相应的架构 ...

  7. App架构经验总结(转载)

    原文地址:http://www.iteye.com/news/31472 架构因人而异,不同的架构师大多会有不同的看法:架构也因项目而异,不同的项目需求不同,相应的架构也会不同.然而,有些东西还是通用 ...

  8. 开发一个 app 有多难?

    171 个回答 默认排序​ 道衍天机 有事情的加微信1293190838找我 1,150 人赞同了该回答 ----------------------------------------------- ...

  9. 从服务端架构设计角度,深入理解大型APP架构升级

    随着智能设备普及和移动互联网发展,移动端应用逐渐成为用户新入口,重要性越来越突出.但企业一般是先有PC端应用,再推APP,APP 1.0版的功能大多从现有PC应用平移过来,没有针对移动自身特点考虑AP ...

随机推荐

  1. button type=“submit”

    写js遇到任何怪异的行为 一定要先看看是不是submit搞的鬼. 函数内部最后总是返回 return false; 也是一个好的习惯

  2. iOS开发实现UIView随着子控件的高度的变化而变化

    例子 其实看完上面的叙述,你会思考,到底什么情况下,一个UIView需要只设置坐标不设置大小呢?其实这种场景相当普遍.比如,我们常常会碰到,一个View中有两个Label,两个Label的高度均和内容 ...

  3. OSG配置失败解决方案

    这连续三天都在台式机上配置OSG,总是报各种各样的错. 后来换到笔记本上配置,结果一次性就配置成功了.笔记本和台式机都是WIN10系统,都是VS2013.或许有时候出错就可以换台电脑或者重装系统试试. ...

  4. GPS定位,根据经纬度查询附近地点的经纬度-sql方法实现

    根据当前所在的坐标点也即经纬度,查找数据库中附近5公里或10公里附近的所有信息的实现,经过查找资料,原来是我高二学的,就是求弦长,数学忘完了,没想到数学还这么有用,数学啊 真是用途太大了. 用到的什么 ...

  5. 【week2】燃尽图

    燃尽图(burn down chart)是在项目完成之前,对需要完成的工作的一种可视化表示.燃尽图有一个Y轴(工作)和X轴(时间).理想情况下,该图表是一个向下的曲线,随着剩余工作的完成,“烧尽”至零 ...

  6. 理解BitSet

    先来看几道面试题: 1.统计40亿个数据中没有出现的数据,将40亿个不同数据进行排序. 2.现在有1千万个随机数,随机数的范围在1到1亿之间,要求写出一种算法,将1到1亿之间没有在随机数中的数求出来. ...

  7. Cacti自定义脚本,监测Docker信息(Script/Command方式)

    一 环境背景 监控主机A:192.168.24.231:被监控主机B:192.168.24.233 A/B主机,通过公私钥建立ssh连接 [操作B主机时不需要输入密码,详见笔记:http://app. ...

  8. [OS] 生产者-消费者问题(有限缓冲问题)

    ·最简单的情形--(一个生产者 + 一个消费者 + 一个大小为1的有限缓冲) 首先来分析其中的同步关系: ·必须在生产者放入一个产品之后,消费者才能够从缓冲中取出产品来消费.·只有在消费者从缓冲区中取 ...

  9. 【Python】Python中的下划线

    单下划线(如: _var): 使用单下划线,用于指定该名变量或函数属性为“私有”.这仅仅是一个惯例,不是强制规定.用于向其他程序员表明这个变量或函数仅仅供内部使用,外部不要访问它.但实际上外部还是可以 ...

  10. I/O复用----poll

    2018-08-01 (星期三)poll(): #include <sys/poll.h> int poll (struct pollfd *fd, unsigned int nfds, ...