kotlin+协程+Retrofit+MVP搭建快速开发框架

文章目录

简介

开始之前让笔者在此对项目中用到的一些基本概念做一些基本的介绍方便大家更好的理解此博客

  • Kotlin是由JetBrains创建的基于JVM的静态编程语言。包含了很多函数式的编程思想的面向对象的的编程语言。kotlin仿佛是为了解决java中存着的一些天生的缺陷而量身定做一般。精简的语法,null-safety,相对应java8更进一步的lambda表达式支持。使用block完美的代替了接口回调等等。使得开发者可以编写尽量少的样板代码。谷歌爸爸早就在2017年就已经宣布kotlin为安卓的官方开发语言了。身为安卓开发从业人员,学习kotlin很有必要。

  • 协程也叫微线程,是一种新的多任务并发的操作手段。 协程是创造出来解决异步问题,线程的调度是操作系统层面完成是抢占式的;协程是非抢占式的,是协作运行的,是由应用层完成调度,协程在挂起的时候不会堵塞线程,只会将当前运行的状态存在内存中,当协程执行完成后,会恢复之前保存的状态继续运行。协程的内部是通过状态机实现的。
    协程具有以下特性

    • 可控制:协程能做到可被控制的发起子任务(协程的启动和停止都由代码控制,不像 java)
    • 轻量级:协程非常小,占用资源比线程还少
    • 语法糖:使多任务或多线程切换不再使用回调语法
      本框架中使用协程封装来实现异步的网络请求。
  • Retrofit是Square 公司开发的一款正对Android 网络请求的框架。底层基于OkHttp 实现。Retrofit 负责请求的数据和请求的结果,使用接口的方式呈现,OkHttp 负责请求的过程。异步的实现采用协程实现

  • MVP目前主要的安卓开发框架有mvc,mvp,mvvm,mvc因为代码的冗余度较高,逐渐被淘汰了。mvvm,笔者之前也自己搭建过mvvm的框架,发现在databing的时候有时候出现的资源文件错误无法准确定位问题。所以暂时项目用的还是mvp(个人感觉项目较小没有使用mvvm的必要)。

项目的架构

项目中新建了一个底层的baseUI的library。上层的所有的module均依赖于这个baseUI lib。
baseui

Mvp的具体实现

主要包括BaseMvpActivity,BaseMvpPresenter,BaseMvpView

  • BaseMvpActivity

在这里插入图片描述

  • BaseMvpPresenter
    在这里插入图片描述

  • BaseMvpView BaseMvpView中主要定义了一些view中常用的方法
    BaseMvpVIew

协程的使用与封装

  • 协程的引入
    • 首先我们需要在baseUI中引入相应的库
      implementation ‘org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1’
      implementation ‘org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1’
      如图
      在这里插入图片描述
  • 我们需要在gradle脚本中添加coroutines支持
    kotlin {
    experimental {
    coroutines ‘enable’
    }
    }
    在这里插入图片描述
  • 协程的封装
    我们新增一个KotlinPresenter的类继承自BaseMvpPresenter用于在底层封装网络请求和对请求结果做出相应的处理。
    在KotlinPresenter中我们定义一个CoroutineScope对象。view中所有的协程操作需要presenterScope在实现。
    val presenterScope: CoroutineScope by lazy {
    CoroutineScope(Dispatchers.Main + Job())
    }
    在这里插入图片描述
    网络请求的封装,我们在KotlinPresenter定义了一个launchRequest方法。在这里插入图片描述
    launchRequest方法中有四个函数作为参数。
    tryBlock:返回的是一个由Result包裹的泛型参数。主要用于网络请求的调用。
    successBlock:主要用于请求成功的调用。相当要onSuccess回调。
    catchBlock:主要用于请求失败的调用。相当于onError回调。
    finallyBlock:主要用于请求完成的回调。相当于onComplete回调

这里调用了一个launchOnUI方法。因为retrofit已经做了线程切换,所以我们不需要切换线程了。
在这里插入图片描述
requestTryCatch方法中对协程进行了tryCatch操作。并对结果进行了相应的处理
在这里插入图片描述
callResponse,用于对请求的结果进行处理。
在这里插入图片描述
这里我们还需要注意一个问题,就是当你的页面被销毁,如果你的协程没有被销毁,就会产生一些不可预知的后果,所以我们要在页面销毁时,将协程关闭。
具体的操作是这样的
重写父类的detachView方法在这里插入图片描述
这样就可以了。

Retrofit的使用

retrofit的使用和封装相信大家都很了解了,这里就不多讲了,直接贴出代码来吧

// An highlighted block
interface ApiServices {
    /**
     * 用户登录
     */
    @GET("login?key=00d91e8e0cca2b76f515926a36db68f5")
    fun requestLoginOut( @Query("phone") phone: String,
                         @Query("passwd") passwd: String): Deferred<Result<LoginBean>>

    @GET("createUser?key=00d91e8e0cca2b76f515926a36db68f5")
    fun requestRegister(
        @Query("phone") phone: String,
        @Query("passwd") passwd: String
    ): Deferred<Result<RegisterBean>>

}

ApiHelper初始化okhttp,和Retrofit。

// An highlighted block

object ApiHelper {
    private var api: ApiServices? = null

    fun api(): ApiServices? {
        if (api == null)
            initApi()
        return api
    }

    /**
     * 初始化api
     */
    fun initApi() {
        // Header
        val headerInter = Interceptor { chain ->
            val builder = chain.request()
                .newBuilder()
            chain.proceed(builder.build())
        }

        val mOkHttpClient = OkHttpClient()
            .newBuilder()
            .readTimeout(20, TimeUnit.SECONDS)
            .writeTimeout(20, TimeUnit.SECONDS)
            .connectTimeout(20, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .addInterceptor(headerInter)
            .addInterceptor(LoggingInterceptor())
            .build()
        //网络接口配置
        api = null
        api = Retrofit.Builder()
            .baseUrl("https://www.apiopen.top/")
            .addConverterFactory(ScalarsConverterFactory.create())       //添加字符串的转换器
            .addConverterFactory(GsonConverterFactory.create())          //添加gson的转换器
            .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())   //添加携程的请求适配器            .client(mOkHttpClient)
            .client(mOkHttpClient)
            .build()
            .create(ApiServices::class.java)
    }


}

希望大家注意一下这里的Deferred
在这里插入图片描述
这里的Deferred用于接收一个Coroutine的返回结果。
协程的请求适配器,需要引入“com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2

在这里插入图片描述

网络请求的实现

现在我们可以来使用我们封装的协程来实现网络请求了。
在presenter层中定义了两个请求。案例如下

// An highlighted block

    override fun requestLogin() {
        view?.showWaitDialog()
        launchRequest(
            {
                ApiHelper.api()?.requestLoginOut(phone,password)?.await()
            },
            { loginBean: LoginBean? ->
                view?.requestLoginSuccess(loginBean)
            },
            { errMsg: String? ->
                view?.requestError(errMsg)
            },
            {
                view?.hideWaitDialog()
            })

    }

    override fun requestRegister() {
        view?.showWaitDialog()
        launchRequest(
            { ApiHelper.api()?.requestRegister(phone,password)?.await() },
            { register: RegisterBean? ->
                view?.requestRegisterSuccess(register)
            },
            { errMsg: String? ->
                view?.requestError(errMsg)
            },
            {
                view?.hideWaitDialog()
            }
        )
    }

怎么样,是不是很简洁舒适,没有了rxjava多重的链式api调用。不需要定义回调函数。代码也一目了然。

如果我们需要在view中运用到异步,同样可以使用presenter层中的定义的presenterScope。例如我们需要下载一张照片,然后在显示。

// An highlighted block
    presenterScope.launch {
            try {
                var bitmap = withContext(Dispatchers.IO) {
                    val bitmap = Glide.with(view.getmActivity())
                        .load(path)
                        .asBitmap().skipMemoryCache(false)
                        .diskCacheStrategy(DiskCacheStrategy.ALL)
                        .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
                        .get()
                    bitmap
                }
                withContext(Dispatchers.Main) {
                    GlideUtils.load(
                        view.getmActivity(),
                        ivAvata,
                        bitmap,
                        GlideCircleTransform(view.getmActivity())
                    )
                }
            } catch (e: Throwable) {
                e.printStackTrace()
            }
        }

项目地址

传送门

此项目已经托管到github并且开源。如果想看源码点击传送门查看。如果觉得还可以,不妨给在下一个star。谢谢大家。

总结

本片文章主要是为了用协程代替RxJava实现网络请求的异步。打造Kotlin+协程+retrofit+mvp的开发架构。
协程作为一种轻量级的用户态的线程。还有很多的语法糖和亮点可以供我们使用和借鉴。后期,我还会跟大家一起探讨协程的实现机制和用途。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
好的,我来回答你的问题。 首先,Kotlin 是一种基于 JVM 的静态类型编程语言,它的语法简洁易懂,支持函数式编程和面向对象编程。 协程Kotlin 中的一种轻量级线程,可以实现异步编程和并发执行。Retrofit 是一款网络请求库,它可以帮助我们轻松地实现网络请求和数据解析。MVVM 是一种软件架构模式,可以将应用程序分为三个部分:模型、视图和视图模型。 下面是一个基于 Kotlin + 协程 + Retrofit + MVVM 的网络请求的优雅实现: 1. 定义 API 接口 首先定义 API 接口,使用 Retrofit 注解来描述请求方法和参数。 ```kotlin interface ApiService { @GET("api/news") suspend fun getNews(@Query("category") category: String): NewsResponse } ``` 2. 创建数据模型 根据 API 接口的返回数据,我们可以创建一个数据模型。 ```kotlin data class News(val title: String, val content: String) data class NewsResponse(val code: Int, val message: String, val newsList: List<News>) ``` 3. 创建 ViewModel ViewModel 是连接数据模型和视图的中间层,它处理数据逻辑并提供可观察的数据。 ```kotlin class NewsViewModel : ViewModel() { private val _newsList = MutableLiveData<List<News>>() val newsList: LiveData<List<News>> = _newsList fun loadNews(category: String) { viewModelScope.launch { val response = retrofit.create(ApiService::class.java).getNews(category) if (response.code == 200) { _newsList.value = response.newsList } } } } ``` 4. 创建视图 视图负责展示数据,并与用户交互。 ```kotlin class NewsActivity : AppCompatActivity() { private val viewModel by viewModels<NewsViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_news) viewModel.newsList.observe(this, Observer { newsList -> // 更新视图 }) viewModel.loadNews("tech") } } ``` 通过使用 Kotlin + 协程 + Retrofit + MVVM,我们可以实现优雅地网络请求,代码简洁易懂,逻辑清晰。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值