【译】Android技术栈,1#架构

  • 初稿链接: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的源委

数据库 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());
    }

表现层

这个表现层是承受去表现图形和提供数据

资源:##

  • 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,用来放一些类库和工具类。

数据库 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的呼吁,这里自身利用了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());
    }

本文由开元棋牌发布于数据库,转载请注明出处:【译】Android技术栈,1#架构

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。