月度归档:2016年05月

仿知乎日报开发历程(一)

记录一下开发一款类似知乎日报的 App。计划使用 MVP,RxJava,RxBus,Retrofit。

Day 1

Resource

  1. api 资源:知乎日报 API 分析
  2. RxJava 学习:给 Android 开发者的 RxJava 详解
  3. RxBus 实现:通过 RxJava 实现一个 Event Bus – RxBus
  4. Retrofit 学习:RxJava 与 Retrofit 结合的最佳实践
  5. MVP 学习:

Process

model

  1. 利用 GsonFormat 生成 API 接口返回 json 对应的 bean;
  2. 写 Retrofit 格式的 API 接口;

    public interface API {
    
       @GET("news/latest")
       rx.Observable<LatestNews> getLatestNews();
    }
    
  3. 声明 Data 接口,用2中声明的接口生成 Retrofit 对象
    Retrofit retrofit = new Retrofit.Builder()
               .baseUrl(Constants.API_HOST)
               .addConverterFactory(GsonConverterFactory.create())
               .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
               .build();
    
       private API mAPI = retrofit.create(API.class);
    

    调用2中接口中的方法请求数据

    public void getLatestNews() {
           mAPI.getLatestNews()
                   .subscribeOn(Schedulers.io())
                   .subscribe(new Observer<LatestNews>() {
                       @Override
                       public void onCompleted() {
    
                       }
    
                       @Override
                       public void onError(Throwable e) {
    
                       }
    
                       @Override
                       public void onNext(LatestNews latestNews) {
                           RxBus.getInstance().send(latestNews);
                       }
                   });
       }
    
  4. 得到 Retrofit 请求的结果后 send 结果到 RxBus。
    @Override
    public void onNext(LatestNews latestNews) {
    RxBus.getInstance().send(latestNews);
    }
    

common

  1. 新建 Constants 类保存 API HOST;
  2. 实现 RxBus。

    public class RxBus {
    
       private static final RxBus INSTANCE = new RxBus();
    
       public static RxBus getInstance() {
           return INSTANCE;
       }
    
       private final Subject<Object, Object> rxBus = new SerializedSubject<>(PublishSubject.create());
    
       public void send(Object o) {
           rxBus.onNext(o);
       }
    
       public Observable<Object> toObserverable() {
           return rxBus;
       }
    
       public boolean hasObservers() {
           return rxBus.hasObservers();
       }
    }
    

app

  1. 声明 View 接口,分析视图展示需要的方法,如 showData,showLoading,hideLoading 等;
    public interface LatestNewsView extends NewsView{
    
       void showNews(LatestNews news);
    
       void showLoading();
    
       void hideLoading();
    }
    
  2. 声明 Presenter 抽象类,引入 start,stop 方法等;
    public abstract class Presenter {
       public abstract void start();
       public abstract void stop();
    }
    
  3. 继承 Presenter,如 MainPresenter,在成员变量中引入 model 的 Data 对象,在构造函数中传入 view 对象,
    private NewsData mNewsData;
    private LatestNewsView mLatestNewsView;
    
    public LatestNewsPresenter(LatestNewsView latestNewsView) {
        mLatestNewsView = latestNewsView;
        mNewsData = new RestNewsData();
    }
    

    start 方法中请求数据,同时注册所需数据的监听;

    @Override
    public void start() {
       mNewsData.getLatestNews();
       RxBus.getInstance().toObserverable().subscribe(new Action1<Object>() {
           @Override
           public void call(Object o) {
               if (o instanceof LatestNews) {
                    mLatestNewsView.showNews((LatestNews) o);
               }
           }
       });
    }
    
  4. Activity 实现 View 接口,new 一个 Presenter 对象,在 onStart 中调用 Presenter 的 start 方法开始请求数据。

Notes

  1. Q:在 View(Activity、Fragment)层中怎么去调用 Presenter 中的方法?
    A:在View初始化时,new 一个 Presenter 实例。
  2. Q:Presenter 怎么去控制 View 中的界面逻辑?
    A:让 View 层通过实现特定 View 接口,每一个 View 类,也就是每一个 Activity 对应实现一个抽象的接口,也就是说在写每个 Activity 时,首先把具体的 View 操作动作提取为一个接口,让 View 实现,让后想办法把这个接口的实例传递到 Presenter 实例中。
  3. Q:Presenter 怎么去获取 model 中的数据?
    A:在 Presenter 中 new 一个 Data 对象。

Problem

  1. 把通用的资源写在 common 的 build.gradle 文件中,引入 app module 的时候报错:

    Error:Module 'ZhiHuDaily:common:unspecified' depends on one or more Android Libraries but is a jar
    

    最后发现是因为 common 是一个 jar module 引入的 RxAndroid 需要依赖 Android;

  2. RxJava 和 Retrofit 的结合需要引入额外的依赖