kotlin之jetpack+mvvm+rxjava+retrofit
最近在做新项目,看到kotlin语言,于是对着菜鸟教程看了一下,准备新项目使用kotlin写:
技术组合
1 网络请求框架okHttp 目前对于okhttp支持的比较好的是retrofit框架
2 异步处理采用的是rxjava框架,目前虽然rxjava3.0出来了,但是retrofit目前还没有更新到3.0 所以采用 的还是rxjava2.0。
3.对于项目整体框架采用的是mvvm思想,因为使用的是谷歌推荐的jetpack,有兴趣的同学可以去了解一下;
下面贴部分代码:
abstract class BaseFragmeent<VM : AndroidViewModel?, SV : ViewDataBinding?> : Fragment() {
protected var viewModel: VM? = null
protected var bindingView: SV? = null
// fragment是否显示了
protected var mIsVisible = false
//MVVM是否准备好了
protected var mIsPrepared = false
//是否是第一次加载
protected var mIsFirst = true
private var activity: Activity? = null
override fun onAttach(context: Context) {
super.onAttach(context)
activity = context as Activity
}
@Nullable
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
bindingView = DataBindingUtil.inflate<SV>(activity?.layoutInflater!!, setContent(), null, false)
return bindingView?.root
}
override fun onActivityCreated(@Nullable savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initViewModel()
}
/**
* 初始化ViewModel
*/
private fun initViewModel() {
val viewModelClass = ClassUtil.getViewModel<VM>(this)
if (viewModelClass != null) {
viewModel = activity?.application?.let {
ViewModelProvider.AndroidViewModelFactory(it)
.create(viewModelClass)
}
}
}
protected open fun <T : View?> getView(id: Int): T {
return view?.findViewById<View>(id) as T
}
/**
* 布局
*/
abstract fun setContent(): Int
}
abstract class BaseActivity<VM : AndroidViewModel?, SV : ViewDataBinding?> : AppCompatActivity() {
// ViewModel
protected var viewModel: VM? = null
// 布局view
protected var bindingView: SV? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//初始化沉浸式
if (isImmersionBarEnabled()) {
initImmersionBar()
}
}
override fun setContentView(@LayoutRes layoutResID: Int) {
bindingView = DataBindingUtil.inflate<SV>(layoutInflater, layoutResID, null, false)
window.setContentView(bindingView!!.root)
initViewModel()
}
/**
* 初始化ViewModel
*/
private fun initViewModel() {
val viewModelClass= ClassUtil.getViewModel<VM>(this)
if (viewModelClass != null) {
viewModel = ViewModelProvider.AndroidViewModelFactory(application)
.create(viewModelClass)
}
}
/**
* 是否可以使用沉浸式
* Is immersion bar enabled boolean.
*
* @return the boolean
*/
protected open fun isImmersionBarEnabled(): Boolean {
return false
}
protected open fun initImmersionBar() {
//在BaseActivity里初始化
ImmersionBar.with(this).navigationBarEnable(false).init()
}
}
open class BaseViewModel(application: Application) : AndroidViewModel(application) {
private var mCompositeDisposable: CompositeDisposable? = null
protected var apiService = RetrofitManager.apiService
var error = MutableLiveData<String>()
protected set
protected fun <T : BaseRes<*>> execute(observable: Observable<T>, subscriberCallBack: SubscriberCallBack<T>) {
observable
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriberCallBack)
}
protected fun addDisposable(disposable: Disposable?) {
if (mCompositeDisposable == null) {
mCompositeDisposable = CompositeDisposable()
}
mCompositeDisposable!!.add(disposable!!)
}
override fun onCleared() {
super.onCleared()
if (mCompositeDisposable != null && !mCompositeDisposable!!.isDisposed) {
mCompositeDisposable!!.clear()
}
}
}
class RetrofitManager private constructor(url: String) {
private val mApiService: APIService
init {
initOkHttpClient()
val retrofit = Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(mOkHttpClient)
.build()
mApiService = retrofit.create(APIService::class.java)
}
companion object {
//时间超时
const val TIMEOUT = 10
@Volatile
private var mOkHttpClient: OkHttpClient? = null
//保证多个地址的;
var managers: MutableMap<String, RetrofitManager> = HashMap()
private const val release_url = "http://ytai-api.test.ytzxjy.com/"
private const val debug_url = ""
//
fun getInstance(url: String): RetrofitManager {
var instance = managers[url]
if (instance == null) {
instance = RetrofitManager(url)
managers[url] = instance
}
return instance
}
val instance: RetrofitManager
get() = getInstance(release_url)
@JvmStatic
val apiService: APIService
get() = instance.mApiService
fun getAPIService(url: String): APIService {
return getInstance(url).mApiService
}
}
private fun initOkHttpClient() {
val interceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
private val mMessage = StringBuilder()
override fun log(message: String) {
var message = message
if (LogUtil.isDebug) {
// 请求或者响应开始
if (message.startsWith("--> POST")) {
mMessage.setLength(0)
}
// 以{}或者[]形式的说明是响应结果的json数据,需要进行格式化
if (message.startsWith("{") && message.endsWith("}")
|| message.startsWith("[") && message.endsWith("]")
) {
message = JsonUtil.formatJson(JsonUtil.decodeUnicode(message))
}
mMessage.append(message)
// 响应结束,打印整条日志
if (message.startsWith("<-- END HTTP")) {
LogUtil.i("message==",mMessage.toString())
}
}
}
})
interceptor.level = HttpLoggingInterceptor.Level.BODY
if (mOkHttpClient == null) {
synchronized(RetrofitManager::class.java) {
if (mOkHttpClient == null) {
// 指定缓存路径,缓存大小100Mb
val cache = Cache(
File(App.app.applicationContext.cacheDir, "HttpCache"),
1024 * 1024 * 100
)
mOkHttpClient = OkHttpClient.Builder()
.cache(cache) //统一处理请求头
.addInterceptor(interceptor)
.retryOnConnectionFailure(false) //错误重连
.connectTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS) //设置超时
.readTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
.writeTimeout(TIMEOUT.toLong(), TimeUnit.SECONDS)
.build()
}
}
}
}
class SubscriberCallBack<T : BaseRes<*>?>(private val apiCallback: ApiCallback<T>) : Observer<T> {
override fun onError(e: Throwable) {
e.printStackTrace()
if (e is HttpException) {
val httpException = e
var msg = httpException.message
val code = httpException.code()
try {
msg = httpException.response().toString()
} catch (e1: IOException) {
e1.printStackTrace()
}
msg = if (code == 408) {
"服务器响应超时,请稍后再试。code=${code}msg=$msg"
} else if (code == 405) {
"请求行中指定的请求方法不能被用于请求相应的资源。code=${code}msg=$msg"
} else if (code == 403) {
"服务器已经理解请求,但是拒绝执行它。code=${code}msg=$msg"
} else if (code == 500) {
"服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。code=${code}msg=$msg"
} else if (code == 404) {
"请求失败,请求所希望得到的资源未被在服务器上发现。code=${code}msg=$msg"
} else {
"code=" + code + "msg=" + msg
}
apiCallback.onFailure(code, msg)
} else if (e is SocketTimeoutException) {
val msg = "连接服务器超时"
apiCallback.onFailure(408, msg)
} else if (e is ConnectException) {
val msg = "网络中断,请检查您的网络状态"
apiCallback.onFailure(408, msg)
} else if (e is TimeoutException) {
val msg = "连接超时,请检查您的网络状态"
apiCallback.onFailure(408, msg)
} else {
// apiCallback.onFailure(0, e.getMessage());
apiCallback.onFailure(0, "未知错误")
}
apiCallback.onCompleted()
}
override fun onSubscribe(disposable: Disposable) {
apiCallback.onSubscribe(disposable)
}
override fun onNext(response: T) {
apiCallback.onSuccess(response)
}
override fun onComplete() {
}
}
目前核心类就是这几个吧,其他都是一些回调,调用的简单业务,有兴趣的可以一起交流交流。