2018正版葡京赌侠诗【译】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或者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
(译者注:音信总线)系统,那一个类别对此播放事件,或者在多少个零件之间创建通信是异常实用的,尤其特别适用于后者。

基本上,通过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());
    }

资源:##

发表评论

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