前言:
各位同學大家好,有段時間沒有給大家更新文章 ,最近還在學習鴻蒙開發的支持,就想著把android里面部分用到知識搬到鴻蒙里面 因為基礎語言都是java 語言,所以就寫了現在這教程 那么廢話不多說我們正式開始
##效果圖

準備工作
1 安裝鴻蒙開發環境 大家可以看我之前的文章
需要用到的三方庫
- //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'
請在build.gradle里面添加依賴然后sygn now 同步下載依賴
具體實現
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="賬戶"
- 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="請輸入賬號"
- />
- <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="請輸入密碼"
- />
- <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個輸入框的內容然后調用網絡接口來實現登錄的操作 業務非常簡單
但是今天要用 MVP+ Rxjava+Retrofit+okhttp 來實現
網絡核心部分
- RetrofitClient 類封裝
- 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;
- }
- /**
- * 設置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 如果需要添加請求頭可以統一在這里添加
- // Request.Builder requestBuilder = original.newBuilder().header("token", "");
- Request request = requestBuilder.build();
- return chain.proceed(request);
- }
- };
- }
- /**
- * 設置攔截器 打印日志
- *
- * @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()
- //設置Header
- .addInterceptor(getHeaderInterceptor())
- //設置攔截器
- .addInterceptor(getInterceptor())
- .build();
- } else {
- okHttpClient = new OkHttpClient().newBuilder()
- //設置Header
- .addInterceptor(getHeaderInterceptor())
- .build();
- }
- }
- return okHttpClient;
- }
- public APIService getApi() {
- //初始化一個client,不然retrofit會自己默認添加一個
- if (retrofit == null) {
- retrofit = new Retrofit.Builder()
- //設置網絡請求的Url地址
- .baseUrl(baseUrl)
- //設置數據解析器
- .addConverterFactory(GsonConverterFactory.create())
- //設置網絡請求適配器,使其支持RxJava與RxAndroid
- .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
- .client(getOkHttpClient())
- .build();
- }
- //創建—— 網絡請求接口—— 實例
- if (apiService==null){
- apiService = retrofit.create(APIService.class);
- }
- return apiService;
- }
- }
我們寫了一個單例來獲取 RetrofitClient 實力并且設置的了請求頭 handler 和設置OKHTTP 日志攔截器
然后定義了 getApi 方法來獲取 APIService 的實例
- RxScheduler
RXjava 線程調度
- 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 線程調度
- */
- public class RxScheduler {
- /**
- * 統一線程處理
- *
- * @param <T> 指定的泛型類型
- * @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());
- }
- };
- }
- /* *
- * 統一線程處理
- *
- * @param <T> 指定的泛型類型
- * @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());
- }
- };
- }
- }
這里代碼就參考了 安卓里面 部分沒有的 HarmonySchedulers.mainThread() 參考了安卓里面的自己實現了一下
- APIService
處理網絡請求的接口 類 所有網絡請求的都寫在 APIService 寫法和安卓的 Retrofitle類似
- 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 賬號
- * @param password 密碼
- * @return
- */
- @FormUrlEncoded
- @POST("user/login")
- Observable<BaseObjectBean<LoginBean>> login(@Field("username") String username,
- @Field("password") String password);
- }
base類
- 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();
- }
- /**
- * 設置布局
- *
- * @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,一般在初始化中調用該方法
- *
- * @param view view
- */
- public void attachView(V view) {
- this.mView = view;
- }
- /**
- * 解除綁定view,一般在onDestroy中調用
- */
- 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();
- /**
- * 數據獲取失敗
- * @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 實現層
- 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 被調用");
- 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是否綁定 如果沒有綁定,就不執行網絡請求
- 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 中 具體調用
- 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("點擊登錄按鈕");
- username=textUsername.getText();
- password=textpasswrod.getText();
- if(username!=null&&password!=null){
- presenter.login(username,password);
- // login(username,password);
- }else {
- new ToastDialog(MainAbility.this).setText("賬號密碼不輸不能為空").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 實現教程 使用起來和安卓的用法非常像 我這里很多代碼是復制過來 同學們可以下載完整的代碼來嘗試。
最后總結:
鴻蒙中MVP+ Rxjava+Retrofit+okhttp 和安卓里面基本如出一轍 只是很少地方有些詫異,同學們如果不是很熟悉 Rxjava+Retrofit+okhttp 請先去看看官方教程 還有mvp模式的不熟悉的請切翻閱我之前的文章 。
原文鏈接:https://harmonyos.51cto.com