kotlin之jetpack+mvvm+rxjava+retrofit

本文介绍了一个基于Kotlin语言、采用Jetpack组件并结合RxJava及Retrofit实现MVVM架构的应用开发方案。文章分享了具体的实现思路和技术选型,并提供了关键代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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() {

    }


}

目前核心类就是这几个吧,其他都是一些回调,调用的简单业务,有兴趣的可以一起交流交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值