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

本文是哪些支付一款颇具扩充性,维护性和测试性的Android应用专题的首先篇。本专题将会涉嫌到有的设计情势和类库的选择办法,裁减Android
Developer
通常支出的愤懑。

简介:##

作为例子,作者将接纳以下那几个类型,事实上正是多少个大致的影视概念目录,能够称呼视图可能其余。

至于影片的消息能够从一个称作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或者2018年全年资料大全,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')
}

Model module##

model
module负责处理消息,查询,保存,删除等等,笔者只处理了从API获取电影详情的操作。

也完成了有的实体类,比如TvMovie,用来表现一部电影。

它近日只依赖common
module,通过那几个类库处理API请求,在这一个例子中小编利用Square出品的Retrofit,小编将在接下去的博客中介绍Retrofit。

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

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上的显现。

通信##

对于那个类型,笔者采用了Message
Bus
(译者注:音讯总线)系统,这一个系统对于播放事件,或然在七个零部件之间创制通讯是10分管用的,特别尤其适用于后者。

基本上,通过Bus出殡事件,对事件感兴趣的类,须要订阅Bus,才能消费十二分事件。

适用这几个体系能够减低模块间的耦合度。

为了兑现那个系统总线,小编利用Square出品的Otto类库。

本身定义了三个Bus,1个用来使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亟需实现2个情势,这些形式所承受参数的数据类型必须与Bus出殡的轩然大波的数据类型一致,兵器必须利用申明:@Subscribe

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

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

资源:##

发表评论

电子邮件地址不会被公开。 必填项已用*标注