美文网首页性能优化移动架构
Kotlin+Retrofit+RxJava+MVP封装(二)

Kotlin+Retrofit+RxJava+MVP封装(二)

作者: 2012lc | 来源:发表于2017-09-21 11:48 被阅读0次

    前言

    Kotlin+Retrofit+RxJava+MVP封装(一)
    Kotlin+Retrofit+RxJava+MVP封装(三)

    封装

    这篇文章主要是在第一篇文章的基础上的一个封装和RecyclerView的实现,就MVP结构来看,我们至少会有三个基类,一个网络请求封装类。

    BaseActivity

    在BaseActivity中,我们将绑定布局,初始化Presenter,写入吐司,页面跳转,等待界面等基础操作。

    abstract class BaseActivity <V:BaseView,T :BasePresenter<V>>: FragmentActivity(),BaseView {
        //当前Activity渲染的视图View
        private var mContextView: View? = null
        private var progressDialog: Dialog? = null
        open var mPresenter:T?=null
        //private var mCenterText: TextView? = null
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // 设置activity为无标题栏
            requestWindowFeature(Window.FEATURE_NO_TITLE)
            mContextView = LayoutInflater.from(this).inflate(bindLayout(), null)
            setContentView(mContextView)
            // 初始化ui
            initView()
            // 初始化数据
            initData()
            // 添加监听器
            initListener()
        }
    
        //布局绑定
        abstract fun bindLayout(): Int
    
        // 初始化ui
        @Suppress("UNCHECKED_CAST")
        protected open fun initView() {
            if(mPresenter==null){
                mPresenter=createPresenter()
            }
            mPresenter!!.attachView(this as V)
        }
    
        // 初始化数据
        protected abstract fun initData()
    
        // 添加监听器
        protected abstract fun initListener()
    
    
        // Toast
        fun showToast(text: String) {
            Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
        }
    
        //activity跳转
        @JvmOverloads fun openActivity(targetActivityClass: Class<*>, bundle: Bundle? = null) {
            val intent = Intent(this, targetActivityClass)
            if (bundle != null) {
                intent.putExtras(bundle)
            }
            startActivity(intent)
        }
    
        fun openActivity(targetActivityClass: Class<*>, targetName: String, targetMessage: String?) {
            val intent = Intent(this, targetActivityClass)
            if (targetMessage != null) {
                intent.putExtra(targetName, targetMessage)
            }
            startActivity(intent)
        }
        //activity跳转并关闭当前页面
        fun openActivityAndCloseThis(targetActivityClass: Class<*>, targetName: String, targetMessage: String) {
            openActivity(targetActivityClass, targetName, targetMessage)
            this.finish()
        }
    
        fun openActivityAndCloseThis(targetActivityClass: Class<*>) {
            openActivity(targetActivityClass)
            this.finish()
        }
    
        fun openActivityAndCloseThis(targetActivityClass: Class<*>, bundle: Bundle) {
            openActivity(targetActivityClass, bundle)
            this.finish()
        }
    
        //显示等待动画
        override fun LoadingShow() {
            progressDialog = Dialog(this, R.style.progress_dialog)
            progressDialog!!.setContentView(R.layout.dialog)
            progressDialog!!.setCancelable(true)
            progressDialog!!.window!!.setBackgroundDrawableResource(android.R.color.transparent)
            progressDialog!!.setCanceledOnTouchOutside(false)
            progressDialog!!.show()
        }
        //隐藏等待动画
        override fun LoadingDis() {
            if (progressDialog != null && progressDialog!!.isShowing)
                progressDialog!!.dismiss()
        }
    
        //弹出原生交互界面
        fun AffirmDialogShow(title: String, content: String) {
            AlertDialog.Builder(this)
                    .setCancelable(false)
                    .setTitle(title)
                    .setMessage(content)
                    .setNegativeButton("取消") { dialogInterface, i -> dialogInterface.dismiss() }
                    .setPositiveButton("确认") { dialogInterface, i ->
                        okOperation()//点击确认操作
                        dialogInterface.dismiss()
                    }.show()
        }
    
        abstract fun createPresenter():T//初始化Presenter
    
        protected open fun okOperation() {}
    
        override fun onDestroy() {
            super.onDestroy()
            mPresenter!!.detachView()
            mContextView = null
          //  Log.i("xxxxxxxxxxxxxxx","xxxxxxxxxxxxxxxxxxx")
        }
    }
    

    BaseModel

    在BaseModel中主要的实现的需要传入参数的写入,数据的请求,Rxjava的线程切换。

    abstract class BaseModel <T:BaseBean>{
        //传入的key
        var mParams:HashMap<String,String>?=HashMap()
       //请求接口
        open fun PostParams(){
            ServiceParams(Params()!!)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe (object : Subscriber<BaseBean>() {
                        override fun onCompleted() {
                            Completed()
                        }
    
                        override fun onError(e: Throwable?) {
                            FailedOperation(e)
                        }
    
                        override fun onNext(o: BaseBean) {
                           // val message = o.message
                            //mOnLoginListenr?.LoginSuccess()
                            SuccessOperation(o)
                        }
                    })
        }
    
        open fun Completed() {
    
        }
       //请求失败
        abstract fun FailedOperation(e: Throwable?)
    
    
       //请求成功
        abstract fun SuccessOperation(o: BaseBean)
    
    
        abstract fun Params(): HashMap<String, String>?
    
       //得到Observable
        abstract fun ServiceParams(params: HashMap<String, String>): Observable<T>
    
    
    
        open fun ClearHashMap(){
            if (mParams!!.size>0)
                mParams!!.clear()
        }
    }
    

    BasePresenter

    在BasePresenter中比较简单,需要实现绑定和解绑函数,attachView,detachView,在这里使用了弱引用,内存不够时释放,

    abstract class BasePresenter<T:BaseView> {
    
        var mViewRef:WeakReference<T>?=null
    
         fun attachView(view:T){
             mViewRef=WeakReference<T>(view)
         }
    
         fun detachView(){
             if(mViewRef!=null){
                 mViewRef!!.clear()
                 mViewRef==null
             }
         }
    }
    

    RetrofitManager

    RetrofitManager是对Retrofit的一个封装,在这个类中我们完成了对OKHTTP和Retrofit的一个初始化,以及调用

    class RetrofitManager : Interceptor {
    
      
        //长缓存有效期为7天
        val CACHE_STALE_LONG="60 * 60 * 24 * 7"
        
        var mOkHttpClient: OkHttpClient? = null
    
        var service: RetrofitService? = null
    
    
    
        init {
            initOkHttpclient()
            var retrofit = Retrofit.Builder()
                    .baseUrl(Constants.BASE_URL)
                    .client(mOkHttpClient)
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
    
            service = retrofit.create(RetrofitService::class.java)
    
        }
    
        //相当于java中的静态内部类
        companion object {
            fun builder() :RetrofitManager {
                return RetrofitManager()
            }
        }
    
    
        //配置缓存策略
        fun initOkHttpclient() {
            //log信息拦截器
            val interceptor = HttpLoggingInterceptor()
            interceptor.level = HttpLoggingInterceptor.Level.BODY
            if (mOkHttpClient == null) {
                mOkHttpClient = OkHttpClient.Builder()
                      //    .cache(cache)
                        .retryOnConnectionFailure(true)
                        .addNetworkInterceptor(this)
                        .addInterceptor(this)
                        .connectTimeout(15, TimeUnit.SECONDS)
                        .readTimeout(10000L, TimeUnit.MILLISECONDS)//读操作超时时间
                        .cookieJar(CookiesManager())
                        .build()
            }
        }
    //这是对cookie的一个长期持有
        private inner class CookiesManager : CookieJar {
            private val cookieStore = PersistentCookieStore(MyApplication.getInstance().applicationContext)
    
            override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>?) {
                if (cookies != null && cookies.size > 0) {
                    for (item in cookies) {
                        cookieStore.add(url, item)
                    }
                }
            }
    
            override fun loadForRequest(url: HttpUrl): List<Cookie> {
                return cookieStore.get(url)
            }
        }
    
        override fun intercept(chain: Interceptor.Chain?): Response {
            var request = chain!!.request()
            if (!NetWorkUtil.isNetWorkConnected()) {
                request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build()
            }
            var response = chain.proceed(request)
            if (NetWorkUtil.isNetWorkConnected()) {
                var cacheControl: String = request.cacheControl().toString()
                return response.newBuilder().header("Cache-Control", cacheControl)
                        .removeHeader("Pragma").build()
            } else {
                return response.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_LONG)
                        .removeHeader("Pragma").build()
            }
        }
    }
    

    BaseBean

    在实际开发中,每一个接口都有一些固定字段,可以提取出来生成BaeBean,其余Bean文件集成BaseBean即可,这里我就不贴出BaseBean了,因为接口原因,BaseBean应该是不一样的。

    RecyclerView

    在这个框架中我是导入的第三方的XRecyclerView

    compile 'com.jcodecraeer:xrecyclerview:1.3.2'
    

    在Android中出现最多的列表,功能大概就是上拉刷新,下拉加载,没有更多数据,当然还有很多异常处理,比如网络异常,加载失败等等异常,在这里对这些异常处理没怎么作为,大家后面自行补充。

    实现步奏

    在接口ListView中我们声明了上拉下拉等方法

    interface ListViews:BaseView {
    
        fun loadMore( data:ArrayList<*>)//加载更多
    
        fun showRefresh(data: ArrayList<*>)//上拉刷新
    
        fun hasNoMoreData()//没有更多
    
    }
    

    在activity中实现,在代码中的注释都比较详细,所以我在文字中就不多作阐述

    class ListActivity : BaseActivity<ListViews,ListPresenter>(),ListViews {
    
    
        var mAdapter:MyAdapter?=null
        var mList:ArrayList<MyPaperBean.PageResultsBean>?= ArrayList()
      //绑定布局
        override fun bindLayout(): Int {
            return R.layout.activity_list
        }
    
        override fun initData() {
            //初始化xrecyclerview
            val layoutManager = LinearLayoutManager(this)
            layoutManager.orientation = LinearLayoutManager.VERTICAL
            mRecyclerview.layoutManager=layoutManager
    
            mRecyclerview.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader)
            mRecyclerview.setLoadingMoreProgressStyle(ProgressStyle.Pacman)
            mRecyclerview.setArrowImageView(R.drawable.iconfont_downgrey)
        }
    
        override fun initListener() {
    //RecyclerView的上拉和下拉
            mRecyclerview.setLoadingListener(object :XRecyclerView.LoadingListener{
                override fun onLoadMore() {
                    mPresenter!!.getMoreData()
                }
    
                override fun onRefresh() {
                    //showToast("ssss")
                    mPresenter!!.getRefreshData()
                }
    
            })
            mAdapter= MyAdapter(mList)
            mRecyclerview.adapter=mAdapter
            mRecyclerview.refresh()
    
    
        }
    //实现接口里面的方法
        @Suppress("UNCHECKED_CAST")
        override fun loadMore(data: ArrayList<*>) {
            mList!!.addAll(data as ArrayList<MyPaperBean.PageResultsBean>)
            mAdapter!!.notifyDataSetChanged()
            mRecyclerview.loadMoreComplete()
        }
        @Suppress("UNCHECKED_CAST")
        override fun showRefresh(data: ArrayList<*>) {
           // showToast("xxxxxxxxx")
            mList!!.addAll(data as ArrayList<MyPaperBean.PageResultsBean>)
            mAdapter!!.notifyDataSetChanged()
            mRecyclerview.refreshComplete()
        }
    
        override fun hasNoMoreData() {
            mRecyclerview.setNoMore(true)
            mAdapter!!.notifyDataSetChanged()
        }
    //得到Presenter
        override fun createPresenter(): ListPresenter{
            return ListPresenter(this)
        }
    
    }
    
    

    同第一篇文章一样,实现Model和Presenter。这里就把Model贴出来,其他的等我第三篇的源码链接吧。

    interface ListModel {
    
        fun getMoreData()//上拉加载
    
        fun getRefreshDta()//下拉刷新
    
        fun showNetError()//网络错误
    
        fun showDataError()//加载错误
    
        fun loadComplete(loadedListener: LoadComplete)//数据加载完成
    
        interface LoadComplete{
            fun getDataRefresh(mDatas:ArrayList<*>)
            fun getDataMore(mDatas:ArrayList<*>)
            fun getDataFailed(baseBean: BaseBean)
            fun hasNoMoreData()
        }
    }
    

    后续

    这篇文章只完成了几个基类的封装和RecyclerView的初步实现,在下篇文章中将完成对RecyclerView的封装,欲知后事如何,请听下回分解......

    相关文章

      网友评论

        本文标题:Kotlin+Retrofit+RxJava+MVP封装(二)

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