斯洛伐克(Slovak)语阅读才干较强的情侣能够直接去看原稿,通常开销的烦恼

原来的文章标题:A useful stack on android #1, architecture

正文是如何支付一款具有扩大性,维护性和测量检验性的Android应用专项论题的率先篇。本专项论题将会波及到有的设计方式和类库的利用形式,裁减Android
Developer
万般支出的非常慢。

正文是对该文章的翻译,本人翻译水平有限,可是会不遗余力确定保障不会合世明显的逻辑错误,塞尔维亚语阅读技艺较强的意中人能够一直去看原稿。
该文章的项目主要采取了MVP的情势,并利用了Square的Retrofit和奥托那四个库,那篇作品属于这一种类的率先篇。
最后再补一句,若是有啥翻译错的,请各位朋友务必提议,不甚感谢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的从头到尾的经过

澳门永利网上娱乐 1

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
    澳门永利网上娱乐 2
    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());
    }

表现层

这个表现层是肩负去展现图形和提供数据

资源:##

模型层

模型负担提供音信,这一层并不知道domain层和表现层,它能促成对数据库的一连和接口,使用REST
API恐怕别的格局

Domain

domain层是一丝一毫独立于表现层,它将位于你的施用的职业逻辑。

实现

domain层和模型层被分成多个module,展现层在主app的module,还会有三个叫common的module,用来放一些类库和工具类。

澳门永利网上娱乐 3

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的乞求,这里笔者使用了SquareRetrofit,小编将在下文介绍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就能有所低耦合度。

为了完毕那个系列,笔者动用了SquareOtto类库。

本身申明了多个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());
    }