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

  • 原稿链接:A useful stack on android #1,
    architecture
  • 原文作者:
    Saúl
    Molinero
  • 译文出自:
    粗鄧子的简书
  • 译者: 小鄧子

本文是什么支付同慢慢悠悠颇具扩展性,维护性和测试性的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接过相应2018年全年资料大全结果,然后处理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());
    }

资源:##

  • 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

发表评论

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