用 Kotlin 编写的 MVP+RxJava+Retrofit 黄历 demo
Posted code小生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用 Kotlin 编写的 MVP+RxJava+Retrofit 黄历 demo相关的知识,希望对你有一定的参考价值。
code小生,一个专注 android 领域的技术平台
Kotlin 在 2017 年 Google 开发者大会的时候,被指定为 Android 的官方语言。现在使用 Kotlin 来开发 Android 也越来越火,如果你还没有接触过 Kotlin,那么肯定是慢人一步了。
其实我在今年寒假之前就已经看完了《Kotlin实战》这本书,但奈于工作和生活上的事情太多,之后一直没有去关注这一部分。最近也是难得有时间,所以重新看了遍Kotlin的语法知识以及对比和Java的不同。于是就想趁热用Kotlin来写一个小demo。
demo虽然很简单,但是涵盖的内容还是很实用的。下面是demo中用到的技术:
RxJava
RxAndroid
Retrofit
anko - JB公司专门为Android开发的一套kotlin组件库
MVP - 基于todo-mvp-kotlin在加入Rx
先来看一下demo目录结构:
以下是我们的正文部分,一步步来完成这个demo:
1.创建Kotlin项目,引入开发用到的库
项目创建没什么好说的,创建时注意勾上“Include Kotlin support"
demo中用到的开源库:
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation "io.reactivex.rxjava2:rxjava:2.1.6"
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
//OKHttp的日志拦截器,可以打印网络请求结果
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
implementation 'org.jetbrains.anko:anko:0.10.5'
}
2.activity_main.xml界面编写
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.wbb.kotlinapp.mvp.ui.MainActivity">
<DatePicker
android:id="@+id/datePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_centerInParent="true"/>
<Button
android:id="@+id/selectButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="日期选择"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"/>
<TextView
android:id="@+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="当天详情"
android:layout_below="@id/selectButton"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"/>
<TextView
android:id="@+id/contentTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/titleTextView"
android:layout_marginTop="20dp"
android:gravity="center"/>
</RelativeLayout>
3.根据json来编写实体类
{
"reason":"Success",
"result":
{
"data":{
"date":"2018-8-9",
"weekday":"星期四",
"animalsYear":"狗",
"suit":"解除.祭祀.祈福.求嗣.修造.动土.竖柱.上梁.安床.纳畜.造屋.合脊.起基.入殓.破土.安葬.",
"avoid":"出火.嫁娶.开光.进人口.出行.词讼.开市.入宅.移徙.赴任.",
"year-month":"2018-8",
"lunar":"六月廿八",
"lunarYear":"戊戌年"}
},
"error_code":0
}
这里可以根据json的结构可以写一个通用的ApiResult,但我这里为了读者清晰,写成了CalentarDayBean
3个实体类如下:
data class CalentarDayBean<T>(val reason: String, val result: T, val error_code: Int)
data class CalentarDayResult<T>(val data: T)
data class CalentarDayData(
val date: String,
val weekday: String,
val animalsYear: String,
val suit: String,
val avoid: String,
val yearMonth: String,
val holiday: String,
val lunar: String,
val lunarYear: String,
val desc: String
)
看到这里是不是觉得Kotlin语言的简洁性,没错Kotlin用data定义一个class可以省去java的一大堆getter、setter
4.Retrofit封装和接口编写
请求接口RetrofitService
interface RetrofitService {
/**
* 获取当天的详细信息
*/
@GET("calendar/day")
fun calenderDay(
@Query("date") date: String,
@Query("key") key: String
): Observable<CalentarDayBean<CalentarDayResult<CalentarDayData>>>
}
Retrofit封装
class RetrofitUtil {
companion object {
const val TAG="RetrofitUtil"
/**
* 创建Retrofit
*/
fun create(url: String): Retrofit {
//显示日志级别
val level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.BODY
//新建log拦截器
val loggingInterceptor: HttpLoggingInterceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { message ->
Log.e(TAG,"OkHttp:$message")
})
loggingInterceptor.level = level
//okHttpClientBuilder
val okHttpClientBuilder = OkHttpClient.Builder()
okHttpClientBuilder.connectTimeout(60, TimeUnit.SECONDS)
okHttpClientBuilder.readTimeout(10, TimeUnit.SECONDS)
//OkHttp进行添加拦截器loggingInterceptor
okHttpClientBuilder.addInterceptor(loggingInterceptor)
return Retrofit.Builder()
.baseUrl(url)
.client(okHttpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
}
/**
* 获取ServiceApi
*/
fun <T> getService(url: String, service: Class<T>): T {
return create(url).create(service)
}
val retrofitService: RetrofitService = RetrofitUtil.getService(Constants.REQUEST_BASE_URL, RetrofitService::class.java)
}
}
全局常量Constants
object Constants{
val REQUEST_BASE_URL="http://v.juhe.cn/"
val KEY="1be865c0e67e3"
}
在Kotlin里是没有静态方法和静态变量、常量这一说法的,一般都是用companion伴生对象代替Java中的static
5.MVP构建
demo的mvp模式是参考谷歌的todo-mvp-kotlin,但是我省去了respoistory这一部分。这一部分的逻辑较为复杂,讲解这一部分的话对于我们的demo来说其实是本末倒置了,有兴趣的同学可以去参考以下博文:
谷歌官方MVP框架源码解析之 TODO-MVP
Android官方MVP架构解读
interface CalentarContract {
interface View : BaseView<Presenter> {
fun showDayCalentarData(calentarDayBean: CalentarDayBean<CalentarDayResult<CalentarDayData>>)
fun showError(errorMsg: String)
}
interface Presenter : BasePresenter {
fun getDayCalentarData(date: String)
}
}
MainActivity实现CalentarContract.View接口,CalentarPresenter实现CalentarContract.Presenter接口
class CalentarPresenter(val view: CalentarContract.View) : CalentarContract.Presenter {
var compositeDisposable:CompositeDisposable
companion object {
const val TAG = "CalentarPresenter"
}
init {
view.presenter = this
compositeDisposable= CompositeDisposable()
}
override fun subscribe() {
}
override fun unsubscribe() {
compositeDisposable.clear()
}
override fun getDayCalentarData(date: String) {
val disposable = RetrofitUtil
.retrofitService
.calenderDay(date, "933dc930886c8c0717607f9f8bae0b48")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result ->
view.showDayCalentarData(result)
Log.e(TAG, result.toString())
}, { error ->
view.showError(error.message.toString())
Log.e(TAG, error.message.toString())
})
compositeDisposable.add(disposable)
}
}
class MainActivity : AppCompatActivity(), CalentarContract.View {
override lateinit var presenter: CalentarContract.Presenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
presenter = CalentarPresenter(this)
selectButton.setOnClickListener {
titleTextView.visibility = View.GONE
selectButton.visibility = View.GONE
contentTextView.visibility = View.GONE
datePicker.visibility = View.VISIBLE
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
datePicker.setOnDateChangedListener { view, year, month, day ->
var date: String = "${year}-${month+1}-${day}"
presenter.getDayCalentarData(date)
}
}
}
override fun onResume() {
super.onResume()
presenter.subscribe()
}
override fun onDestroy() {
super.onDestroy()
presenter.unsubscribe()
}
override fun showDayCalentarData(calentarDayBean: CalentarDayBean<CalentarDayResult<CalentarDayData>>) {
datePicker.visibility=View.GONE
titleTextView.visibility = View.VISIBLE
selectButton.visibility = View.VISIBLE
contentTextView.visibility = View.VISIBLE
titleTextView.text=calentarDayBean.result.data.date
contentTextView.text = calentarDayBean.result.data.toString()
}
override fun showError(errorMsg: String) {
toast(errorMsg)
}
}
最后给上demo演示效果
KotlinDemo演示.gif
参考链接
from-java-to-kotlin
菜鸟Kotlin教程
附上demo地址
https://github.com/weibindev/KotlinAppDemo
kotlin
分享技术我是认真的
以上是关于用 Kotlin 编写的 MVP+RxJava+Retrofit 黄历 demo的主要内容,如果未能解决你的问题,请参考以下文章
android查询天气demo,基于mvp+kotlin+rxjava2+room+retrofit2
Android 开源项目Kotlin+MVP+Retofit2+RxJava2架构开发一款短视频App