前言:
各位同學(xué)大家好鲤桥,有段時間沒有給大家更新文章 ,最近還在學(xué)習(xí)鴻蒙開發(fā)的支持,就想著把a(bǔ)ndroid里面部分用到知識搬到鴻蒙里面 因?yàn)榛A(chǔ)語言都是java 語言摩钙,所以就寫了現(xiàn)在這教程 那么廢話不多說我們正式開始
效果圖
準(zhǔn)備工作
1 安裝鴻蒙開發(fā)環(huán)境 大家可以看我之前的文章
需要用到的三方庫
//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'
請?jiān)赽uild.gradle里面添加依賴然后sygn now 同步下載依賴
具體實(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="賬戶"
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個輸入框的內(nèi)容然后調(diào)用網(wǎng)絡(luò)接口來實(shí)現(xiàn)登錄的操作 業(yè)務(wù)非常簡單
但是今天要用 MVP+ Rxjava+Retrofit+okhttp 來實(shí)現(xiàn)
網(wǎng)絡(luò)核心部分
-
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;
}
/**
* 設(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 如果需要添加請求頭可以統(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() {
//初始化一個client,不然retrofit會自己默認(rèn)添加一個
if (retrofit == null) {
retrofit = new Retrofit.Builder()
//設(shè)置網(wǎng)絡(luò)請求的Url地址
.baseUrl(baseUrl)
//設(shè)置數(shù)據(jù)解析器
.addConverterFactory(GsonConverterFactory.create())
//設(shè)置網(wǎng)絡(luò)請求適配器哲嘲,使其支持RxJava與RxAndroid
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.client(getOkHttpClient())
.build();
}
//創(chuàng)建—— 網(wǎng)絡(luò)請求接口—— 實(shí)例
if (apiService==null){
apiService = retrofit.create(APIService.class);
}
return apiService;
}
}
我們寫了一個單例來獲取 RetrofitClient 實(shí)力并且設(shè)置的了請求頭 handler 和設(shè)置OKHTTP 日志攔截器
然后定義了 getApi 方法來獲取 APIService 的實(shí)例
-
RxScheduler
RXjava 線程調(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 線程調(diào)度
*/
public class RxScheduler {
/**
* 統(tǒng)一線程處理
*
* @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());
}
};
}
/* *
* 統(tǒng)一線程處理
*
* @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() 參考了安卓里面的自己實(shí)現(xiàn)了一下
-
APIService
處理網(wǎng)絡(luò)請求的接口 類 所有網(wǎng)絡(luò)請求的都寫在 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();
}
/**
* 設(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是否綁定 如果沒有綁定眠副,就不執(zhí)行網(wǎng)絡(luò)請求
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("賬號密碼不輸不能為空").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)教程 使用起來和安卓的用法非常像 我這里很多代碼是復(fù)制過來 同學(xué)們可以下載完整的代碼來嘗試
最后總結(jié):
鴻蒙中MVP+ Rxjava+Retrofit+okhttp 和安卓里面基本如出一轍 只是很少地方有些詫異画切,同學(xué)們?nèi)绻皇呛苁煜? Rxjava+Retrofit+okhttp 請先去看看官方教程 還有mvp模式的不熟悉的請切翻閱我之前的文章 。還有跟多關(guān)于鴻蒙 網(wǎng)絡(luò)編程的實(shí)現(xiàn)方法同學(xué)私下有興趣可以嘗試去實(shí)現(xiàn)我這邊就不展開講了 ,最后希望我的文章能幫助到各位解決問題 囱怕,以后我還會貢獻(xiàn)更多有用的代碼分享給大家霍弹。各位同學(xué)如果覺得文章還不錯 ,麻煩給關(guān)注和star娃弓,小弟在這里謝過啦