澳门永利网上娱乐普通支付之烦扰。英语阅读能力较强的情人可一直去押原稿。

  • 原稿链接:A useful stack on android #1,
    architecture
  • 原文作者:
    Saúl
    Molinero
  • 译文出自:
    稍稍鄧子的简书
  • 译者: 小鄧子

原稿标题:A useful stack on android #1, architecture

正文是怎样开发同缓慢有着扩展性,维护性和测试性的Android应用专题的率先首。本专题将会见波及到部分设计模式和类库的以办法,减少Android
Developer
寻常支付的堵。

正文是针对性该文章的翻译,本人翻译水平有限,但是会尽力而为保证不见面起明显的逻辑错误,英语阅读能力较强之心上人可直接去看原稿。
欠篇的种要采用了MVP的模式,并下了Square的Retrofit和Otto这点儿只仓库,这篇文章属于即同一层层之首先篇。
末了重复补充一词,如果起甚翻译错的,请各位朋友务必指出,不杀感激QAQ,如果来吗疑惑欢迎提出,共同讨论。

简介:##

当例子,我用运以下这项目,事实上便是一个简易的电影概念目录,可以叫视图或者其它。

关于影片之音讯可由一个叫作Themoviedb的公然API中拿走,在此版块中Apiary可找到正确的文档说明。

品类基于Model View
Presenter

设计模式,也参照了片Material
Design

设计规范,比如转场,(界面)结构,动画,配色等等。

具有代码都得以自Github遭遇拿走,所以恳请随意看,这里同样有一个视频因此来显示App。

Paste_Image.png


架构:##

搭的计划基于Model View
Presenter

,它是Model View
Controller

设计模式的一个变种。

这种计划试图抽象Presentation臃肿的事情逻辑,在Android中马上是蛮重大之,因为自Framework
提倡这点儿有些与数码层解耦合,一个眼看的例证就是AdaptersCursorLoaders

这种架构促使业务逻辑层和数据层不再随着视图层的转移而更改,这样不管Domain臃肿的代码复用还是如Database或者REST
API
等于数据源的改观,都变得简单起来。

译文如下:

概述##

这种结构得以给细分为老三独第一层次:

  • presentation
  • model
  • domain

Presentation
Presentation臃肿负责提供数据并显示图形化界面。

Model
Model臃肿将肩负提供信息,这等同层并不知道Presentation层和Domain,它能及数据库,REST
API或者其它可持久化数据等落实连续。

当及时等同重合,也得兑现部分应用程序的实体类,用来代表,电影,种类等等。

Domain
Domain臃肿完全独立为Presentation臃肿之外,这等同交汇专门处理工作逻辑。

立马是以系列的第一篇稿子,本系列以介绍如何安排环境去开发一个享可扩展性、可维护性和而测试性的档次,在按照系列被,我将涵盖一些模式和与类库的利用要安卓开发者在平凡中未见面疯狂。

实现##

Domain层和Model臃肿为放大至个别单java module中,app
module也就是是Android应用代表Presentation臃肿,这里还有另外一个common
module,用来存放有国有类库和工具类们。

Domain module

Domain
module存放着部分usecase同其的贯彻类似,它们是应用程序的事情逻辑。

这个module完全独立为Android framework

据它的模块出model module和common module。

一个usecase可为此来获取不同门类电影之毕竟评分,看一样收押何人品种的影片最为给欢迎,usecase待获取信息然后做出计算,所有这些信还是因为Model层提供。

dependencies {
    compile project (':common')
    compile project (':model')
}

概要

作例子,我将以下面的品种,这是一个简约的电影目录,能够让标记为视图或者挂起。

有关电影的音是调用这个公共接口
themoivedb,你能在Apiary立同章找到确切的文档

夫类别是因Model View
Presenter(MVP)模式,也促成了片Material
Design的宏图,比如转场、结构、动画、配色等等。

怀有的代码能在github上面下载,这里吧起一个视频显示这个app的始末

App展示

Model module##

model
module负责处理信息,查询,保存,删除等等,我特处理了于API获取电影详情的操作。

也落实了片实体类,比如TvMovie,用来表现一样统影片。

其目前只依赖common
module,通过这类库处理API请求,在这事例中本人用Square出品的Retrofit,我拿当连片下的博客中介绍Retrofit。

dependencies {
    compile project(':common')
    compile 'com.squareup.retrofit:retrofit:1.9.0'
}

架构:

其一架构的筹划是依据MVP模式,MVP模式是MVC模式之同一种植演变

这种模式尝试去抽象表现层的作业逻辑,在Android中就是老关键的,因为我们的框架降低了它和数据层的耦合度,一个明白的例子就是Adaters或者CursorLoaders。

这种架构促使,视图层的变不欲修改工作逻辑层和数据层。这样就是可怜简短的复用代码或者变化多种多样的数据源,比如数据库或者REST
API

翻译注:以上只是针对MVP模式的简单介绍

Presentation module##

便Android应用自身,包括resources, assets, 逻辑等等。

它们跟履行usecaseDomain拓展交互,比如可以为此来得到有平时段的影片列表,或者从某个电影中得到特殊的数目。

夫模块只含有PresenterView

每一个ActivityFragmentDialog都实现MVPView接口,它指定了有的当View直达展开展示,隐藏,显示信息等操作。

比如,PopularMoviesView通过点名一些操作展示时影视列表,然后MoviesActivity实现它。

public interface PopularMoviesView extends MVPView {

    void showMovies (List<TvMovie> movieList);

    void showLoading ();

    void hideLoading ();

    void showError (String error);

    void hideError ();
}

MVP设计模式就是吃View转换得硬着头皮的简练,由Presenter控制其的所作所为。(译者注:View臃肿应反映KISS基准,感兴趣的同窗可以了解一下Keep
it simple stupid

public class MoviesActivity extends ActionBarActivity implements
    PopularMoviesView, ... {

    ...
    private PopularShowsPresenter popularShowsPresenter;
    private RecyclerView popularMoviesRecycler;
    private ProgressBar loadingProgressBar;
    private MoviesAdapter moviesAdapter;
    private TextView errorTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        ...
        popularShowsPresenter = new PopularShowsPresenterImpl(this);
        popularShowsPresenter.onCreate();
    }

    @Override
    protected void onStop() {

        super.onStop();
        popularShowsPresenter.onStop();
    }

    @Override
    public Context getContext() {

        return this;
    }

    @Override
    public void showMovies(List<TvMovie> movieList) {

        moviesAdapter = new MoviesAdapter(movieList);
        popularMoviesRecycler.setAdapter(moviesAdapter);
    }

    @Override
    public void showLoading() {

        loadingProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {

        loadingProgressBar.setVisibility(View.GONE);
    }

    @Override
    public void showError(String error) {

        errorTextView.setVisibility(View.VISIBLE);
        errorTextView.setText(error);
    }

    @Override
    public void hideError() {

        errorTextView.setVisibility(View.GONE);
    }

    ...
}

这个usecase通过Presenter调用,并且Presenter接相应结果,然后处理View及的呈现。

概述

这种架构会分成三重叠:

  • presentation(也就算是上文一直翻译的见层)
  • model
  • domain

    otto

通信##

对此此路,我选择了Message
Bus
(译者注:消息总线)系统,这个系统对于播放事件,或者以个别只零部件之间建立通信是怪有效之,尤其特别适用于后者。

基本上,通过Bus出殡事件,对事件感兴趣的切近,需要订阅Bus,才能够花十分事件。

适用是系统可以降低模块间的耦合度。

为落实之系统总线,我利用Square出品的Otto类库。

自定义了简单单Bus,一个因此来要usecase及REST
API进行通信,另一个于是来发送事件到Presentation
层。

REST_BUS应用任意线程处理事件,UI_BUS利用默认线程发送事件,这个线程就是主线程。

public class BusProvider {

    private static final Bus REST_BUS = new Bus(ThreadEnforcer.ANY);
    private static final Bus UI_BUS = new Bus();

    private BusProvider() {};

    public static Bus getRestBusInstance() {

        return REST_BUS;
    }

    public static Bus getUIBusInstance () {

        return UI_BUS;
    }
}

夫仿佛经过common
module管理。因为兼具的模块都急需看它,从而和Bus开展交互。

dependencies {
    compile 'com.squareup:otto:1.3.5'
}

说到底,想象一下此场景,当用户打开应用,显示最让欢迎之影片。

View调用onCreate()方法时,Presenter订阅UI_BUS吸纳事件。当onStop()办法给调用的时候Presenter收回订阅。Presenter运行GetMoviesUseCase这个usecase

@Override
    public void onCreate() {

        BusProvider.getUIBusInstance().register(this);

        Usecase getPopularShows = new GetMoviesUsecaseController(GetMoviesUsecase.TV_MOVIES);
        getPopularShows.execute();
    }

    ...

    @Override
    public void onStop() {

        BusProvider.getUIBusInstance().unregister(this);
    }
}

以接收事件,Presenter待贯彻一个道,这个办法所领参数的数据类型必须同Bus出殡的波之数据类型一致,兵器必须下注解:@Subscribe

@Subscribe
    @Override
    public void onPopularMoviesReceived(PopularMoviesApiResponse popularMovies) {

        popularMoviesView.hideLoading();
        popularMoviesView.showMovies(popularMovies.getResults());
    }

表现层

这个表现层举凡当夺变现图形和提供数据

资源:##

  • Architecting Android…The clean
    way? –
    Fernando Cejas

  • Effective Android
    UI –
    Pedro Vicente Gómez Sanchez

  • Reactive programming and message buses for
    mobile –
    Csaba Palfi

  • The clean
    architecture –
    Uncle Bob

  • MVP
    Android –
    Antonio Leiva

模型层

型负责提供信息,这无异于重合并不知道domain层和表现层,它亦可促成对数据库的连天和接口,使用REST
API或者其它方法

Domain

domain层是一心独立于表现层,它以位于你的以之事务逻辑。

实现

domain层和模型层被分成两只module,表现层在主app的module,还有一个受common的module,用来加大有类库和工具类。

app架构图

Domain module

domain module 有着usecases和其的落实类似,这是当利用的政工逻辑

是模块是一点一滴独立于Android框架

它们是凭让 model module 和 common module。

usecase 能够赢得各种影片之评级,看看啊一样好像是极度让欢迎的。usecase
会需要获得电影之音并盘算,将这些消息提供于model。

dependencies {
    compile project (':common')
    compile project (':model')
}

Model module

Model module
是承担对信息的管理,增删改查等等,在第一独版本我只有对影片api的音讯进行保管。

她为兑现了实体,比如TvMovie这个看似表示也一个电影。

她时只依赖 common
module,这个类库被用来保管API的请求,这里自己以了Square的Retrofit,我拿当下文介绍Retrofit。

Presentation module

即时即是app本身,有着resources, assets ,逻辑等等。

它们吧和 domain 正在运转的 usecases
相互影响着,比如,想博得有特定时间之影或千篇一律部影片的指定时间。

在这个module中有着 presentersviews

每个Activity,Fragment,Dialog都落实了MVPView接口,它指定了在View上开展亮、隐藏和打信息之操作。

选举个例子,PopularMoviesView指定了形当前影视列表的操作,并受MoivesActivity实现这些点子。

public interface PopularMoviesView extends MVPView {

    void showMovies (List<TvMovie> movieList);

    void showLoading ();

    void hideLoading ();

    void showError (String error);

    void hideError ();
}

MVP模式让视图变得硬着头皮简单,由presenter决定视图的所作所为

public class MoviesActivity extends ActionBarActivity implements
    PopularMoviesView, ... {

    ...
    private PopularShowsPresenter popularShowsPresenter;
    private RecyclerView popularMoviesRecycler;
    private ProgressBar loadingProgressBar;
    private MoviesAdapter moviesAdapter;
    private TextView errorTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        ...
        popularShowsPresenter = new PopularShowsPresenterImpl(this);
        popularShowsPresenter.onCreate();
    }

    @Override
    protected void onStop() {

        super.onStop();
        popularShowsPresenter.onStop();
    }

    @Override
    public Context getContext() {

        return this;
    }

    @Override
    public void showMovies(List<TvMovie> movieList) {

        moviesAdapter = new MoviesAdapter(movieList);
        popularMoviesRecycler.setAdapter(moviesAdapter);
    }

    @Override
    public void showLoading() {

        loadingProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {

        loadingProgressBar.setVisibility(View.GONE);
    }

    @Override
    public void showError(String error) {

        errorTextView.setVisibility(View.VISIBLE);
        errorTextView.setText(error);
    }

    @Override
    public void hideError() {

        errorTextView.setVisibility(View.GONE);
    }

    ...
}

usecase 将被 presenter 执行,他们用收响应并对views管理。

public class PopularShowsPresenterImpl implements PopularShowsPresenter {

    private final PopularMoviesView popularMoviesView;

    public PopularShowsPresenterImpl(PopularMoviesView popularMoviesView) {

        this.popularMoviesView = popularMoviesView;
    }

    @Override
    public void onCreate() {

        ...
        popularMoviesView.showLoading();

        Usecase getPopularShows = new GetMoviesUsecaseController(GetMoviesUsecase.TV_MOVIES);
        getPopularShows.execute();
    }

    @Override
    public void onStop() {

        ...
    }


    @Override
    public void onPopularMoviesReceived(PopularMoviesApiResponse popularMovies) {

        popularMoviesView.hideLoading();
        popularMoviesView.showMovies(popularMovies.getResults());
    }
}

通讯

这个类型被本身选了一个Message
Bus系统,这个系统充分有用于广播事件,它成立了点滴单零部件之间的通信。

要事件都是通过发送一个Bus,如果想去消费有Bus,就用去订阅者Bus。

用这个体系,整个module就会见持有低耦合度。

为了贯彻此体系,我以了Square的Otto类库。

自家声明了有限独Bus,一个用来usecases的REST API
通信,另外一个用以表现层发送事件。

REST_BUS运用任何线程进行事件之处理,UI_BUS于UI线程,也就算是主线程上进行事件的拍卖。

public class BusProvider {

    private static final Bus REST_BUS = new Bus(ThreadEnforcer.ANY);
    private static final Bus UI_BUS = new Bus();

    private BusProvider() {};

    public static Bus getRestBusInstance() {

        return REST_BUS;
    }

    public static Bus getUIBusInstance () {

        return UI_BUS;
    }
}

这近乎为用于管理 common
module,因为具备的module可以拜它,并跟bus相互影响。

dependencies {
    compile 'com.squareup:otto:1.3.5'
}

末尾,思考下面的事例,在用户打开App的上显得多数被欢迎的影视。

OnCreate方式给Android视图调用的时候,这个presenter订阅UI_BUS用来接受事件。这个presenter在OnStop法给调用的时光解除订阅,这个presenter运行在GetMoivesSerCase.

@Override
    public void onCreate() {

        BusProvider.getUIBusInstance().register(this);

        Usecase getPopularShows = new GetMoviesUsecaseController(GetMoviesUsecase.TV_MOVIES);
        getPopularShows.execute();
    }

    ...

    @Override
    public void onStop() {

        BusProvider.getUIBusInstance().unregister(this);
    }
}

领事件的语句,这个presenter一定要促成一个方法,这个点子的参数要同发送事件的办法的参数相同,并且一定要是动用Subscribe注解。

@Subscribe
    @Override
    public void onPopularMoviesReceived(PopularMoviesApiResponse popularMovies) {

        popularMoviesView.hideLoading();
        popularMoviesView.showMovies(popularMovies.getResults());
    }