项目作者: leifu1107

项目描述 :
:pig::pig::pig: 本项目采用 Kotlin 语言编写,结合 MVP+RxJava2+Retrofit2等的架构设计,封装比较简单,代码量少 1.Rxjava2采用了背压和非背压, 2.实体类采用了泛型和继承两种 3.比大部分作者的框架封装和使用都简单高效
高级语言: Kotlin
项目地址: git://github.com/leifu1107/MvpKotlin.git


MvpKotlin

:pig: kotlin mvp框架的封装, 1.Rxjava2采用了背压和非背压, 2.实体类采用了泛型和继承两种 3.比大部分作者的框架封装和使用都简单高效

本项目采用 Kotlin 语言编写,结合 MVP+RxJava2+Retrofit2等的架构设计,封装比较简单,代码量少



  1. interface IBaseView {//可根据实际情况增加一些方法
  2. /**
  3. * 加载中
  4. */
  5. fun showLoading()
  6. /**
  7. * 取消加载中
  8. */
  9. fun dismissLoading()
  10. /**
  11. * 显示错误提示
  12. */
  13. fun showErrorMsg(msg: String)
  14. }

  1. interface IBasePresenter<in V : IBaseView> {
  2. fun attachView(view: V)
  3. fun detachView()
  4. }

  1. open class BaseRxPresenter<V : IBaseView> : IBasePresenter<V> {
  2. var mView: V? = null
  3. private set
  4. private var compositeDisposable: CompositeDisposable? = null
  5. fun addSubscription(disposable: Disposable) {
  6. if (compositeDisposable == null) {
  7. compositeDisposable = CompositeDisposable()
  8. }
  9. compositeDisposable!!.add(disposable)
  10. }
  11. override fun attachView(view: V) {
  12. this.mView = view
  13. }
  14. override fun detachView() {
  15. mView = null
  16. if (!compositeDisposable!!.isDisposed) {
  17. compositeDisposable!!.clear()
  18. }
  19. }
  20. }

  1. /**
  2. *创建人:雷富
  3. *创建时间:2019/6/5 16:16
  4. *描述:
  5. */
  6. abstract class BaseMvpActivity<in V : IBaseView, P : IBasePresenter<V>> : BaseActivity(), IBaseView {
  7. var mPresenter: P? = null
  8. override fun initView(savedInstanceState: Bundle?) {
  9. super.initView(savedInstanceState)
  10. mPresenter = createPresenter()
  11. if (mPresenter != null) {
  12. mPresenter!!.attachView(this as V)
  13. }
  14. }
  15. /**
  16. * 释放一些资源
  17. */
  18. override fun onDestroy() {
  19. super.onDestroy()
  20. mPresenter?.detachView()
  21. }
  22. /**
  23. * 加载中
  24. */
  25. override fun showLoading() {
  26. LoadingUtil.showLoading(mActivity, "加载中...")
  27. }
  28. /**
  29. * 取消加载
  30. */
  31. override fun dismissLoading() {
  32. LoadingUtil.dismissLoading()
  33. }
  34. /**
  35. * 显示错误提示
  36. */
  37. override fun showErrorMsg(msg: String) {
  38. Toast.makeText(mContext, msg, Toast.LENGTH_LONG).show()
  39. }
  40. /**
  41. * 请求网络数据
  42. */
  43. abstract fun startNetwork()
  44. /**
  45. * 创建Presenter
  46. */
  47. abstract fun createPresenter(): P
  48. }

  1. /**
  2. *创建人:雷富
  3. *创建时间:2019/6/5 17:24
  4. *描述:
  5. */
  6. object RetrofitManager {
  7. val apiService: ApiService by lazy {
  8. getRetrofit().create(ApiService::class.java)
  9. }
  10. private fun getRetrofit(): Retrofit {
  11. // 获取retrofit的实例
  12. return Retrofit.Builder()
  13. .baseUrl(UrlConstant.BASE_URL) //自己配置
  14. .client(getOkHttpClient())
  15. .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
  16. .addConverterFactory(GsonConverterFactory.create())
  17. .build()
  18. }
  19. private fun getOkHttpClient(): OkHttpClient {
  20. //添加一个log拦截器,打印所有的log
  21. val httpLoggingInterceptor =
  22. HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { message: String? -> Log.e("okhttp", message) })
  23. //可以设置请求过滤的水平,body,basic,headers
  24. httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
  25. //设置 请求的缓存的大小跟位置
  26. val cacheFile = File(MyApp.context.cacheDir, "cache")
  27. val cache = Cache(cacheFile, 1024 * 1024 * 50) //50Mb 缓存的大小
  28. return OkHttpClient.Builder()
  29. // .addInterceptor(addQueryParameterInterceptor()) //参数添加
  30. // .addInterceptor(addHeaderInterceptor()) // token过滤
  31. .addInterceptor(httpLoggingInterceptor) //日志,所有的请求响应度看到
  32. // .addNetworkInterceptor(addCacheInterceptor())// 添加缓存
  33. // .addInterceptor(addCacheInterceptor())// 添加缓存
  34. .cache(cache) //添加缓存
  35. .connectTimeout(60L, TimeUnit.SECONDS)
  36. .readTimeout(60L, TimeUnit.SECONDS)
  37. .writeTimeout(60L, TimeUnit.SECONDS)
  38. .build()
  39. }
  40. /**
  41. * 设置公共参数
  42. */
  43. private fun addQueryParameterInterceptor(): Interceptor {
  44. return Interceptor { chain ->
  45. val originalRequest = chain.request()
  46. val request: Request
  47. val modifiedUrl = originalRequest.url().newBuilder()
  48. // Provide your custom parameter here
  49. .addQueryParameter("udid", "d2807c895f0348a180148c9dfa6f2feeac0781b5")
  50. .addQueryParameter("deviceModel", "")
  51. .build()
  52. request = originalRequest.newBuilder().url(modifiedUrl).build()
  53. chain.proceed(request)
  54. }
  55. }
  56. /**
  57. * 设置头
  58. */
  59. private fun addHeaderInterceptor(): Interceptor {
  60. return Interceptor { chain ->
  61. val originalRequest = chain.request()
  62. val requestBuilder = originalRequest.newBuilder()
  63. // Provide your custom header here
  64. // .header("token", token)
  65. .method(originalRequest.method(), originalRequest.body())
  66. val request = requestBuilder.build()
  67. chain.proceed(request)
  68. }
  69. }
  70. /**
  71. * 设置缓存
  72. */
  73. private fun addCacheInterceptor(): Interceptor {
  74. return Interceptor { chain ->
  75. var request = chain.request()
  76. if (!NetworkUtil.isConnected()) {
  77. request = request.newBuilder()
  78. .cacheControl(CacheControl.FORCE_CACHE)
  79. .build()
  80. }
  81. val response = chain.proceed(request)
  82. if (NetworkUtil.isConnected()) {
  83. val maxAge = 0
  84. // 有网络时 设置缓存超时时间0个小时 ,意思就是不读取缓存数据,只对get有用,post没有缓冲
  85. response.newBuilder()
  86. .header("Cache-Control", "public, max-age=" + maxAge)
  87. .removeHeader("Retrofit")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
  88. .build()
  89. } else {
  90. // 无网络时,设置超时为4周 只对get有用,post没有缓冲
  91. val maxStale = 60 * 60 * 24 * 28
  92. response.newBuilder()
  93. .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
  94. .removeHeader("nyn")
  95. .build()
  96. }
  97. response
  98. }
  99. }
  100. }

  1. /**
  2. * 创建人:雷富
  3. * 创建时间:2018/7/30 17:38
  4. * 描述: 2016/8/3.
  5. * 统一线程处理
  6. *虽然在Rxjava2中,Flowable是在Observable的基础上优化后的产物,Observable能解决的问题Flowable也都能解决,但是并不代表Flowable可以完全取代Observable,在使用的过程中,并不能抛弃Observable而只用Flowable。
  7. *由于基于Flowable发射的数据流,以及对数据加工处理的各操作符都添加了背压支持,附加了额外的逻辑,其运行效率要比Observable慢得多。
  8. *只有在需要处理背压问题时,才需要使用Flowable。
  9. */
  10. object RxManage {
  11. /**
  12. * compose简化线程切换
  13. * @param <T>
  14. * @return
  15. </T> */
  16. fun <T> rxSchedulerObservableHelper(): ObservableTransformer<T, T> {
  17. return ObservableTransformer { observable ->
  18. observable.subscribeOn(Schedulers.io())
  19. .observeOn(AndroidSchedulers.mainThread())
  20. }
  21. }
  22. /**
  23. * compose简化线程切换
  24. * @param <T>
  25. * @return
  26. </T> */
  27. fun <T> rxSchedulerFlowableHelper(): FlowableTransformer<T, T> {
  28. return FlowableTransformer { observable ->
  29. observable.subscribeOn(Schedulers.io())
  30. .observeOn(AndroidSchedulers.mainThread())
  31. }
  32. }
  33. /**
  34. *compose判断结果,统一返回结果处理,支持背压
  35. * @param <T>
  36. * @return
  37. </T> */
  38. fun <T> handleObservableResult(): ObservableTransformer<T, T> {
  39. return ObservableTransformer { observable ->
  40. observable.flatMap(Function<T, Observable<T>> { bean ->
  41. val baseBean = bean as BaseBean
  42. if (baseBean.code == 200) {//{"code":200,"msg":"成功!","data":{"appId":"com.chat.peakchao","appkey":"00d91e8e0cca2b76f515926a36db68f5"}}
  43. createObservable(bean)
  44. } else {
  45. Observable.error(ApiException(baseBean.msg))
  46. }
  47. })
  48. }
  49. }
  50. /**
  51. *compose判断结果,统一返回结果处理,支持背压
  52. * @param <T>
  53. * @return
  54. </T> */
  55. fun <T> handleFlowableResult(): FlowableTransformer<T, T> {
  56. return FlowableTransformer { flowable ->
  57. flowable.flatMap(Function<T, Flowable<T>> { bean ->
  58. val baseBean = bean as BaseBean
  59. if (baseBean.code == 200) {
  60. createFlowable(bean)
  61. } else {
  62. Flowable.error(ApiException(baseBean.msg))
  63. }
  64. })
  65. }
  66. }
  67. /**
  68. *不通过继承,通过泛型实现实体类
  69. * @param <T>
  70. * @return
  71. </T> */
  72. fun <T> handleFlowableResult2(): FlowableTransformer<BaseResponseBean<T>, T> {
  73. return FlowableTransformer { flowable ->
  74. flowable.flatMap { bean ->
  75. if (bean.code == 200) {
  76. createFlowable(bean.data)
  77. } else {
  78. Flowable.error(ApiException(bean.msg))
  79. }
  80. }
  81. }
  82. }
  83. /**
  84. * 生成Observable,不支持背压
  85. * @param <T>
  86. * @return
  87. </T> */
  88. private fun <T> createObservable(t: T): Observable<T> {
  89. return Observable.create { emitter ->
  90. try {
  91. emitter.onNext(t)
  92. emitter.onComplete()
  93. } catch (e: Exception) {
  94. emitter.onError(e)
  95. }
  96. }
  97. }
  98. /**
  99. * 生成Flowable,支持背压
  100. * @param <T>
  101. * @return
  102. </T> */
  103. private fun <T> createFlowable(t: T): Flowable<T> {
  104. return Flowable.create({ emitter ->
  105. try {
  106. emitter.onNext(t)
  107. emitter.onComplete()
  108. } catch (e: Exception) {
  109. emitter.onError(e)
  110. }
  111. }, BackpressureStrategy.BUFFER)
  112. }
  113. }

  1. package com.leifu.mvpkotlin.net.except
  2. import android.util.Log
  3. import com.google.gson.JsonParseException
  4. import com.leifu.mvpkotlin.base.IBaseView
  5. import org.json.JSONException
  6. import retrofit2.HttpException
  7. import java.net.ConnectException
  8. import java.net.SocketTimeoutException
  9. import java.net.UnknownHostException
  10. import java.text.ParseException
  11. /**
  12. * desc: 异常处理类
  13. */
  14. class ExceptionHandle {
  15. companion object {
  16. var errorMsg = "请求失败,请稍后重试"
  17. fun handleException(e: Throwable, mView: IBaseView): String {
  18. e.printStackTrace()
  19. if (e is ApiException) {
  20. errorMsg = e.message.toString()
  21. } else if (e is HttpException) {
  22. if (e.code() == 403) {//可以处理一些退出登录逻辑,可以自己修改
  23. mView.showErrorMsg("请重新登录")
  24. }
  25. } else if (e is SocketTimeoutException) {//网络超时
  26. errorMsg = "网络连接异常"
  27. } else if (e is ConnectException) { //均视为网络错误
  28. errorMsg = "网络连接异常"
  29. } else if (e is JsonParseException || e is JSONException || e is ParseException) { //均视为解析错误
  30. Log.e("TAG", "数据解析异常: " + e.message)
  31. errorMsg = "数据解析异常"
  32. } else if (e is UnknownHostException) {
  33. errorMsg = "网络连接异常"
  34. } else if (e is IllegalArgumentException) {
  35. errorMsg = "参数错误"
  36. } else {//未知错误
  37. Log.e("TAG", "未知错误Debug调试: " + e.message)
  38. errorMsg = "未知错误,可能抛锚了吧~"
  39. }
  40. Log.e("TAG", "错误调试: " + e.message)
  41. // Toast.makeText(MyApp.context, errorMsg, Toast.LENGTH_LONG).show()
  42. mView.showErrorMsg(errorMsg)
  43. return errorMsg
  44. }
  45. }
  46. }
  1. package com.leifu.mvpkotlin.presenter
  2. import com.leifu.mvpkotlin.base.BaseRxPresenter
  3. import com.leifu.mvpkotlin.bean.ObjectBean
  4. import com.leifu.mvpkotlin.net.except.ExceptionHandle
  5. import com.leifu.mvpkotlin.net.rx.RetrofitManager
  6. import com.leifu.mvpkotlin.net.rx.RxManage
  7. import com.leifu.mvpkotlin.presenter.contract.ObservableContract
  8. /**
  9. *创建人:雷富
  10. *创建时间:2019/6/6 13:57
  11. *描述:
  12. */
  13. class ObservablePresenter : BaseRxPresenter<ObservableContract.View>(), ObservableContract.Presenter {
  14. override fun getObjectData() {
  15. mView?.showLoading()
  16. addSubscription(
  17. RetrofitManager.apiService.getObservableObjectData()
  18. .compose(RxManage.rxSchedulerObservableHelper())
  19. .compose(RxManage.handleObservableResult<ObjectBean>())
  20. .subscribe({
  21. run { ->
  22. mView?.showObjectData(it)
  23. mView?.dismissLoading()
  24. }
  25. },
  26. { t ->
  27. mView?.dismissLoading()
  28. mView?.let { ExceptionHandle.handleException(t, it) }
  29. })
  30. )
  31. }
  32. }