鴻蒙 MVP+ Rxjava+Retrofit+okhttp 實(shí)現(xiàn)教程
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言:
各位同學(xué)大家好,有段時(shí)間沒(méi)有給大家更新文章 ,最近還在學(xué)習(xí)鴻蒙開(kāi)發(fā)的支持,就想著把a(bǔ)ndroid里面部分用到知識(shí)搬到鴻蒙里面 因?yàn)榛A(chǔ)語(yǔ)言都是java 語(yǔ)言,所以就寫(xiě)了現(xiàn)在這教程 那么廢話(huà)不多說(shuō)我們正式開(kāi)始
##效果圖

準(zhǔn)備工作
1 安裝鴻蒙開(kāi)發(fā)環(huán)境 大家可以看我之前的文章
需要用到的三方庫(kù)
- //okhttp3
 - implementation 'com.squareup.okhttp3:okhttp:4.2.0'
 - implementation "com.squareup.okhttp3:logging-interceptor:3.10.0"
 - //retrofit2
 - implementation 'com.squareup.retrofit2:retrofit:2.9.0'
 - implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
 - implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
 
請(qǐng)?jiān)赽uild.gradle里面添加依賴(lài)然后sygn now 同步下載依賴(lài)
具體實(shí)現(xiàn)
MainAbility布局代碼
- <?xml version="1.0" encoding="utf-8"?>
 - <DirectionalLayout
 - xmlns:ohos="http://schemas.huawei.com/res/ohos"
 - ohos:height="match_parent"
 - ohos:width="match_parent"
 - ohos:orientation="vertical">
 - <Text
 - ohos:id="$+id:text_fruit_tag"
 - ohos:height="35vp"
 - ohos:width="match_parent"
 - ohos:background_element="$graphic:text_element"
 - ohos:layout_alignment="left"
 - ohos:text="賬戶(hù)"
 - ohos:text_size="85"
 - ohos:right_margin="20vp"
 - ohos:left_margin="20vp"
 - ohos:top_margin="25vp"
 - ohos:text_color="#000000"
 - />
 - <TextField
 - ohos:id="$+id:text_username"
 - ohos:height="35vp"
 - ohos:width="match_parent"
 - ohos:background_element="$graphic:text_element"
 - ohos:layout_alignment="left"
 - ohos:text_size="50"
 - ohos:right_margin="20vp"
 - ohos:left_margin="20vp"
 - ohos:text_color="#000000"
 - ohos:top_margin="25vp"
 - ohos:basement="#000099"
 - ohos:hint="請(qǐng)輸入賬號(hào)"
 - />
 - <Text
 - ohos:id="$+id:text_number_tag"
 - ohos:height="35vp"
 - ohos:width="match_parent"
 - ohos:background_element="$graphic:text_element"
 - ohos:layout_alignment="left"
 - ohos:text="密碼"
 - ohos:text_size="85"
 - ohos:right_margin="20vp"
 - ohos:left_margin="20vp"
 - ohos:text_color="#000000"
 - ohos:top_margin="25vp"
 - />
 - <TextField
 - ohos:id="$+id:text_password"
 - ohos:height="35vp"
 - ohos:width="match_parent"
 - ohos:background_element="$graphic:text_element"
 - ohos:layout_alignment="left"
 - ohos:text_size="50"
 - ohos:right_margin="20vp"
 - ohos:left_margin="20vp"
 - ohos:text_color="#000000"
 - ohos:top_margin="25vp"
 - ohos:basement="#000099"
 - ohos:hint="請(qǐng)輸入密碼"
 - />
 - <Button
 - ohos:id="$+id:login_btn"
 - ohos:width="match_parent"
 - ohos:height="50vp"
 - ohos:text="登錄"
 - ohos:background_element="$graphic:button_element"
 - ohos:text_size="50"
 - ohos:text_color="#FFFFFF"
 - ohos:top_margin="25vp"
 - ohos:right_margin="20vp"
 - ohos:left_margin="20vp"
 - />
 - </DirectionalLayout>
 
布局效果

我們的目的很明確 我們想拿到2個(gè)輸入框的內(nèi)容然后調(diào)用網(wǎng)絡(luò)接口來(lái)實(shí)現(xiàn)登錄的操作 業(yè)務(wù)非常簡(jiǎn)單
但是今天要用 MVP+ Rxjava+Retrofit+okhttp 來(lái)實(shí)現(xiàn)
網(wǎng)絡(luò)核心部分
- RetrofitClient 類(lèi)封裝
 
- package com.example.hmsrxjava_demo.net;
 - import java.io.IOException;
 - import io.reactivex.rxjava3.annotations.NonNull;
 - import ohos.agp.render.render3d.BuildConfig;
 - import okhttp3.Interceptor;
 - import okhttp3.OkHttpClient;
 - import okhttp3.Request;
 - import okhttp3.Response;
 - import okhttp3.logging.HttpLoggingInterceptor;
 - import retrofit2.Retrofit;
 - import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
 - import retrofit2.converter.gson.GsonConverterFactory;
 - /**
 - * description:
 - */
 - public class RetrofitClient {
 - private static volatile RetrofitClient instance;
 - private APIService apiService;
 - private String baseUrl = "https://www.wanandroid.com";
 - private Retrofit retrofit;
 - private OkHttpClient okHttpClient;
 - private RetrofitClient() {
 - }
 - public static RetrofitClient getInstance() {
 - if (instance == null) {
 - synchronized (RetrofitClient.class) {
 - if (instance == null) {
 - instance = new RetrofitClient();
 - }
 - }
 - }
 - return instance;
 - }
 - /**
 - * 設(shè)置Header
 - *
 - * @return
 - */
 - private Interceptor getHeaderInterceptor() {
 - return new Interceptor() {
 - @Override
 - public Response intercept(@NonNull Chain chain) throws IOException {
 - Request original = chain.request();
 - Request.Builder requestBuilder = original.newBuilder();
 - //添加Token 如果需要添加請(qǐng)求頭可以統(tǒng)一在這里添加
 - // Request.Builder requestBuilder = original.newBuilder().header("token", "");
 - Request request = requestBuilder.build();
 - return chain.proceed(request);
 - }
 - };
 - }
 - /**
 - * 設(shè)置攔截器 打印日志
 - *
 - * @return
 - */
 - private Interceptor getInterceptor() {
 - HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
 - //顯示日志
 - interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
 - return interceptor;
 - }
 - public OkHttpClient getOkHttpClient() {
 - if (okHttpClient == null) {
 - //如果為DEBUG 就打印日志
 - if (BuildConfig.DEBUG) {
 - okHttpClient = new OkHttpClient().newBuilder()
 - //設(shè)置Header
 - .addInterceptor(getHeaderInterceptor())
 - //設(shè)置攔截器
 - .addInterceptor(getInterceptor())
 - .build();
 - } else {
 - okHttpClient = new OkHttpClient().newBuilder()
 - //設(shè)置Header
 - .addInterceptor(getHeaderInterceptor())
 - .build();
 - }
 - }
 - return okHttpClient;
 - }
 - public APIService getApi() {
 - //初始化一個(gè)client,不然retrofit會(huì)自己默認(rèn)添加一個(gè)
 - if (retrofit == null) {
 - retrofit = new Retrofit.Builder()
 - //設(shè)置網(wǎng)絡(luò)請(qǐng)求的Url地址
 - .baseUrl(baseUrl)
 - //設(shè)置數(shù)據(jù)解析器
 - .addConverterFactory(GsonConverterFactory.create())
 - //設(shè)置網(wǎng)絡(luò)請(qǐng)求適配器,使其支持RxJava與RxAndroid
 - .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
 - .client(getOkHttpClient())
 - .build();
 - }
 - //創(chuàng)建—— 網(wǎng)絡(luò)請(qǐng)求接口—— 實(shí)例
 - if (apiService==null){
 - apiService = retrofit.create(APIService.class);
 - }
 - return apiService;
 - }
 - }
 
我們寫(xiě)了一個(gè)單例來(lái)獲取 RetrofitClient 實(shí)力并且設(shè)置的了請(qǐng)求頭 handler 和設(shè)置OKHTTP 日志攔截器
然后定義了 getApi 方法來(lái)獲取 APIService 的實(shí)例
- RxScheduler
 
RXjava 線(xiàn)程調(diào)度
- package com.example.hmsrxjava_demo.net;
 - import com.example.hmsrxjava_demo.HarmonySchedulers;
 - import org.reactivestreams.Publisher;
 - import io.reactivex.rxjava3.core.Flowable;
 - import io.reactivex.rxjava3.core.FlowableTransformer;
 - import io.reactivex.rxjava3.core.Observable;
 - import io.reactivex.rxjava3.core.ObservableSource;
 - import io.reactivex.rxjava3.core.ObservableTransformer;
 - import io.reactivex.rxjava3.schedulers.Schedulers;
 - /**
 - * description:RXjava 線(xiàn)程調(diào)度
 - */
 - public class RxScheduler {
 - /**
 - * 統(tǒng)一線(xiàn)程處理
 - *
 - * @param <T> 指定的泛型類(lèi)型
 - * @return FlowableTransformer
 - */
 - public static <T> FlowableTransformer< T, T> Flo_io_main() {
 - return new FlowableTransformer<T, T>() {
 - @Override
 - public Publisher<T> apply(Flowable<T> upstream) {
 - return upstream.subscribeOn(Schedulers.io())
 - .observeOn(HarmonySchedulers.mainThread());
 - }
 - };
 - }
 - /* *
 - * 統(tǒng)一線(xiàn)程處理
 - *
 - * @param <T> 指定的泛型類(lèi)型
 - * @return ObservableTransformer*/
 - public static <T> ObservableTransformer<T, T> Obs_io_main() {
 - return new ObservableTransformer<T, T>() {
 - @Override
 - public ObservableSource<T> apply( Observable<T> upstream) {
 - return upstream.subscribeOn(Schedulers.io())
 - .observeOn(HarmonySchedulers.mainThread());
 - }
 - };
 - }
 - }
 
這里代碼就參考了 安卓里面 部分沒(méi)有的 HarmonySchedulers.mainThread() 參考了安卓里面的自己實(shí)現(xiàn)了一下
- APIService
 
處理網(wǎng)絡(luò)請(qǐng)求的接口 類(lèi) 所有網(wǎng)絡(luò)請(qǐng)求的都寫(xiě)在 APIService 寫(xiě)法和安卓的 Retrofitle類(lèi)似
- package com.example.hmsrxjava_demo.net;
 - import com.example.hmsrxjava_demo.bean.BaseObjectBean;
 - import com.example.hmsrxjava_demo.bean.LoginBean;
 - import io.reactivex.rxjava3.core.Observable;
 - import retrofit2.http.Field;
 - import retrofit2.http.FormUrlEncoded;
 - import retrofit2.http.POST;
 - /**
 - * Description:
 - */
 - public interface APIService {
 - /**
 - * 登陸
 - *
 - * @param username 賬號(hào)
 - * @param password 密碼
 - * @return
 - */
 - @FormUrlEncoded
 - @POST("user/login")
 - Observable<BaseObjectBean<LoginBean>> login(@Field("username") String username,
 - @Field("password") String password);
 - }
 
base類(lèi)
- BaseAbility
 
- package com.example.hmsrxjava_demo.base;
 - import ohos.aafwk.ability.Ability;
 - import ohos.aafwk.content.Intent;
 - public abstract class BaseAbility extends Ability {
 - @Override
 - protected void onStart(Intent intent) {
 - super.onStart(intent);
 - super.setUIContent(getLayoutId());
 - initView();
 - }
 - @Override
 - protected void onStop() {
 - super.onStop();
 - }
 - /**
 - * 設(shè)置布局
 - *
 - * @return
 - */
 - public abstract int getLayoutId();
 - /**
 - * 初始化視圖
 - */
 - public abstract void initView();
 - }
 
- BaseMvpAbility
 
- package com.example.hmsrxjava_demo.base;
 - import ohos.aafwk.content.Intent;
 - public abstract class BaseMvpAbility <T extends BasePresenter>extends BaseAbility implements BaseView {
 - protected T mPresenter;
 - @Override
 - protected void onStart(Intent intent) {
 - super.onStart(intent);
 - }
 - @Override
 - protected void onStop() {
 - if (mPresenter != null) {
 - mPresenter.detachView();
 - }
 - super.onStop();
 - }
 - }
 
- BasePresenter
 
- package com.example.hmsrxjava_demo.base;
 - /**
 - * Description:
 - */
 - public class BasePresenter<V extends BaseView> {
 - protected V mView;
 - /**
 - * 綁定view,一般在初始化中調(diào)用該方法
 - *
 - * @param view view
 - */
 - public void attachView(V view) {
 - this.mView = view;
 - }
 - /**
 - * 解除綁定view,一般在onDestroy中調(diào)用
 - */
 - public void detachView() {
 - this.mView = null;
 - }
 - /**
 - * View是否綁定
 - *
 - * @return
 - */
 - public boolean isViewAttached() {
 - return mView != null;
 - }
 - }
 
- 
    
BaseView
 
- package com.example.hmsrxjava_demo.base;
 - /**
 - * Description:
 - */
 - public interface BaseView {
 - /**
 - * 顯示加載中
 - */
 - void showLoading();
 - /**
 - * 隱藏加載
 - */
 - void hideLoading();
 - /**
 - * 數(shù)據(jù)獲取失敗
 - * @param errMessage
 - */
 - void onError(String errMessage);
 - }
 
- Model 層
 
- package com.example.hmsrxjava_demo.contract;
 - import com.example.hmsrxjava_demo.base.BaseView;
 - import com.example.hmsrxjava_demo.bean.BaseObjectBean;
 - import com.example.hmsrxjava_demo.bean.LoginBean;
 - import io.reactivex.rxjava3.core.Observable;
 - /**
 - * Description:
 - */
 - public interface MainContract {
 - interface Model {
 - Observable<BaseObjectBean<LoginBean>> login(String username, String password);
 - }
 - interface View extends BaseView {
 - @Override
 - void showLoading();
 - @Override
 - void hideLoading();
 - @Override
 - void onError(String errMessage);
 - void onSuccess(BaseObjectBean<LoginBean> bean);
 - }
 - interface Presenter {
 - /**
 - * 登陸
 - *
 - * @param username
 - * @param password
 - */
 - void login(String username, String password);
 - }
 - }
 
- ##model 實(shí)現(xiàn)層
 
- package com.example.hmsrxjava_demo.model;
 - import com.example.hmsrxjava_demo.bean.BaseObjectBean;
 - import com.example.hmsrxjava_demo.bean.LoginBean;
 - import com.example.hmsrxjava_demo.contract.MainContract;
 - import com.example.hmsrxjava_demo.net.RetrofitClient;
 - import io.reactivex.rxjava3.core.Observable;
 - /**
 - * Description:
 - */
 - public class MainModel implements MainContract.Model {
 - private static final String TAG = "MainModel";
 - @Override
 - public Observable<BaseObjectBean<LoginBean>> login(String username, String password) {
 - System.out.println("MainModel login 被調(diào)用");
 - return RetrofitClient.getInstance().getApi().login(username,password);
 - }
 - }
 
- 
    
Presenter層
 
- package com.example.hmsrxjava_demo.presenter;
 - import com.example.hmsrxjava_demo.base.BasePresenter;
 - import com.example.hmsrxjava_demo.bean.BaseObjectBean;
 - import com.example.hmsrxjava_demo.bean.LoginBean;
 - import com.example.hmsrxjava_demo.contract.MainContract;
 - import com.example.hmsrxjava_demo.model.MainModel;
 - import com.example.hmsrxjava_demo.net.RxScheduler;
 - import io.reactivex.rxjava3.annotations.NonNull;
 - import io.reactivex.rxjava3.core.Observer;
 - import io.reactivex.rxjava3.disposables.Disposable;
 - /**
 - * Description:
 - */
 - public class MainPresenter extends BasePresenter<MainContract.View> implements MainContract.Presenter {
 - private MainContract.Model model;
 - public MainPresenter() {
 - model = new MainModel();
 - }
 - @Override
 - public void login(String username, String password) {
 - //View是否綁定 如果沒(méi)有綁定,就不執(zhí)行網(wǎng)絡(luò)請(qǐng)求
 - if (!isViewAttached()) {
 - return;
 - }
 - model.login(username, password)
 - .compose(RxScheduler.Obs_io_main())
 - .subscribe(new Observer<BaseObjectBean<LoginBean>>() {
 - @Override
 - public void onSubscribe(@NonNull Disposable d) {
 - mView.showLoading();
 - }
 - @Override
 - public void onNext(@NonNull BaseObjectBean<LoginBean> loginBeanBaseObjectBean) {
 - mView.onSuccess(loginBeanBaseObjectBean);
 - System.out.println("onNext ----- >");
 - }
 - @Override
 - public void onError(@NonNull Throwable e) {
 - mView.onError(e.getMessage());
 - mView.hideLoading();
 - }
 - @Override
 - public void onComplete() {
 - mView.hideLoading();
 - }
 - });
 - }
 - }
 
- 
    
MainAbility 中 具體調(diào)用
 
- package com.example.hmsrxjava_demo;
 - import com.example.hmsrxjava_demo.base.BaseMvpAbility;
 - import com.example.hmsrxjava_demo.bean.BaseObjectBean;
 - import com.example.hmsrxjava_demo.bean.LoginBean;
 - import com.example.hmsrxjava_demo.contract.MainContract;
 - import com.example.hmsrxjava_demo.presenter.MainPresenter;
 - import ohos.agp.components.Button;
 - import ohos.agp.components.Component;
 - import ohos.agp.components.TextField;
 - import ohos.agp.window.dialog.ToastDialog;
 - public class MainAbility extends BaseMvpAbility<MainPresenter>implements MainContract.View {
 - private TextField textUsername, textpasswrod;
 - private String username, password;
 - private Button loginBtn;
 - private MainPresenter presenter;
 - @Override
 - public int getLayoutId() {
 - return ResourceTable.Layout_ability_main;
 - }
 - @Override
 - public void initView() {
 - textUsername= (TextField) findComponentById(ResourceTable.Id_text_username);
 - textpasswrod= (TextField) findComponentById(ResourceTable.Id_text_password);
 - presenter=new MainPresenter();
 - presenter.attachView(this);
 - loginBtn= (Button) findComponentById(ResourceTable.Id_login_btn);
 - if(loginBtn!=null){
 - loginBtn.setClickedListener(new Component.ClickedListener() {
 - @Override
 - public void onClick(Component component) {
 - System.out.println("點(diǎn)擊登錄按鈕");
 - username=textUsername.getText();
 - password=textpasswrod.getText();
 - if(username!=null&&password!=null){
 - presenter.login(username,password);
 - // login(username,password);
 - }else {
 - new ToastDialog(MainAbility.this).setText("賬號(hào)密碼不輸不能為空").show(); }
 - }
 - });
 - }
 - }
 - @Override
 - public void onSuccess(BaseObjectBean<LoginBean> bean) {
 - System.out.println(bean.getErrorCode()+bean.getErrorMsg());
 - new ToastDialog(MainAbility.this).setText(bean.getErrorCode()+bean.getErrorMsg()).show();
 - }
 - @Override
 - public void showLoading() {
 - }
 - @Override
 - public void hideLoading() {
 - }
 - @Override
 - public void onError(String errMessage) {
 - }
 - }
 
到此 鴻蒙 MVP+ Rxjava+Retrofit+okhttp 實(shí)現(xiàn)教程 使用起來(lái)和安卓的用法非常像 我這里很多代碼是復(fù)制過(guò)來(lái) 同學(xué)們可以下載完整的代碼來(lái)嘗試。
最后總結(jié):
鴻蒙中MVP+ Rxjava+Retrofit+okhttp 和安卓里面基本如出一轍 只是很少地方有些詫異,同學(xué)們?nèi)绻皇呛苁煜? Rxjava+Retrofit+okhttp 請(qǐng)先去看看官方教程 還有mvp模式的不熟悉的請(qǐng)切翻閱我之前的文章 。
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
















 
 
 







 
 
 
 