栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MVP + Retrofit + RxJava 搭建一个基础的Android开发框架

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MVP + Retrofit + RxJava 搭建一个基础的Android开发框架

MVP + Retrofit + RxJava 搭建一个基础的Android开发框架 前言

本项目旨在搭建一个简易的Android开发结构,避免新手开发时出现代码混乱的问题,如有不同意见欢迎评论区提出包含一个基础的框架搭建,讲解都在注释里 一、主要功能

    提供基础的MVP结构,并集成相关的初始化操作提供基础的网络管理框架,更方便的进行网络请求和管理提供日志打印管理,可以在logcat自动打印指定级别的http日志,方便调试提供简单的页面示例 SampleActivity
二、部分关键代码 1. 引入相关依赖
// blankj 工具包,包含了相当多的功能,强推
implementation 'com.blankj:utilcodex:1.30.6'

// retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

// rx java
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation "me.jessyan:rxerrorhandler:2.1.1"

// butterKnife 控件绑定
implementation 'com.jakewharton:butterknife:10.2.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
2. 代码结构图

3. MVP 相关代码

MVP 接口定义

public interface IModel {
    void onDestroy();
}

public interface IView {
    
    default void showLoading(){
    }

    
    default void hideLoading() {
    }

    
    default void showMessage(String msg) {
        ToastUtils.showShort(msg);
    }
}

public interface IPresenter {

    
    void addDisposable(Disposable... disposables);

    
    default void initDataReq() {

    }

    void onDestroy();
}

baseModel 实现

import com.blankj.utilcode.util.ToastUtils;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;

import java.lang.reflect.ParameterizedType;
import java.util.Objects;

public abstract class baseModel

implements IModel { protected P mPresenter; Class serviceClass; @SuppressWarnings("unchecked") public baseModel(P mPresenter) { this.mPresenter = mPresenter; try { // 这一段代码,就是反射,通过泛型,获取指定的类 ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass(); if (type == null) { throw new RuntimeException("运行异常,初始化失败: " + getClass().getSimpleName()); } serviceClass = (Class) type.getActualTypeArguments()[1]; } catch (Exception e) { e.printStackTrace(); } } //使用Retrofit获取了指定接口的实例 //通过Service执行某一个请求时,拼接Url并执行网络访问,并将返回结果按指定格式解析并返回 protected S obtainService() { return NetManager.getInstance().bindService(serviceClass);//谁拿到 ,谁指定Service } protected boolean checkCode(CommonResBean bean) { String needDisplay = bean.checkCode(); if (needDisplay == null) { return true; } // 向 presenter 中 增加通知错误信息线程 mPresenter.addDisposable(Observable.just(needDisplay) .observeOn(AndroidSchedulers.mainThread()) .filter(Objects::nonNull) .subscribe(ToastUtils::showShort)); return false; } @Override public void onDestroy() { mPresenter = null; } }

basePresenter 实现

import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;

import java.lang.reflect.ParameterizedType;

//basePresenter 两个泛型,前者为视图的,后者为数据源的
public abstract class basePresenter implements IPresenter {

    protected V mView;//V 泛型变量
    protected M mModel;//M 泛型变量

    // 这是一个集合,用来控制生命周期
    private CompositeDisposable compositeDisposable;

    @SuppressWarnings("unchecked")
    public basePresenter(V mView) {
        this.mView = mView;
        // 保存了上级 View
        try {
            // 一个泛型Model 实例
            ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
            if (type == null) {
                throw new RuntimeException("运行异常,初始化失败: " + getClass().getSimpleName());
            }
            Class classM = (Class) type.getActualTypeArguments()[1];
            this.mModel = (M) classM.getConstructors()[0].newInstance(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
        compositeDisposable = new CompositeDisposable();
    }

    //从子管理传参到这里,再for循环出来数据 给compositeDisposable
    public void addDisposable(Disposable... disposables) {
        if (compositeDisposable == null) {
            return;
        }
        for (Disposable disposable : disposables) {
            compositeDisposable.add(disposable);
        }
    }

    @Override
    public void onDestroy() {
        mView = null;
        if (mModel != null) {
            mModel.onDestroy();//不等于空,就销毁
            mModel = null;
        }
        // 在合适的时机取消未结束的网络请求
        // 取消所有未完成的网络请求
        // 因为视图已经销毁了,如果继续下去,会崩溃
        if (compositeDisposable != null) {
            compositeDisposable.dispose();
            compositeDisposable = null;
        }
    }
}

baseActivity/baseFragment 实现

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import androidx.annotation.CallSuper;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.ButterKnife;


public abstract class baseActivity

extends AppCompatActivity implements IView, InitialPro

{ protected P mPresenter; protected View mContentView; @SuppressLint("InflateParams") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Event后,在后台能接到消息; 要用Manager里面的eventMManager mPresenter = initPresenter();//被 泛型的某一个Presenter来初始化IPresenter 在Activity中 mContentView = LayoutInflater.from(this).inflate(getContentViewId(), null, false); setContentView(mContentView); ButterKnife.bind(this, mContentView); initView(); initData(); } @CallSuper protected void initData() { mPresenter.initDataReq(); } //解绑 @Override protected void onDestroy() { super.onDestroy(); if (mPresenter != null) { mPresenter.onDestroy(); mPresenter = null; } } }

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import butterknife.ButterKnife;




public abstract class baseFragment

extends Fragment implements IView, InitialPro

{ protected P mPresenter; protected View mContentView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mPresenter = initPresenter();//被泛型的某一个Presenter来初始化(引入)IPresenter 在Fragment中 } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { mContentView = inflater.inflate(getContentViewId(), container, false); // base View 主要做的,绑定 Presenter,初始化结构,绑定ButterKnife // ButterKnife 就是做了一个视图绑定,不用再findviewbyid ButterKnife.bind(this, mContentView); initView(); initData(); return mContentView; } @CallSuper protected void initData() { // 可以看到,在View 基类中,视图创建好了之后 // 会告知Presenter可以准备请求网络数据了 // 因为如果过早,视图还没创建,如果网络请求好了,那就会崩溃 // 所以这个时机让Presenter请求网络 哦。明白了。是的。。 mPresenter.initDataReq(); } @Override public void onDestroy() { super.onDestroy(); // 在视图销毁时,释放资源 if (mPresenter != null) { // 告知Presenter释放 mPresenter.onDestroy(); mPresenter = null; } } }

4. Retrofit 部分关键代码
import com.blankj.utilcode.util.GsonUtils;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

import java.util.concurrent.TimeUnit;

public class NetManager {
    private static NetManager netManager;
    Retrofit retrofit;

    private NetManager() {
        // 我们使用的是Retrofit代管网络,这是他的初始化方法
        retrofit = new Retrofit.Builder()
                .client(obtainOKHttpClient())
                // 这是基础url,会跟 Service 中的 拼接
                .baseUrl("https://www.7timer.info")
                .addConverterFactory(GsonConverterFactory.create(GsonUtils.getGson()))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    private OkHttpClient obtainOKHttpClient() {
        return new OkHttpClient.Builder()
                .callTimeout(10, TimeUnit.SECONDS)
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .addInterceptor(new RequestInterceptor(RequestInterceptor.Level.ALL))
                .build();
    }

    public static NetManager getInstance() {
        if (netManager == null) {
            throw new RuntimeException("你还没有初始化 NetManager");
        }
        return netManager;
    }

    // 这两个操作,保证唯一,放到Application中
    // 初始化,单例模式,保证唯一
    public static void init(Context context) {
        netManager = new NetManager();
    }

    // 释放资源
    public static void release() {
        if (netManager != null) {
            netManager.retrofit = null;
            netManager = null;
        }
    }

    public  T bindService(Class targetInterface) {
        return retrofit.create(targetInterface);
    }
}
三、使用示例 1. 声明要访问的网络接口
import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Query;

public interface SampleServices {
    
    @GET("/bin/api.pl")
    Observable getWeather(
            @Query("lon") double lon,
            @Query("lat") double lat,
            @Query("product") String pro,
            @Query("output") String output
    );
}
2. 创建SampleModel调用请求
import cn.lzd.mvp.base.struct.baseModel;
import cn.lzd.mvp.base.struct.IPresenter;
import io.reactivex.Observable;

public class SampleModel extends baseModel {
    public SampleModel(IPresenter mPresenter) {
        super(mPresenter);
    }

    public Observable getWeather() {
        return obtainService().getWeather(
                        113.17,
                        23.09,
                        "astro",
                        "json"
                );
    }
}
3. 创建Presenter管理请求,并分发数据
import cn.lzd.mvp.base.net.RxUtils;
import cn.lzd.mvp.base.struct.basePresenter;

public class SamplePresenter extends basePresenter {
    public SamplePresenter(SampleActivity mView) {
        super(mView);
    }

    void reqWeather() {
        addDisposable(mModel.getWeather()
                .compose(RxUtils.applySchedulers(mView))
                .subscribe(weatherData -> mView.onReceiveWeatherData(weatherData.getDatas())));
    }
}
4. 创建View显示视图
@SuppressLint("NonConstantResourceId")
public class SampleActivity extends baseActivity {
    @BindView(R.id.reqResult)
    TextView tvReqResult;
    @BindView(R.id.loadingBG)
    View loadingBG;
    @BindView(R.id.loadingProgress)
    ProgressBar loadingProgress;
    @BindView(R.id.request)
    View request;

    @Override
    public int getContentViewId() {
        return R.layout.activity_sample;
    }

    @Override
    public void initView() {
        super.initView();
        tvReqResult.setMovementMethod(ScrollingMovementMethod.getInstance());
    }

    @OnClick({R.id.request, R.id.loadingBG})
    public void onClick(View view) {
        // 对不同的控件做点击事件处理
        switch (view.getId()) {
            case R.id.request: {
                tvReqResult.setText("");
                view.setEnabled(false);
                mPresenter.reqWeather();
                break;
            }
            case R.id.loadingBG:{
                ToastUtils.showShort("请等待……");
                break;
            }
        }
    }

    void onReceiveWeatherData(List weatherData) {
        StringBuilder stringBuilder = new StringBuilder();
        for (SampleBeans.DayData dayData : weatherData) {
            stringBuilder.append(GsonUtils.toJson(dayData)).append("nn");
        }
        tvReqResult.setText(stringBuilder);
        request.setEnabled(true);
    }

    @Override
    public void showLoading() {
        loadingBG.setVisibility(View.VISIBLE);
        loadingProgress.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        loadingBG.setVisibility(View.GONE);
        loadingProgress.setVisibility(View.GONE);
    }
}
四、关于Observable数据流向的一个简要图示

五、运行结果示例


相关示例代码下载链接:MVP_DEMO

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号