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

设计形式的3个变种。

那种设计试图抽象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,才能消费11分事件。

适用这么些系统能够下跌模块间的耦合度。

为了兑现这么些系统总线,小编利用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());
    }

资源:##

发表评论

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