前言:
各位同学大家好,有段时间没有给大家更新文章 ,最近还在学习鸿蒙开发的支持,就想着把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