如果您之前学习 Android MVP ,很可能是从 AndroidMVPSample(https://github.com/WuXiaolong/AndroidMVPSample)开始的,此Sample最初是 Android MVP 示例,后来融合 Retrofit 和 RxJava,分别演示了普通写法(Retrofit)、普通写法(Retrofit+Rxjava)、MVP+Retrofit+Rxjava,跟它一样,我写了 Kotlin 版 Retrofit +RxJava 来练手,还是以天气示例。
依赖
build.gradle
buildscript {
ext.kotlin_version = '1.1.2-4'
ext.retrofit_version = '2.0.2'
ext.rxkotlin_version = '0.60.0'
ext.rxandroid_version = '1.2.1'
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
//编译 Kotlin 源代码和模块.
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}}
app/build.gradle
apply plugin: 'com.android.application'apply plugin: 'kotlin-android'android {
//……}dependencies {
//针对 JDK 7 或 JDK 8
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
//Retrofit
compile "com.squareup.retrofit2:retrofit:$retrofit_version"
compile "com.squareup.okhttp3:logging-interceptor:$logging_interceptor_version"
compile "com.squareup.retrofit2:converter-gson:$retrofit_version"
compile "com.squareup.retrofit2:adapter-rxjava:$retrofit_version"
//RxJava
compile "io.reactivex:rxkotlin:$rxkotlin_version"
compile "io.reactivex:rxandroid:$rxandroid_version"}
网络权限
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
WeatherinfoModel
天气接口:http://www.weather.com.cn/adat/sk/101190201.html当我们使用 Gson 来解析 json 到我们的类中,这些属性的名字必须要与json中的名字一样,哎,我又忘记这点,因此浪费了很多时间排错。
data class WeatherinfoModel constructor(val weatherinfo: WeatherinfoBean) {
data class WeatherinfoBean(
val city: String,
val cityid: String
)}
ApiStores
网络请求 url 都放这里:
interface ApiStores {
companion object {
//baseUrl
val API_SERVER_URL = "http://www.weather.com.cn/"
}
//加载天气
@GET("adat/sk/{cityId}.html")
fun loadData(@Path("cityId") cityId: String): Observable<WeatherinfoModel>}
ApiClient
Retrofit 初始化、配置:
//object声明单例模式
object ApiClient {
fun retrofit(): ApiStores {
val builder = OkHttpClient.Builder()
if (BuildConfig.DEBUG) {
// Log信息拦截器
val loggingInterceptor = HttpLoggingInterceptor()
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
//设置 Debug Log 模式
builder.addInterceptor(loggingInterceptor)
}
val okHttpClient = builder.build()
val retrofit = Retrofit.Builder()
.baseUrl(ApiStores.API_SERVER_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(okHttpClient)
.build()
//ApiStores::class.java取得对象的 Java 类
return retrofit.create(ApiStores::class.java)
}}
ApiCallback
还是做了回调:
abstract class ApiCallback<M> : Subscriber<M>() {
abstract fun onSuccess(model: M)
abstract fun onFailure(msg: String?)
abstract fun onFinish()
override fun onCompleted() {
onFinish()
}
override fun onNext(m: M) {
onSuccess(m)
}
override fun onError(e: Throwable?) {
//这块应该可以优化
if (e is HttpException) {
val httpException = e
//httpException.response().errorBody().string()
val code = httpException.code()
var msg = httpException.message
Log.d("wxl", "code=" + code)
if (code == 504) {
msg = "网络不给力"
}
if (code == 502 || code == 404) {
msg = "服务器异常,请稍后再试"
}
onFailure(msg)
} else {
onFailure(e.toString())
}
onFinish()
}}
BaseActivity
建了基类,可以把一些公用的方法放到这里,方便:
open class BaseActivity : AppCompatActivity() {
val mCompositeSubscription: CompositeSubscription = CompositeSubscription()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onDestroy() {
if (mCompositeSubscription.hasSubscriptions()) {
//取消注册,以避免内存泄露
mCompositeSubscription.unsubscribe()
}
super.onDestroy()
}
open fun <M> addSubscription(observable: Observable<M>, subscriber: Subscriber<M>) {
mCompositeSubscription.add(
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber))
}}
MainActivity
请求接口:
//冒号表示继承
class MainActivity : BaseActivity() {
//问号表示该变量可以为空
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//object为对象表达式
addSubscription(ApiClient.retrofit().loadData("101190201"), object : ApiCallback<WeatherinfoModel>() {
override fun onSuccess(model: WeatherinfoModel) {
Log.d("wxl", "city=" + model.weatherinfo.city + ",cityid=" + model.weatherinfo.cityid)//输出“city=无锡,cityid=101190201”
}
override fun onFailure(msg: String?) {
Log.d("wxl", "onFailure=" + msg)
}
override fun onFinish() {
Log.d("wxl", "onFinish")
}
})
}}
参考
Keddit — Part 6: API — Retrofit & Kotlin
Kotlin for Android 实践
系列博客
Kotlin for Android(一)准备工作
Kotlin for Android(二)基础语法
Kotlin for Android(三)类和对象