kotlin大法:協程它不香嗎(網絡交互篇)

andriod項目中網絡請求使用kotlinRetrofit的最優雅方式,拋棄Callback,拋棄RxJava,接受協程java

源碼傳送門: android-kotlin-retrofit-wrapandroid

網上一大堆都是Retrofit+Rxjava或者使用回調方式,其實使用協程纔是真的簡單好用git


android項目如今基本都是用kotlin開發,而kotlin的優點顯而易見,其中的協程也是一大利器github

網絡交互通常使用okhttp+Retrofit,而在okhttp4.0+已經使用了kotlin做爲維護語言,Retrofit在2.6.0版本也開始支持了掛起(suspend)修飾符,這使得android項目中使用kotlin個Retrofit進行網絡交互尤其方便數據庫

該項目內容爲kotlin協程配合Retrofit實現網絡請求的一個示例json

Step0: android項目中加入kotlin及其協程的支持

  • 項目根目錄build.gradle文件中加入:api

    buildscript {
          ext.kotlin_version = '1.3.50'
          ext.kotlin_coroutines = '1.3.2'
          
      	...
    
          dependencies {
              classpath 'com.android.tools.build:gradle:3.5.0'
              classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
              ...
          }
      }
    複製代碼
  • app目錄下的build.gradle中加入支持並添加依賴:網絡

    apply plugin: 'kotlin-android'
      apply plugin: 'kotlin-android-extensions'
    
      dependencies {
          implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
          implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines"
          implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines"
          
      	implementation 'androidx.core:core-ktx:1.1.0'
          implementation 'androidx.appcompat:appcompat:1.1.0'
      
          implementation 'com.squareup.retrofit2:retrofit:2.6.2'
          implementation "com.squareup.okhttp3:okhttp:4.2.0"
          implementation "com.squareup.okhttp3:logging-interceptor:4.2.0"
      	
      	...
      }
    複製代碼

Step1: 對Retrofit的簡單封裝 詳見RetrofitWrap.kt

/**
 * 是否開啓打印日誌,默認關閉
 */
fun init(baseUrl: String, debugEnable: Boolean = false) {
    instance.retrofit = Retrofit.Builder().apply {
        baseUrl(baseUrl)
        client(okhttpClient(debugEnable))
        addConverterFactory(StringConverterFactory.create())
    }.build()
}

/**
 * 獲取API服務
 */
fun <T> service(service: Class<T>): T {
    if (instance.retrofit != null) {
        return instance.retrofit!!.create(service)
    } else {
        throw IllegalStateException("請先調用RetrofitWrap.init()方法進行初始化")
    }
}
複製代碼

就兩個對外方法:架構

  • init:初始化,配置baseUrl和是否打印日誌,其餘參數能夠基於源碼修改加入
  • service:獲取服務實例,傳入定義api的接口類,而後調用對應方法便可完成數據請求

Step2: 根據業務定義網絡交互方法,例如API.kt

interface API {
    @GET("test.json")
    suspend fun info(): String
}
複製代碼

使用Example,詳見TestActivity.kt

  • 完整示例:app

    class TestActivity : AppCompatActivity(), CoroutineScope by MainScope() {
      
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_main)
      
              RetrofitWrap.init("https://okfood.vip/", false)
      
              btn.setOnClickListener {
                  content.text = "加載中..."
                  launch {
                      val data = withContext(Dispatchers.IO) {
                          RetrofitWrap.service(API::class.java).info()
                      }
                      content.text = if (TextUtils.isEmpty(data)) "error" else data
                  }
              }
          }
      
          override fun onDestroy() {
              super.onDestroy()
              cancel()
          }
      }
    複製代碼
  • 說明

    • 初始化RetrofitWrap.init須要放置在第一次請求網絡以前,能夠是application中
    • 不建議使用GlobalScopelaunch一個協程任務,android中便於生命週期的管理提供了MainScope,在頁面銷燬處調用cancel()避免內存泄露

閒外話

  • 該項目內容僅是一種極簡使用方式的展現,具體項目中,能夠根據項目架構作對應調整,好比加上使用ViewModel以及LiveData等

  • 同理,實現方式也能夠用於數據庫的操做,畢竟網絡和數據庫都是android數據存儲的方式

相關文章
相關標籤/搜索