美文网首页
Android 快速打造Kotlin+MVP+Rxjava+Re

Android 快速打造Kotlin+MVP+Rxjava+Re

作者: 100岁的Android工程师 | 来源:发表于2018-08-28 14:24 被阅读0次

    快速打造Kotlin+MVP+Rxjava+Retrofit项目架构(引用Google推荐架构模式:契约接口)

    文件目录:

    主目录
    mvp中的目录

    主要代码示例:

    • 1、一个登录模型(也叫bean、entity)
    /**
     * 后台规定的接口命名的字段是大写开头
     */
    
    class LoginModel : Base() {
    
        /**
         * Ext : {"Authority":3,"Token":"213bfc688a7e099b1f2a27b64f59c9e1"}
         * Message : 登录成功
         * State : true
         */
    
        var ext: ExtBean? = null
    
    
        class ExtBean {
            /**
             * Authority : 3
             * Token : 213bfc688a7e099b1f2a27b64f59c9e1
             */
    
            var authority: Int = 0
            var token: String? = null
        }
    }
    
    • 2、一个登录的契约接口
    interface View : BaseContract.BaseView {
            fun loginSus(loginModel: LoginModel) //登录成功
            fun err(code: Int, message: String) //出错
        }
    
        interface Presenter : BaseContract.BasePresenter<View> {
            fun login(telephoneNumber: String, verificationCode: String, token: String) //登录
        }
    

    顺便贴出BaseContract契约接口基类

    /**
     * 对应mvp中的contract契约接口
     */
    
    interface BaseContract {
        interface BasePresenter<in T> {
            /*该方法可以获取到View实例对象*/
            fun attachView(view: T)
    
            /*释放View对象的引用,gc才能回收View*/
            fun detachView()
        }
    
        interface BaseView {
            //view的一些共有方法
            fun showError(e: Throwable)
            fun complete()
        }
    }
    
    • 3、一个实现了View接口充当V层的Activity
    /**
     * 模拟登录的view层
     */
    class MainActivity : BaseActivity<LoginContract.View,LoginContract.Presenter>(),LoginContract.View {
        override fun err(code: Int, message: String) {
            ToastUtils.showShort("错误码:$code\n错误信息:$message")
        }
    
        override fun loginSus(loginModel: LoginModel) {
            disMissLoading()
            if (loginModel.State) {
                ToastUtils.showShort("登录成功")
            }else{
                ToastUtils.showShort(loginModel.Message)
            }
        }
    
        override fun showError(e: Throwable) {
            disMissLoading()
        }
    
        override fun complete() {
    
        }
    
        override fun getLayoutId(): Int = R.layout.activity_main
    
        override fun configView() {
            login.setOnClickListener({
                showLoading()
                mPresenter!!.login("18381309101","1111","") })
        }
    
        override fun initData() {
    
        }
    
        override fun initPresenter(): LoginContract.Presenter = LoginPresenter()
    
    }
    
    • 实现Presenter,充当P层的一个登录的Presenter
    class LoginPresenter : RxPresenter<LoginContract.View>(), LoginContract.Presenter {
    
        /**
         * 登录
         * @param telephoneNumber
         * @param verificationCode
         * @param token
         */
        override fun login(telephoneNumber: String, verificationCode: String, token: String) {
            val subscription = HttpManager.getWorkHttpService()!!.signIn(telephoneNumber, verificationCode, token)
                    .compose(ScheduleTransformer.instance)
                    .subscribe(object : ObserverImp<Any>() {
    
                        override fun onErr(errCode: Int, str: String) {
                            mView!!.err(errCode,str)
                        }
    
                        override fun doNext(loginModel: Any) {
                            mView!!.loginSus(loginModel as LoginModel)
                        }
                    })
            addSubscribe(subscription)
        }
    }
    

    到这里mvp构建就已经完成了,但是那些日常操作:统一错误处理、文件进度监听、Retorfit的自定义拦截器、内存泄漏处理、Retrofit自定义转换器等等还需要完成。。。

    一些重要的代码:

    • 统一错误处理
    override fun onError(e: Throwable) {
            var e = e
            var throwable = e
            //获取最根源的异常
            while (throwable.cause != null) {
                if (e is HttpException) {
                    break
                }
                e = throwable
                throwable = throwable.cause!!
            }
            if (e is HttpException) {
                when (e.code()) {
                    UNAUTHORIZED -> onErr(UNAUTHORIZED, "")
                    FORBIDDEN -> onErr(FORBIDDEN, "权限错误")          //权限错误,需要实现
                    NOT_FOUND -> onErr(NOT_FOUND, "")
                    REQUEST_TIMEOUT -> onErr(REQUEST_TIMEOUT, "")
                    GATEWAY_TIMEOUT -> onErr(GATEWAY_TIMEOUT, "")
                    INTERNAL_SERVER_ERROR -> onErr(INTERNAL_SERVER_ERROR, "")
                    BAD_GATEWAY -> onErr(BAD_GATEWAY, "")
                    SERVICE_UNAVAILABLE -> onErr(SERVICE_UNAVAILABLE, "")
                    else -> onErr(ERR_CODE_NET, "")
                }
            } else if (e is SocketTimeoutException) {
                onErr(GATEWAY_TIMEOUT, "请求超时!")
            } else if (e is UnknownHostException) {
                onErr(ERR_CODE_NET, "网络连接失败!")
            } else {
                onErr(ERR_CODE_UNKNOWN, "未知错误!")
            }
        }
    
    • 2、文件进度监听
     override fun read(sink: Buffer, byteCount: Long): Long {
                    try {
                        val bytesRead = super.read(sink, byteCount)
                        if (totalBytesRead == 0L && listener != null) {
                            listener.DLoadStart()
                        }
                        totalBytesRead += if (bytesRead != -1L) bytesRead else 0
    
                        if (null != listener) {
                            if (bytesRead == -1L) {
                                listener.DLoadSuccess()
                            }
                            if ((totalBytesRead * 100L / responseBody.contentLength()).toInt() > lastPro) {
                                listener.DLoadProgress((totalBytesRead * 100L / responseBody.contentLength()).toInt())
                            }
                            lastPro = (totalBytesRead * 100L / responseBody.contentLength()).toInt()
                        }
                        return bytesRead
                    } catch (e: IOException) {
                        listener?.DLoadFail()
                    }
    
                    return 0L
    
                }
    
    • 3、自定义文件下载拦截器
    /**
     * 文件下载拦截器
     */
    
    class DownLoadInterceptor(private val listener: DLProListener) : Interceptor {
    
        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): Response {
            val originalResponse = chain.proceed(chain.request())
    
            return originalResponse.newBuilder()
                    .body(FileResBody(originalResponse.body(), listener))
                    .build()
        }
    }
    
    • 4、内存泄漏处理,释放对activity 的引用
     override fun attachView(view: T) {
            this.mView = view
        }
    
        override fun detachView() {
            this.mView = null
            unSubscribe()
        }
    
    • 5、自定义单例的Retrofit转换器
    /**
     * 单例实现的转换器,统一指定每一个接口请求实在io线程,回调在ui线程
     */
    
    class ScheduleTransformer<T>
    /**
     * 私有的构造函数
     */
    private constructor() : Observable.Transformer<T, T> {
        /**
         *懒加载内部单例
         */
        private object TransformerHolder {
            private val instance: ScheduleTransformer<Any>? = null
            fun getInstance(): ScheduleTransformer<Any> {
                return instance ?: ScheduleTransformer<Any>()
            }
        }
    
        override fun call(tObservable: Observable<T>): Observable<T> {
            return tObservable.subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
        }
    
        /**
         * 伴生
         */
        companion object {
            val instance: ScheduleTransformer<Any>
                get() = TransformerHolder.getInstance()
        }
    }
    

    该架构用起来十分方便和灵活,里面还有常用的一些基类和处理类,已经在正式项目中使用,请大胆尝试,Github地址:实战MVP架构,包含JAVA版本,欢迎打星鼓励!

    相关文章

      网友评论

          本文标题:Android 快速打造Kotlin+MVP+Rxjava+Re

          本文链接:https://www.haomeiwen.com/subject/uhgfwftx.html