andriod項目中網絡請求使用kotlin
和Retrofit
的最優雅方式,拋棄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
項目根目錄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"
...
}
複製代碼
/**
* 是否開啓打印日誌,默認關閉
*/
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的接口類,而後調用對應方法便可完成數據請求interface API {
@GET("test.json")
suspend fun info(): String
}
複製代碼
完整示例: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中GlobalScope
去launch
一個協程任務,android中便於生命週期的管理提供了MainScope
,在頁面銷燬處調用cancel()
避免內存泄露該項目內容僅是一種極簡使用方式的展現,具體項目中,能夠根據項目架構作對應調整,好比加上使用ViewModel以及LiveData等
同理,實現方式也能夠用於數據庫的操做,畢竟網絡和數據庫都是android數據存儲的方式