1. 程式人生 > >Android Retrofit+Rxjava+MVP三大框架整合

Android Retrofit+Rxjava+MVP三大框架整合

Retrofit的詳解

  • retrofit是基於okhttp的封裝工具類,功能十分豐富.我能力還是有限,在這裡先說下它的使用吧!

    簡單使用

    1. 新增Gradle依賴項

      compile 'com.squareup.retrofit2:retrofit:2.1.0'
    2. 建立Api介面

      作為一個get請求的url,並提供一些可變的引數

      @GET("yoururl/{neededParameter}")
      Call<ResponseBody> getParameter(@Path("parameter") String parameter);

      這裡的@Path只是為了用後面parameter來代替{neededParameter}這個佔位符

      還有其他的例如@Query就是類似於url?parameter=…這種

    3. 建立retrofit例項

      Retrofit retrofit=new Retrofit.Builder()
              .baseUrl(yourUrl)
              .addConverterFactory(GsonConventerFactory.create())
              .build();
      IApimanager apiManager=retrofit.create(IApiManager.class);
      Call<ResponseBody> call=apiManager.getParameter("parameter");
      call.enqueue(new Callback<ResponseBody>(){
          @Override
      public void onResponse(Call<User> call, Response<User> response)
      {
          Log.e(TAG, "getParameter:" + response.body());
      }
      
      @Override
      public void onFailure(Call<User> call, Throwable t)
      {
          Log.e(TAG,t.printStackTrace();
      }
      });

Rxjava

  • Rxjava,簡單來說, 它是一種模式, 類似於觀察者模式的這種,但又好像是升級的版本.總的來說,他也是一種簡化非同步操作的庫。

  • 我就結合一下我的這個專案給大家講一下RxJava的基本使用吧!

  • RxJava的基本使用

    • 相信大家也看到了上面的ApiManager返回的是一個Call型別的, 如果我們要使用RxJava的話, 就應該像下面這樣寫;
     @GET("index")
     rx.Observable<NewList> getNews(@Query("key") String key);

    只是把返回值換成了Rxjava 的Observable, 為什麼這麼做呢, 接下來就在Retrofit下做手腳了:

    public void getData(String key) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constant.URL_NEWS)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        IApiManager apiManager = retrofit.create(IApiManager.class);
        apiManager.getNews(key)
                .subscribeOn(Schedulers.io())
                .map(new Func1<NewList, List<News>>() {
                    @Override
                    public List<News> call(NewList newList) {
                        List<News> news = new ArrayList<News>();
                        for (NewList.ResultBean.DataBean eachNews : newList.getResult().getData()) {
                            News everyNews = new News();
                            everyNews.setDate(eachNews.getDate());
                            everyNews.setTitle(eachNews.getTitle());
                            everyNews.setThumbnail_pic_s(eachNews.getThumbnail_pic_s());
                            everyNews.setUrl(eachNews.getUrl());
                            news.add(everyNews);
                        }
                        return news;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<List<News>>() {
                    @Override
                    public void onCompleted() {
    
                    }
    
                    @Override
                    public void onError(Throwable e) {
                        Toast.makeText(getActivity(), "網路出了些問題", Toast.LENGTH_SHORT).show();
                        e.printStackTrace();
                    }
    
                    @Override
                    public void onNext(List<News> newses) {
                        mRefreshNewsAdapter.addAll(newses);
                    }
                });
    }

    或許你會感到頭疼, 為什麼這麼長一大串啊, 說好的簡潔去了哪裡.

    其實, RxJava是邏輯的簡潔, 讓我來給你分析一下吧!

    首先是addCallAdapterFactory(RxJavaCallAdapterFactory.create()) ,這個是新增一個RxJava介面卡

    然後就是那一大串什麼鬼, getNews(key)後面是什麼鬼, 其實是 getNews返回的一個Obserable型別, 這個Obserable呢, 就是可以被觀察的物件了, 詳情就可以去了解上面那篇文章.

    map操作進行了簡單的json資料解析, 而這個操作是進行再子執行緒的io裡, 然後再回到主執行緒, 將資料分別顯示出來.

    對於RxJava的我這裡也就用了這麼多, 其實還有很多用法沒有在這裡寫出來, 有興趣的朋友可以去探索上面那篇文章, 寫得真的很適合新手入門的.

MVP

  • 什麼是MVP結構?

    相信大家應該聽說過什麼是MVC結構(model,view,controller) , 這三個英文單詞簡單的說一下, model(模型)業務邏輯和實體模型, view(檢視)就是佈局檔案, controller(控制器)Activity.

    沒錯, 大家入門開始寫的專案, 大多數都是以這種為架構的, 常說的Activity處理一切事物, 導致了一個檔案裡面程式碼幾百行, 甚至上千行, 所以我們要學習MVP結構 , 從而來提高專案的解耦性, 啥是解耦?

    就是各個模組的依賴度, 你依賴著你爸媽, 當你長大了, 慢慢獨立了, 解耦性就高了.

    好了, 說了那麼多MVC, 換到MVP來, MVP和MVC只是一字之差?

    P和C 有什麼區別啊? P-presenter / C-controller

    Presenter主要用來完成View和Model的互動, controller是Activity,完成大多數工作.

  • MVC 和 MCP 的區別

    這裡引用一下hongyang大佬的圖片, 地址淺談 MVP in Android

    這裡寫圖片描述

  • 專案例項

    其實大多數用來做登入註冊的demo, 其實整個app用的MVP主要還是在登入註冊, 其他的用了Retrofit和RxJava

    首先看看下面的紅色框的檔案

    這裡寫圖片描述

    1. 建立Model

      實體類User

      public class User {
          private String mUserName;
          private String mPassword;
      
          public User(String userName, String password) {
              mUserName = userName;
              mPassword = password;
          }
      
          public String getUserName() {
              return mUserName;
          }
      
          public void setUserName(String userName) {
              mUserName = userName;
          }
      
          public String getPassword() {
              return mPassword;
          }
      
          public void setPassword(String password) {
              mPassword = password;
          }
      }

      業務邏輯UserModel類

      public class UserModel {
          public void login(final String userName, final String password, final OnLoginListener onLoginListener){
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          Thread.sleep(2000);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      if("ThatNight".equals(userName)&&"123".equals(password)){
                          User user=new User(userName,password);
                          onLoginListener.loginSuccess(user);
                      }else{
                          onLoginListener.loginFailed();
                      }
                  }
              }).start();
          }
      }

      登入監聽介面OnLoginListener

      public interface OnLoginListener {
          void loginSuccess(User user);
          void loginFailed();
      }
    2. 建立View

      登入介面ILoginView,主要是寫一些在UI操作的方法

      public interface ILoginView {
          void loginSuccess();
      
          void loginFailed();
      
          void setPbVisiable(int visiable);
      
          void showText(String text);
      
          String getUserName();
      
          String getPassword();
      
      }

      然後LoginActivity實現ILoginView介面, 並實現方法

      public class LoginActivity extends AppCompatActivity implements ILoginView {
      
          @InjectView(R.id.et_login_name)
          EditText mEtLoginName;
          @InjectView(R.id.et_login_pwd)
          EditText mEtLoginPwd;
          @InjectView(R.id.btn_login_login)
          Button mBtnLoginLogin;
          @InjectView(R.id.progressBar)
          ProgressBar mProgressBar;
      
          private LoginPresenter mLoginPresenter;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_login);
              ButterKnife.inject(this);
              init();
          }
      
          private void init() {
              mLoginPresenter = new LoginPresenter(this);
      
          }
      
          @Override
          public void loginSuccess() {
              setPbVisiable(View.INVISIBLE);
              Intent intent = new Intent(LoginActivity.this, MainActivity.class);
              startActivity(intent);
              finish();
          }
      
          @Override
          public void loginFailed() {
              Toast.makeText(this, "登入失敗!", Toast.LENGTH_SHORT).show();
          }
      
          @Override
          public void setPbVisiable(int visiable) {
              mProgressBar.setVisibility(visiable);
              if (visiable == View.VISIBLE) {
                  mBtnLoginLogin.setEnabled(false);
              } else {
                  mBtnLoginLogin.setEnabled(true);
              }
          }
      
          @Override
          public void showText(String text) {
              Toast.makeText(this, text + " 登入成功!", Toast.LENGTH_SHORT).show();
          }
      
          @Override
          public String getUserName() {
              return mEtLoginName.getText().toString();
          }
      
          @Override
          public String getPassword() {
              return mEtLoginPwd.getText().toString();
          }
      
          @OnClick(R.id.btn_login_login)
          public void onClick() {
          }
      }
    3. 建立Presenter類

      主要是寫一個方法讓LoginActivity呼叫, 比如按下登入按鈕就呼叫這裡的login方法.

      public class LoginPresenter {
          private ILoginView mILoginView;
          private UserModel mUserModel;
          private Handler mHandler = new Handler();
      
          public LoginPresenter(ILoginView ILoginView) {
              mILoginView = ILoginView;
              mUserModel = new UserModel();
          }
      
      
          public void login() {
              mILoginView.setPbVisiable(View.VISIBLE);
              mUserModel.login(mILoginView.getUserName(), mILoginView.getPassword(), new OnLoginListener() {
                  @Override
                  public void loginSuccess(final User user) {
                      mHandler.post(new Runnable() {
                          @Override
                          public void run() {
                              mILoginView.showText(user.getUserName());
                              mILoginView.loginSuccess();
                          }
                      });
                  }
      
                  @Override
                  public void loginFailed() {
                      mHandler.post(new Runnable() {
                          @Override
                          public void run() {
                              mILoginView.loginFailed();
                          }
                      });
                  }
              });
          }
      }

      效果圖:
      這裡寫圖片描述

總結

  • 雖然感覺這三大框架的app到處都是, 但是要真正的熟悉裡面的邏輯, 還是需要花費一定時間來拆輪子, 不研究這些原始碼,只會使用是永遠不足夠的, 好好加油!

  • 最終效果圖:

    這裡寫圖片描述