Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [android架構篇]mvp+rxjava+retrofit+eventBus

[android架構篇]mvp+rxjava+retrofit+eventBus

編輯:關於Android編程

android架構篇

mvp+rxjava+retrofit+eventBus


高層不應該知道低層的細節,應該是面向抽象的編程。業務的實現交給實現的接口的類。高層只負責調用。


首先,要介紹一下一個項目中好架構的好處:好的軟件設計必須能夠幫助開發者發展和擴充解決方案,保持代碼清晰健壯,並且可擴展,易於維護,而不必每件事都重寫代碼。面對軟件存在的問題,必須遵守SOLID原則(面向對象五大原則),不要過度工程化,盡可能降低框架中模塊的依賴性。


之前的一段時間,學習了一些新的技術,並把自己關注的技術整合了一下,是的,相似的技術有很多,自己擇優選擇,將它們的思想和技術應用到了自己的搭建的項目框架中.
限於自己能力水平有限,自己搭建的項目可能還有些不足,歡迎大家指正批評,讓自己的想法和設計思想走向正軌.O(∩_∩)O謝謝~

在框架中

1.項目整體框架: 利用google-clean-architecture的思想 來負責項目的整體MVP架構.

MVP是模型(Model)、視圖(View)、主持人(Presenter)的縮寫,分別代表項目中3個不同的模塊。我以登錄為例子,進行說明.

這裡寫圖片描述
這裡每個業務首先要有一個管理接口Contract,在這裡面有三個接口來面向接口編程, (Model),(View),(Presenter). 將三個接口放在一起便於管理.
這裡寫圖片描述

   /**
 * 登錄關聯接口類
 *
 * Created by ccj on 2016/7/7.
 */
public interface LoginContract {
    interface View extends BaseView {
        void showProgress();
        void hideProgress();
        void showError(String error);
        void navigateToMain();
        void navigateToRegister();
    }
    interface Presenter extends BasePresenter {
        void login(String username, String password);
        void onDestroy();
    }
    interface Model{
        void saveUserInfo(User user);
        void saveLoginState(Boolean isLogin);
        void saveRememberPass(User user);

    }

}

模型(Model):實現 implements LoginContract.Model 負責處理數據的加載或者存儲,比如從網絡或本地數據庫獲取數據等;這裡的login 涉及到的業務邏輯比較少請求網絡 采用了rxjava +retroft+gsons 相當於 model層. 如果處理的出具多,就采用此model ,就像圖片保存顯示等等.

視圖(View):采用接口的方式,讓activity實現該接口,接口中有關於視圖的方法,例如”initVIew()”,”showDialog()”,”hideDialog()”等等, 負責界面數據的展示,與用戶進行交互;

public class LoginActivity extends BaseActivity implements LoginContract.View {

//省略bufferknife 注解
private LoginPresenter presenter;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    ButterKnife.bind(this);
    presenter=new LoginPresenter(this);
    presenter.start();//初始化控制層
}

//實現於view的方法
@Override
public void navigateToMain() {
    Intent intent =new Intent(getBaseContext(),MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(intent);
}
主持人(Presenter):持有 view和model的對象,操作兩者的方法.相當於協調者,是模型與視圖之間的橋梁,將模型與視圖分離開來,對view 和model 進行調度操作。
  /**
 * login的presenter層 進行對view 和 model 的控制,
 * Created by ccj on 2016/7/7.
 */
public class LoginPresenter implements LoginContract.Presenter {

    private LoginContract.View loginView;
    public LoginPresenter(LoginContract.View loginView) {
        this.loginView = loginView;
    }

    @Override
    public void login(String username, String password) {
        loginView.showProgress();
        Observable userObservable = APIService.userLogin(username, password);
        userObservable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber() {
                    @Override
                    public void onCompleted() {
                        loginView.hideProgress();
                    }

                    @Override
                    public void onError(Throwable e) {
                        TLog.log(e.getMessage().toString());
                        loginView.hideProgress();
                        loginView.showError(e.getMessage().toString());
                    }

                    @Override
                    public void onNext(User getIpInfoResponse) {
                        TLog.log(getIpInfoResponse.toString());
                        loginView.navigateToMain();
                    }
                });
    }

    @Override
    public void start() {

    }

2.網絡訪問: 采用rxjava+retrofit+gson進行網絡訪問,並輕松的將json轉為對象,結構清晰,使用方便.

在APIService中初始化retrofit
 /**
 * 調用後台的接口,架構網絡層采用Retroft+Rxjava+gson
 * Created by ccj on 2016/7/1.
 *
 */
public class APIService {

    private static final String TAG = "APIService";
    public static final String URL_HOST ="http://123.234.82.23" ;//服務器端口
    /**
     * 基礎地址
     * 初始化 retroft
     */
    private static final Retrofit sRetrofit = new Retrofit.Builder()
            .baseUrl(URL_HOST)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 使用RxJava作為回調適配器
            .build();
    private static final RetrofitRequest apiManager = sRetrofit.create(RetrofitRequest.class);
    /**
     * 登錄,返回,我這邊用的是json格式的post,大家可以進行選擇
     * @param city
     * @return
     */
    public static Observable userLogin(String format, String city) {
        HashMap hashMap =new HashMap<>();
        hashMap.put("UserPhone", format);
        hashMap.put("UserPassWord", city);
        TLog.log(hashMap.toString());
        Observable ss = apiManager.userLogin(hashMap);
        return  ss;
    }

    /**********************仿照上面的方法,進行請求數據****************************/
用retrofit訪問 返回observable的對象
public interface RetrofitRequest {


    boolean isTest=true; //是否在測試環境下
    //發布之前更改
    String BASE_URL_TEST = "/flyapptest/";//測試服務器
    String BASE_URL_OFFICAL = "/flyapp/";//正式服務器

    String BASE_URL = isTest?BASE_URL_TEST:BASE_URL_OFFICAL;//發布服務器


    /**
     * 登錄返回(json post)
     * @param body
     * @return
     */
    @Headers( "Content-Type: application/json" )
    @POST(BASE_URL+"Login.ashx/")
    Observable userLogin(@Body HashMap body);

3.異步處理: 采用rxjava響應式框架進行優雅的異步處理,簡化代碼邏輯,並且很好的解決內存洩漏 問題.(相關模塊在TakePhoto業務中)

  /**
     * rxjava 進行異步操作 eventBus進行時間傳遞
     * @param data
     */
    @Override
    public void savePhoto(final Intent data) {
        TLog.log("savePhoto", "data-->" + data.getData().toString());
        Log.e("Tlog-->", "data-->" + data.getData().toString());
        saveObservable = Observable.fromCallable(new Callable() {
            @Override
            public String call() throws Exception {//通知調用  並返回string
                return savePic(data);//此方法在io線程中調用 並返回
            }
        });

        saveSubscription = saveObservable
                .subscribeOn(Schedulers.io())//observable在調度中的IO線程中進行調度進行
                .observeOn(AndroidSchedulers.mainThread())//在主線程中進行觀察
                .subscribe(new Observer() {//訂閱觀察者
                    @Override
                    public void onCompleted() {
                        Log.e("Tlog-->", "onCompleted-->");
                    }
                    @Override
                    public void onError(Throwable e) {
                        Log.e("Tlog-->", "Throwable-->" + e.getMessage().toString());
                        EventBus.getDefault().post(new EventUtils.ObjectEvent(e.getMessage().toString()));
                    }
                    @Override
                    public void onNext(String s) {//帶參數的下一步,在此就是當
                        Log.e("Tlog-->", "s-->" + s);
                        EventBus.getDefault().post(new EventUtils.ObjectEvent(bitmap));

                    }
                });
    }

4.事件訂閱: 采用EventBus作為事件總線,進行線程間,組件之間的通信.

/**
 * 事件總線 用於組件或線程通信,可替代回調,廣播等
 * Created by ccj on 2016/4/14.
 */
public class EventUtils {

    /**
     * object類型(即傳統的所有類型,都可以強轉進行傳遞事件)
     */
    public static class ObjectEvent{
        private Object object;
        public ObjectEvent(Object object) {
            // TODO Auto-generated constructor stub
            this.object = object;
        }
        public Object getMsg(){
            return object;
        }
    }

}

5.代碼分包: 根據業務區分進行分包,便於對代碼進行管理 .

這裡寫圖片描述

6. 工具類: TDeviceUtils設備狀態的工具類,,SeriliazebleUtils 序列化工具類,SharepreferenceUtils保存工具類,
相關請參考代碼

7.app棧管理: 基於baseActivity,很好的釋放內存,管理內存.
相關請參考代碼


待後期完成

異常捕獲(待完善)
測試框架Espresso/JUnit/Mockito/Robolectric (待完善)
gradle相關構建編譯


總結

1.層次分明,各層級之間都不管對方如何實現,只關注結果;
2.在視圖層(Presentation Layer)使用MVP架構,使原本臃腫的Activity(或Fragment)變得簡單,其處理方法都交給了Presenter。
3.易於做測試,只要基於每個模塊單獨做好單元測試就能確保整體的穩定性。
4.易於快速迭代,基於代碼的低耦合,只需在業務邏輯上增加接口,然後在相應的層級分別實現即可,絲毫不影響其他功能。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved