Kotlin語言基于Mvp+Retrofit+RxJava封裝的Android項(xiàng)目的基礎(chǔ)依賴庫

溫馨提示

寫博客是為了記錄在開發(fā)過程中所涉及到的技術(shù)以及遇到的問題的解決镊折,如果該博客對您有所幫助片习,希望可以點(diǎn)個關(guān)注/喜歡懂鸵;如果您對文章中的內(nèi)容有什么不同的見解爬范,歡迎留言進(jìn)行討論掸茅。謝謝椅邓!

Kotlin語言基于Mvp+Retrofit+RxJava封裝的Android項(xiàng)目的基礎(chǔ)依賴庫

前言

該Library是基于Kotlin語言封裝的一個庫秧了,主要是用來創(chuàng)建一個kotlin項(xiàng)目時耙箍,作為項(xiàng)目的簡單封裝,使用該Library作為依賴引入狱窘,即可進(jìn)行項(xiàng)目開發(fā)陵且,省去一些前期準(zhǔn)備工作裁僧。

該Library主要進(jìn)行了一下封裝:

  1. 采用普通MVC架構(gòu)的方式个束,對Activity,F(xiàn)ragment,Adapter和一些工具類的封裝以及自定義View的實(shí)現(xiàn)聊疲;
  2. 采用Retrofit+RxJava 對http請求進(jìn)行相應(yīng)的封裝茬底,可設(shè)置公共參數(shù),并對RX生命周期進(jìn)行處理获洲;
  3. 采用MVP架構(gòu)阱表,對上面封裝的Activity,F(xiàn)ragment 進(jìn)行二次封裝贡珊;
  4. 該項(xiàng)目使用了org.jetbrains.anko 最爬,可實(shí)現(xiàn)對布局文件的自動依賴注入,kotlin文件中的View名稱就是對應(yīng)布局文件中View的 id;

項(xiàng)目GitHub地址

一门岔、采用普通方式封裝的基礎(chǔ)文件介紹

1爱致、BaseActivity

package:cn.onestravel.library.kotlin.base.activity

所有Activity的基類,定義一些子類必須實(shí)現(xiàn)的和可實(shí)現(xiàn)的方法:

 /**
     * 獲取布局ID,子類必須實(shí)現(xiàn)
     */
    protected abstract fun getLayoutId(): Int


    /**
     * 初始化 View 的相關(guān)操作寒随,若有需要可在子類實(shí)現(xiàn)
     */
    protected open fun initView() {}

    /**
     * 初始化 Listener 事件的相關(guān)操作糠悯,若有需要可在子類實(shí)現(xiàn)
     */
    protected open fun initListener() {}


    /**
     * 初始化 Data 數(shù)據(jù)的相關(guān)操作,若有需要可在子類實(shí)現(xiàn)
     */
    protected open fun initData() {}


    /**
     * 在主線程彈出Toast 提示
     * @param msg 需要彈出的提示信息
     */
    protected open fun showToast(msg:String){
        runOnUiThread {
            toast(msg)
        }
    }

    /**
     * 在主線程彈出Toast 提示
     * @param stringRes 需要彈出的提示信息的string資源ID
     */
    protected open fun showToast(stringRes:Int){
        runOnUiThread {
            toast(getString(stringRes))
        }
    }

    /**
     * 跳轉(zhuǎn)到另一個Activity妻往,并且finish 掉當(dāng)前Activity
     * 需要跳轉(zhuǎn)的Activity必須繼承于BaseActivity 或者
     * @param params 可變參數(shù)互艾,需要通過intent傳遞的參數(shù) eg:"key" to "value"
     */
    inline fun <reified T: BaseActivity> startActivityAndFinish(vararg params: Pair<String, Any?>) {
        startActivity<T>(*params)
        finish()
    }

2、BaseListActivity

package:cn.onestravel.library.kotlin.base.activity

繼承自BaseActivity讯泣,實(shí)現(xiàn)針對RecyclerView實(shí)現(xiàn)列表數(shù)據(jù)的一些配置纫普,簡化實(shí)現(xiàn)只有一個列表布局的Activity,并且實(shí)現(xiàn)上拉加載好渠,下拉刷新操作昨稼。

主要方法如下:

 protected fun getRecyclerView():LoadMoreRecyclerView{
        return mRecyclerView
    }

    /**
     * 獲取recyclerView的布局管理器,子類可重寫該方法晦墙,來更改布局管理器
     */
    protected open fun getLayoutManager(): RecyclerView.LayoutManager {
        val layoutManager: LinearLayoutManager = LinearLayoutManager(this)
        //設(shè)置為垂直布局悦昵,這也是默認(rèn)的
        layoutManager.orientation = OrientationHelper.VERTICAL
        return layoutManager
    }


    /**
     * 設(shè)置RecyclerView 的Adapter適配器
     * @param adapter 設(shè)置的Adapter,必須是BaseRecyclerAdapter的子類
     */
    protected fun <T> setAdapter(adapter: BaseRecyclerAdapter<T>) {
        mRecyclerView.adapter = adapter
    }

    /**
     * 設(shè)置刷新控件的顏色
     */
    protected fun setRefreshColorSchemeColors(@ColorInt vararg colors: Int) {
        mRefreshLayout.setColorSchemeColors(*colors)
    }
    /**
     * 設(shè)置刷新控件的顏色
     */
    protected fun setColorSchemeResources(@ColorRes vararg colorIds: Int) {
        mRefreshLayout.setColorSchemeResources(*colorIds)
    }

    /**
     * 設(shè)置刷新控件是否顯示
     */
    protected fun isRefresh(isRefresh: Boolean) {
        mRefreshLayout.isRefreshing = false
    }

    /**
     * 刷新完成
     */
    protected fun refreshComplete() {
        mRefreshLayout.isRefreshing = false
    }

    /**
     * 刷新數(shù)據(jù)晌畅,子類實(shí)現(xiàn)該方法,進(jìn)行數(shù)據(jù)請求
     */
    protected open fun refreshDatas() {

    }

    /**
     * 加載更多完成
     */
    protected fun loadMoreComplete() {
        mRecyclerView.loadMoreComplete(true)
    }

    /**
     * 設(shè)置是否可以加載更多
     */
    protected fun canLoadMore(canLoadMore: Boolean) {
        mRecyclerView.loadMoreEnable = canLoadMore
    }

    /**
     * 設(shè)置是否還有更多的數(shù)據(jù)
     */
    protected fun hasLoadMore(hasLoadMore: Boolean) {
        mRecyclerView.hasMore = hasLoadMore
    }

    /**
     * 加載新數(shù)據(jù)寡痰,子類實(shí)現(xiàn)該方法抗楔,進(jìn)行數(shù)據(jù)請求
     */
    protected open fun loadMoreDatas() {

    }

3、BaseRecyclerAdapter

package:cn.onestravel.library.kotlin.base.adapter

針對RecyclerView使用的RecyclerView.Adapter進(jìn)行封裝拦坠,實(shí)現(xiàn)一些基礎(chǔ)的布局(不常變化的)設(shè)置的方法连躏,定義一些方法,簡化子類的實(shí)現(xiàn)贞滨,更加有利于縮短開發(fā)時間入热;實(shí)現(xiàn)adapter中提示Toast的方法拍棕,以及添加、設(shè)置數(shù)據(jù)勺良,或者基礎(chǔ)View的設(shè)置相關(guān)內(nèi)容的方法绰播;對Item點(diǎn)擊和長按的監(jiān)聽事件。

主要方法如下:


abstract class BaseRecyclerAdapter<T> : RecyclerView.Adapter<VH>(), View.OnClickListener, View.OnLongClickListener {
    private val mDatas: MutableList<T> = ArrayList<T>()
    private lateinit var context: Context
    private var clickListener: OnItemClickListener<T>? = null
    private var longClickListener: OnItemLongClickListener<T>? = null


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
        context = parent.context
        val convertView = LayoutInflater.from(parent.context).inflate(getLayoutId(viewType), parent, false)
        convertView.setOnClickListener(this)
        convertView.setOnLongClickListener(this)
        return VH(convertView)
    }

    /**
     * 設(shè)置Item 的點(diǎn)擊事件
     */
    fun setOnItemClick(listener: OnItemClickListener<T>) {
        clickListener = listener
    }

    /**
     * 設(shè)置Item 的點(diǎn)擊事件
     */
    fun setOnItemClick(onClick: (view:View,position:Int,data:T) -> Unit) {
        clickListener = object :  OnItemClickListener<T> {
            override fun onItemClick(view: View, position: Int, data: T) {
                onClick(view,position,data)
            }
        }
    }

    /**
     * 設(shè)置Item 的長按事件
     */
    fun setOnItemLongClick(listener:OnItemLongClickListener<T>) {
        longClickListener = listener
    }

    /**
     * 設(shè)置Item 的長按事件
     */
    fun setOnItemLongClick(onLongClick: (view:View,position:Int,data:T) -> Boolean) {
        longClickListener = object : OnItemLongClickListener<T> {
            override fun onItemLongClick(view: View, position: Int, data: T):Boolean {
                return onLongClick(view,position,data)
            }
        }
    }

    override fun onClick(p0: View?) {
        val position:Int = p0?.getTag(R.id.itemViewPosition) as Int
        val data:T = mDatas.get(position)
        clickListener?.onItemClick(p0,position,data)
    }

    override fun onLongClick(p0: View?): Boolean {
        val position:Int = p0?.getTag(R.id.itemViewPosition) as Int
        val data:T = mDatas.get(position)
        return longClickListener?.onItemLongClick(p0,position,data) ?: true
    }

    /**
     * 設(shè)置數(shù)據(jù),并且會清空原數(shù)據(jù)列表
     * @param datas 新的數(shù)據(jù)列表
     */
    open fun setDatas(datas: List<T>) {
        mDatas.clear()
        mDatas.addAll(datas)
        notifyDataSetChanged()
    }

    /**
     * 添加新的數(shù)據(jù)列表到原數(shù)據(jù)列表末尾
     * @param datas 新的數(shù)據(jù)列表
     */
    open fun addDatas(datas: List<T>) {
        mDatas.addAll(datas)
        notifyDataSetChanged()
    }

    /**
     * 添加新的數(shù)據(jù)列表到原數(shù)據(jù)列表的指定位置
     * @param position 需要添加的指定位置
     * @param datas 新的數(shù)據(jù)列表
     */
    open fun addDatas(position: Int, datas: List<T>) {
        val pos = if (position > mDatas.size) {
            mDatas.size
        } else position
        mDatas.addAll(pos, datas)
        notifyDataSetChanged()
    }

    /**
     * 更新數(shù)據(jù)列表指定位置上的數(shù)據(jù)
     * @param position 需要更新數(shù)據(jù)的位置
     * @param data 更新后的數(shù)據(jù)
     */
    open fun updateData(position: Int, data: T) {
        if (position < mDatas.size) {
            mDatas.removeAt(position)
            mDatas.add(position, data)
            notifyItemChanged(position)
        }
    }

    /**
     * 添加新的數(shù)據(jù)到原數(shù)據(jù)列表末尾
     * @param datas 新的數(shù)據(jù)
     */
    open fun addData(data: T) {
        mDatas.add(data)
        notifyItemInserted(mDatas.size - 1)
    }

    /**
     * 添加新的數(shù)據(jù)到原數(shù)據(jù)列表的指定位置
     * @param position 需要添加的指定位置
     * @param data 新的數(shù)據(jù)
     */
    open fun addData(position: Int, data: T) {
        val pos = if (position > mDatas.size) {
            mDatas.size
        } else position
        mDatas.add(pos, data)
        notifyItemInserted(pos)
    }

    /**
     * 移除指定位置上的數(shù)據(jù)
     * @param position 需要添加的指定位置
     */
    open fun removeDataAt(position: Int) {
        if (position < mDatas.size) {
            mDatas.removeAt(position)
            notifyItemRemoved(position)
        }
    }

    protected open fun showToast(msg: String) {
        context.runOnUiThread {
            context.toast(msg)
        }
    }

    /**
     * 移除指定的數(shù)據(jù)
     * @param data 需要移除的數(shù)據(jù)實(shí)體
     */
    open fun removeData(data: T) {
        if (mDatas.contains(data)) {
            val position = mDatas.indexOf(data)
            mDatas.removeAt(position)
            notifyItemRemoved(position)
        }
    }

    /**
     * 根據(jù)View的類型獲取對應(yīng)的Item布局的ID
     */
    @LayoutRes
    abstract fun getLayoutId(viewType: Int): Int


    /**
     * 綁定ViewHolder 時執(zhí)行的方法尚困,在此方法里處理對Item的view的操作
     */
    abstract fun onBindVH(holder: VH, position: Int, datas: T)

    /**
     * 返回?cái)?shù)據(jù)的數(shù)量
     */
    override fun getItemCount(): Int {
        return mDatas.size
    }

    override fun onBindViewHolder(holder: VH, position: Int) {
        holder.itemView.setTag(R.id.itemViewPosition, position)
        onBindVH(holder, position, mDatas.get(position))
    }


}

/**
 *Item 的點(diǎn)擊事件
 */
interface OnItemClickListener<T> {
    fun onItemClick(view: View, position: Int, data: T)
}

/**
 *Item 的長按事件
 */
interface OnItemLongClickListener<T> {
    fun onItemLongClick(view: View, position: Int, data: T):Boolean
}

/**
 * 所有的Adapter 使用的ViewHolder
 */
class VH(itemView: View) : RecyclerView.ViewHolder(itemView) {


    /**
     * 根據(jù)View的id獲取對應(yīng)的View
     */
    inline fun <reified E : View> getView(@IdRes viewId: Int): E {
        return itemView.find<E>(viewId)
    }

    /**
     * 對TextView及其子類設(shè)置文本內(nèi)容
     * @param viewId 對應(yīng)的View 的id
     * @param value 需要設(shè)置的文本內(nèi)容
     */
    inline fun setText(@IdRes viewId: Int, value: String) {
        val view: View = this.getView(viewId)
        if (view is TextView) {
            val tv: TextView = view
            tv.text = value
        }
    }

    /**
     * 對TextView及其子類設(shè)置文本內(nèi)容
     * @param viewId 對應(yīng)的View 的id
     * @param value 需要設(shè)置的文本內(nèi)容
     */
    inline fun setText(@IdRes viewId: Int, value: Spannable) {
        val view: View = this.getView(viewId)
        if (view is TextView) {
            val tv: TextView = view
            tv.text = value
        }
    }

    /**
     * 對TextView及其子類設(shè)置文本內(nèi)容
     * @param viewId 對應(yīng)的View 的id
     * @param stringRes 需要設(shè)置的文本資源的id
     */
    inline fun setText(@IdRes viewId: Int, @StringRes stringRes: Int) {
        val view: View = this.getView(viewId)
        if (view is TextView) {
            val tv: TextView = view
            tv.setText(stringRes)
        }
    }

    /**
     * 對ImageView及其子類設(shè)置圖片
     * @param viewId 對應(yīng)的View 的id
     * @param resId 需要設(shè)置的圖片資源的id
     */
    inline fun setImageResource(@IdRes viewId: Int, @DrawableRes resId: Int) {
        val view: View = getView(viewId)
        if (view is ImageView) {
            val iv: ImageView = view
            iv.imageResource = resId
        }
    }

    /**
     * 對ImageView及其子類設(shè)置圖片
     * @param viewId 對應(yīng)的View 的id
     * @param imgUrl 需要設(shè)置的網(wǎng)絡(luò)圖片的地址
     */
    inline fun setImageUrl(@IdRes viewId: Int, imgUrl: String) {
        val view: View = getView(viewId)
        if (view is ImageView) {
            val iv: ImageView = view
            iv.loadImage(imgUrl)
        }
    }

    /**
     * 對View及其子類設(shè)置背景圖片
     * @param viewId 對應(yīng)的View 的id
     * @param resId 需要設(shè)置的背景圖片的資源地址
     */
    inline fun setBackgroundResource(@IdRes viewId: Int, @DrawableRes resId: Int) {
        val view: View = getView(viewId)
        view.setBackgroundResource(resId)
    }

    /**
     * 對View及其子類設(shè)置背景顏色
     * @param viewId 對應(yīng)的View 的id
     * @param color 需要設(shè)置的背景顏色
     */
    inline fun setBackgroundColor(@IdRes viewId: Int, @ColorInt color: Int) {
        val view: View = getView(viewId)
        view.setBackgroundColor(color)
    }


    /**
     * 對View及其子類設(shè)置點(diǎn)擊事件
     * @param viewId 對應(yīng)的View 的id
     * @param color 需要設(shè)置的背景顏色
     */
    inline fun setOnClick(@IdRes viewId: Int, crossinline onClick: (View) -> Unit) {
        val view: View = getView(viewId)
        view.setOnClickListener {
            onClick.invoke(it)
        }
    }

}

4蠢箩、ImageViewExtend

package: cn.onestravel.library.kotlin.base.extend

改文件是ImageView的擴(kuò)展方法的文件,主要針對ImageView加載網(wǎng)絡(luò)圖片而新增的一些擴(kuò)展方法

具體方法如下:

inline fun ImageView.loadImage(imgUrl: String): ImageView {
    ImageUtils.loadImageUrl(this.context, imgUrl, this)
    return this
}

inline fun ImageView.loadBitmap(imgUrl: String): ImageView {
    ImageUtils.loadImageBitmap(this.context, imgUrl, this)
    return this
}

inline fun ImageView.loadGif(imgUrl: String): ImageView {
    ImageUtils.loadImageGif(this.context, imgUrl, this)
    return this
}

inline fun ImageView.loadImgCallBack(imgUrl: String, requestListener: RequestListener<Bitmap>): ImageView {
    ImageUtils.loadImageCallBack(this.context, imgUrl, this, requestListener)
    return this
}

5事甜、BaseFragment

package: cn.onestravel.library.kotlin.base.fragment

所有Fragment的基類谬泌,定義一些子類必須實(shí)現(xiàn)的和可實(shí)現(xiàn)的方法,具體方法與BaseActivity方法類似逻谦。

6掌实、BaseListFragment

package: cn.onestravel.library.kotlin.base.fragment

繼承自BaseFragment,實(shí)現(xiàn)針對RecyclerView實(shí)現(xiàn)列表數(shù)據(jù)的一些配置邦马,簡化實(shí)現(xiàn)只有一個列表布局的Fragment潮峦,并且實(shí)現(xiàn)上拉加載,下拉刷新操作勇婴;具體方法與BaseListActivity相同忱嘹。

7、DensityUtil

package: cn.onestravel.library.kotlin.base.utils

尺寸轉(zhuǎn)換工具類耕渴,可以將dip轉(zhuǎn)為px拘悦,將px轉(zhuǎn)為dip;獲取屏幕寬度和高度橱脸。

    /**
     * dip轉(zhuǎn)換為px
     */
    fun dip2px(dp: Int): Int {
        return (dp * density).toInt()
    }


    /**
     * px轉(zhuǎn)換為dip
     */
    fun px2dip(px:  Float): Int {
        return (px / density).toInt()
    }

    /**
     * 獲取屏幕寬度
     */
    fun appWidth(): Int {
        return Resources.getSystem().getDisplayMetrics().widthPixels
    }

    /**
     * 獲取屏幕高度
     */
    fun appHeight(): Int {
        return Resources.getSystem().getDisplayMetrics().heightPixels
    }

8础米、CircleTextView

package:cn.onestravel.library.kotlin.base.view

自定義圓形TextView,一滿足不同需求

9添诉、EmptyView

package:cn.onestravel.library.kotlin.base.view

自定義 數(shù)據(jù)為空的頁面視圖屁桑,主要有三個功能類型,分別為:數(shù)據(jù)為空顯示頁面(TYPE_EMPTY)栏赴;加載進(jìn)度提示頁面(TYPE_LOADING)蘑斧;加載失敗可點(diǎn)擊重試頁面(TYPE_RELOAD)

重新定義的一下方法如下:

/**
     * 設(shè)置頁面顯示類型
     *
     * @param type
     */
    fun setEmptyType(type: Int) {
        _setEmptyType(type, true)
    }

    /**
     * 設(shè)置頁面顯示類型
     *
     * @param type
     */
    private fun _setEmptyType(type: Int, isShow: Boolean) {
        this.emptyType = type
        when (type) {
            TYPE_EMPTY -> {
                layoutLoading!!.visibility = View.GONE
                layoutReload!!.visibility = View.GONE
                layoutEmpty!!.visibility = View.VISIBLE
                btnReload!!.visibility = View.GONE
                ivEmptyImg!!.visibility = View.VISIBLE
            }
            TYPE_LOADING -> {
                layoutLoading!!.visibility = View.VISIBLE
                layoutEmpty!!.visibility = View.GONE
                layoutReload!!.visibility = View.GONE
                if (tvLoadingMsg != null) {
                    tvLoadingMsg!!.text = "正在加載..."
                }
            }
            TYPE_RELOAD -> {
                layoutLoading!!.visibility = View.GONE
                layoutEmpty!!.visibility = View.GONE
                layoutReload!!.visibility = View.VISIBLE
                btnReload!!.visibility = View.VISIBLE
                ivEmptyImg!!.visibility = View.VISIBLE
            }
        }
        if (isShow) {
            show()
        }
    }

    /**
     * 設(shè)置空數(shù)據(jù)界面的背景色
     *
     * @param color 背景色
     */
    fun setEmptyBackgroundColor(color: Int) {
        layoutEmpty!!.setBackgroundColor(color)
    }

    /**
     * 設(shè)置錯誤描述
     *
     * @param resId
     */
    fun setEmptyText(@StringRes resId: Int) {
        if (tvEmptyMsg != null) {
            tvEmptyMsg!!.text = mContext!!.getString(resId)
        }
    }

    /**
     * 設(shè)置錯誤描述
     *
     * @param text
     */
    fun setEmptyText(text: CharSequence?) {
        var text = text
        if (text == null) {
            text = ""
        }
        if (tvEmptyMsg != null) {
            tvEmptyMsg!!.text = text
        }
    }


    /**
     * 設(shè)置錯誤描述字體大小
     *
     * @param size
     */
    fun setEmptyTextSize(size: Float) {
        if (tvEmptyMsg != null) {
            tvEmptyMsg!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, size)
        }
    }

    /**
     * 設(shè)置錯誤描述顏色
     *
     * @param color
     */
    fun setEmptyTextColor(color: Int) {
        if (tvEmptyMsg != null) {
            tvEmptyMsg!!.setTextColor(color)
        }
    }

    /**
     * 設(shè)置錯誤描述顏色
     *
     * @param colors
     */
    fun setEmptyTextColor(colors: ColorStateList) {
        if (tvEmptyMsg != null) {
            tvEmptyMsg!!.setTextColor(colors)
        }
    }

    /**
     * 設(shè)置頁面圖片
     *
     * @param resId
     */
    fun setEmptyImgResource(@DrawableRes resId: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            this.noDataImg = mContext!!.getDrawable(resId)
        } else {
            this.noDataImg = mContext!!.resources.getDrawable(resId)
        }
        if (ivEmptyImg != null) {
            ivEmptyImg!!.setImageResource(resId)
        }
    }


    /**
     * 設(shè)置頁面圖片
     *
     * @param noDataImg
     */
    fun setEmptyImg(noDataImg: Drawable) {
        this.noDataImg = noDataImg
        if (ivEmptyImg != null) {
            ivEmptyImg!!.setImageDrawable(noDataImg)
        }
    }

    /**
     * 獲取加載按鈕文字
     */
    fun getReloadBtnText(): String? {
        return reloadBtnText
    }

    /**
     * 設(shè)置重新加載按鈕文字
     *
     * @param resId
     */
    fun setReloadBtnText(resId: Int) {
        this.reloadBtnText = mContext!!.getString(resId)
        if (btnReload != null) {
            btnReload!!.text = this.reloadBtnText
        }
    }

    /**
     * 設(shè)置重新加載按鈕文字
     *
     * @param reloadBtnText
     */
    fun setReloadBtnText(reloadBtnText: String) {
        this.reloadBtnText = reloadBtnText
        if (btnReload != null) {
            btnReload!!.text = this.reloadBtnText
        }
    }


    /**
     * 設(shè)置重新加載按鈕文字大小
     *
     * @param reloadBtnTextSize
     */
    fun setReloadBtnTextSize(reloadBtnTextSize: Float) {
        this.reloadBtnTextSize = reloadBtnTextSize
        if (btnReload != null) {
            btnReload!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, this.reloadBtnTextSize)
        }
    }


    /**
     * 設(shè)置重新加載按鈕文字顏色
     *
     * @param color
     */
    fun setReloadBtnTextColor(color: Int) {
        this.reloadBtnTextColor = color
        if (btnReload != null) {
            btnReload!!.setTextColor(this.reloadBtnTextColor)
        }
    }

    /**
     * 設(shè)置重新加載按鈕文字顏色
     *
     * @param colors
     */
    fun setReloadBtnTextColor(colors: ColorStateList) {
        if (btnReload != null) {
            btnReload!!.setTextColor(colors)
        }
    }


    /**
     * 設(shè)置加載按鈕背景
     *
     * @param reloadBackground
     */
    fun setReloadBtnBackground(reloadBackground: Drawable) {
        this.reloadBtnBackground = reloadBackground
        if (btnReload != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                btnReload!!.background = this.reloadBtnBackground
            } else {
                btnReload!!.setBackgroundDrawable(this.reloadBtnBackground)
            }
        }
    }

    /**
     * 設(shè)置加載按鈕背景
     *
     * @param color
     */
    fun setReloadBtnBackgroundColor(color: Int) {
        this.reloadBtnBackground = ColorDrawable(color)
        if (btnReload != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                btnReload!!.background = this.reloadBtnBackground
            } else {
                btnReload!!.setBackgroundDrawable(this.reloadBtnBackground)
            }
        }
    }

    /**
     * 設(shè)置加載按鈕背景
     *
     * @param resId
     */
    fun setReloadBtnBackgroundResource(resId: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            this.reloadBtnBackground = mContext!!.getDrawable(resId)
        } else {
            this.reloadBtnBackground = mContext!!.resources.getDrawable(resId)
        }
        if (btnReload != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                btnReload!!.background = this.reloadBtnBackground
            } else {
                btnReload!!.setBackgroundDrawable(this.reloadBtnBackground)
            }
        }
    }

    /**
     * 獲取加載提示文字
     */
    fun getReloadText(): String? {
        return reloadText
    }

    /**
     * 設(shè)置重新加載提示文字
     *
     * @param resId
     */
    fun setReloadText(resId: Int) {
        this.reloadText = mContext!!.getString(resId)
        if (tvReloadMsg != null) {
            tvReloadMsg!!.text = this.reloadText
        }
    }

    /**
     * 設(shè)置重新加載提示文字
     *
     * @param reloadText
     */
    fun setReloadText(reloadText: String) {
        this.reloadText = reloadText
        if (tvReloadMsg != null) {
            tvReloadMsg!!.text = this.reloadText
        }
    }


    /**
     * 設(shè)置重新加載提示文字大小
     *
     * @param reloadTextSize
     */
    fun setReloadTextSize(reloadTextSize: Float) {
        this.reloadTextSize = reloadTextSize
        if (tvReloadMsg != null) {
            tvReloadMsg!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, this.reloadTextSize)
        }
    }


    /**
     * 設(shè)置重新加載提示文字顏色
     *
     * @param color
     */
    fun setReloadTextColor(color: Int) {
        this.reloadTextColor = color
        if (tvReloadMsg != null) {
            tvReloadMsg!!.setTextColor(this.reloadTextColor)
        }
    }

    /**
     * 設(shè)置重新加載提示文字顏色
     *
     * @param colors
     */
    fun setReloadTextColor(colors: ColorStateList) {
        if (tvReloadMsg != null) {
            tvReloadMsg!!.setTextColor(colors)
        }
    }

    /**
     * 設(shè)置頁面圖片
     *
     * @param resId
     */
    fun setReloadImgResource(@DrawableRes resId: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            this.reloadImage = mContext!!.getDrawable(resId)
        } else {
            this.reloadImage = mContext!!.resources.getDrawable(resId)
        }
        if (ivReloadImg != null) {
            ivReloadImg!!.setImageResource(resId)
        }
    }


    /**
     * 設(shè)置頁面圖片
     *
     * @param reloadImage
     */
    fun setReloadImg(reloadImage: Drawable) {
        this.reloadImage = reloadImage
        if (ivReloadImg != null) {
            ivReloadImg!!.setImageDrawable(reloadImage)
        }
    }


    /**
     * 設(shè)置加載提示文字
     *
     * @param resId
     */
    fun setLoadingText(resId: Int) {
        this.loadingText = mContext!!.getString(resId)
        if (tvLoadingMsg != null) {
            tvLoadingMsg!!.text = this.loadingText
        }
    }

    /**
     * 設(shè)置加載提示文字
     *
     * @param loadingText
     */
    fun setLoadingText(loadingText: String) {
        this.loadingText = loadingText
        if (tvLoadingMsg != null) {
            tvLoadingMsg!!.text = this.loadingText
        }
    }

    /**
     * 顯示此視圖
     */
    fun show() {
        this.visibility = View.VISIBLE
    }

    /**
     * 隱藏此視圖
     */
    fun hide() {
        this.visibility = View.GONE
    }

    /**
     * 設(shè)置重新加載監(jiān)聽事件
     *
     * @param listener
     */
    fun setOnReloadListener(listener: OnReloadListener) {
        this.onReloadListener = listener
    }


    interface OnReloadListener {
        fun onReload()
    }

    companion object {
        const val TYPE_EMPTY = 0 // 頁面為空,沒有數(shù)據(jù)時展示
        const val TYPE_LOADING = 1 // 正在加載視圖
        const val TYPE_RELOAD = 2 // 加載失敗须眷,顯示重新加載視圖
    }

10竖瘾、ShapeImageView

package:cn.onestravel.library.kotlin.base.view

自定義矩形和圓形ImageView,實(shí)現(xiàn)帶邊框的圓角矩形ImageView或圓形ImageVIew

viewShape的值為:

說明
SHAPE_REC 矩形ImageView
SHAPE_CIRCLE 圓形ImageView
SHAPE_OVAL 橢圓ImageView
/**
 * 設(shè)置ImageView的形式花颗,圓角矩形捕传,圓形,或橢圓
 **/
var shape = SHAPE_REC: Int
        get() = shape
        set(shape) {
            this.shape = shape
            invalidate()
        }
/**
 * 設(shè)置ImageView邊框顏色
 **/
 var borderColor: Int
        get() = mBorderColor
        set(mBorderColor) {
            this.mBorderColor = mBorderColor
            mBorderPaint.color = mBorderColor
            invalidate()
        }
    /**
     * 設(shè)置ImageView的圓角
     **/
    var roundRadius: Float
        get() = mRoundRadius
        set(mRoundRadius) {
            this.mRoundRadius = mRoundRadius
            invalidate()
        }
    /**
     * 設(shè)置ImageView的邊框?qū)挾?     **/
    fun setBorderSize(mBorderSize: Int) {
        this.borderSize = mBorderSize.toFloat()
        mBorderPaint.strokeWidth = mBorderSize.toFloat()
        initRect()
        invalidate()
    }
    /**
     * 設(shè)置ImageView的圖片資源
     **/
override fun setImageResource(resId: Int) {
        super.setImageResource(resId)
        mBitmap = ImageUtils.getBitmapFromDrawable(drawable)
        setupBitmapShader()
    }
    /**
     * 設(shè)置ImageView的Drawable
     **/        
    override fun setImageDrawable(drawable: Drawable?) {
        super.setImageDrawable(drawable)
        mBitmap = ImageUtils.getBitmapFromDrawable(drawable)
        setupBitmapShader()
    }

    

二扩劝、采用RxJava+Retrofit架構(gòu)封裝的關(guān)于Http請求以及生命周期處理的文件介紹

1庸论、BaseRxActivity

package:cn.onestravel.library.kotlin.rxrequest.activity

繼承自BaseActivity 职辅,針對RxJava處理了相對應(yīng)的生命周期,同時擁有BaseActivity的所有特性聂示。

生命周期處理:

abstract class BaseRxActivity : BaseActivity(), LifecycleProvider<ActivityEvent> {
    private val lifecycleSubject:BehaviorSubject<ActivityEvent> = BehaviorSubject.create()

    @CheckResult
    override fun lifecycle(): Observable<ActivityEvent> {
        return lifecycleSubject.hide()
    }

    @CheckResult
    override fun <T> bindUntilEvent(event: ActivityEvent): LifecycleTransformer<T> {
        return RxLifecycle.bindUntilEvent(lifecycleSubject, event)
    }

    @CheckResult
    override fun <T> bindToLifecycle(): LifecycleTransformer<T> {
        return RxLifecycleAndroid.bindActivity(lifecycleSubject)
    }

    @CallSuper
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycleSubject.onNext(ActivityEvent.CREATE)
    }

    @CallSuper
    override fun onStart() {
        super.onStart()
        lifecycleSubject.onNext(ActivityEvent.START)
    }

    @CallSuper
    override fun onResume() {
        super.onResume()
        lifecycleSubject.onNext(ActivityEvent.RESUME)
    }

    @CallSuper
    override fun onPause() {
        lifecycleSubject.onNext(ActivityEvent.PAUSE)
        super.onPause()
    }

    @CallSuper
    override fun onStop() {
        lifecycleSubject.onNext(ActivityEvent.STOP)
        super.onStop()
    }

    @CallSuper
    override fun onDestroy() {
        lifecycleSubject.onNext(ActivityEvent.DESTROY)
        super.onDestroy()
    }
}

2域携、BaseRxListActivity

package:cn.onestravel.library.kotlin.rxrequest.activity

繼承自BaseListActivity ,針對RxJava處理了相對應(yīng)的生命周期催什,同時擁有BaseListActivity下拉刷新涵亏,上拉加載的所有特性。

3蒲凶、BaseRxFragment

package:cn.onestravel.library.kotlin.rxrequest.fragment

繼承自BaseFragment 气筋,針對RxJava處理了相對應(yīng)的生命周期,同時擁有BaseFragment的所有特性旋圆。

生命周期處理:

abstract class BaseRxFragment : BaseFragment(), LifecycleProvider<FragmentEvent> {
    private val lifecycleSubject:BehaviorSubject<FragmentEvent> = BehaviorSubject.create()

    override fun lifecycle(): Observable<FragmentEvent> {
        return lifecycleSubject.hide()
    }

    @CheckResult
    override fun <T> bindUntilEvent(event: FragmentEvent): LifecycleTransformer<T> {
        return RxLifecycle.bindUntilEvent(lifecycleSubject, event)
    }

    @CheckResult
    override fun <T> bindToLifecycle(): LifecycleTransformer<T> {
        return RxLifecycleAndroid.bindFragment(lifecycleSubject)
    }

    @CallSuper
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycleSubject.onNext(FragmentEvent.CREATE)
    }


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        lifecycleSubject.onNext(FragmentEvent.CREATE_VIEW)
        return super.onCreateView(inflater, container, savedInstanceState)
    }


    @CallSuper
    override fun onStart() {
        super.onStart()
        lifecycleSubject.onNext(FragmentEvent.START)
    }

    @CallSuper
    override fun onResume() {
        super.onResume()
        lifecycleSubject.onNext(FragmentEvent.RESUME)
    }

    @CallSuper
    override fun onPause() {
        lifecycleSubject.onNext(FragmentEvent.PAUSE)
        super.onPause()
    }

    @CallSuper
    override fun onStop() {
        lifecycleSubject.onNext(FragmentEvent.STOP)
        super.onStop()
    }

    override fun onDestroyView() {
        lifecycleSubject.onNext(FragmentEvent.DESTROY_VIEW)
        super.onDestroyView()
    }

    @CallSuper
    override fun onDestroy() {
        lifecycleSubject.onNext(FragmentEvent.DESTROY)
        super.onDestroy()
    }
}

4宠默、BaseRxListFragment

package:cn.onestravel.library.kotlin.rxrequest.fragment

繼承自BaseListFragment ,針對RxJava處理了相對應(yīng)的生命周期灵巧,同時擁有BaseListFragment下拉刷新搀矫,上拉加載的所有特性。

5刻肄、BaseObserver<T: ResponseResult>

package:cn.onestravel.library.kotlin.rxrequest.common

RxJava+Retrofit 請求的觀察者瓤球,返回特定數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù),并進(jìn)行相應(yīng)的處理敏弃。

具體實(shí)現(xiàn)如下:

/**
 * @name cn.onestravel.library.kotlin.rxrequest.common.BaseObserver
 * @description 請求返回結(jié)果卦羡,返回json數(shù)據(jù)必須符合 {"code":"0000","msg":""}
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
abstract class BaseObserver<T : ResponseResult> : Observer<T> {

    /**
     * 請求開始 處理基本的loading框的顯示等
     *
     * @param d
     */
    fun onStart(d: Disposable) {
        Log.e(
            TAG,
            "===========單個接口請求開始========="
        )
    }

    /**
     * 此方法必須實(shí)現(xiàn)
     *
     * @param result 請求成功的結(jié)果
     */
    abstract fun onSuccess(result: T)

    /**
     * 請求失敗
     *
     * @param code 錯誤碼
     * @param msg  錯誤提示語
     */
    fun onFailure(code: String, msg: String?) {
        Log.e(
            TAG,
            "接口請求失敗===code = " + code + "errorMsg =" + msg 
        )
    }

    /**
     * 請求都完成時之行此方法
     */
    fun onFinish() {

    }

    override fun onSubscribe(d: Disposable) {
        onStart(d)
    }

    override fun onNext(result: T) {
        if (BaseResponse.REQUEST_OK == result.code) {
            onSuccess(result)
            Log.i(TAG, "請求成功responseBody====" + JSON.toJSONString(result))
        } else {
            onFailure(result.code, result.msg)
        }

    }

    override fun onError(e: Throwable) {
        var errorMsg = ""
        var errorCode = 0
        if (e is HttpException) {
            val httpException = e as HttpException
            errorCode = httpException.response().code()
            if (404 == errorCode || 500 == errorCode) {
                errorMsg = "請求異常,請稍候重試麦到!"
            } else {

            }

        } else {
            //todo 設(shè)置固定的錯誤碼及錯誤提示
        }
        onFailure(errorCode.toString(), errorMsg)
    }

    override fun onComplete() {
        onFinish()
    }

    companion object {
        private val TAG = "request"
    }
}

BaseResponse:

/**
 * @name cn.onestravel.library.kotlin.rxrequest.common.BaseResponse
 * @description 請求返回結(jié)果數(shù)據(jù)基類
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
open class BaseResponse(val code: String = "0000", val msg: String = ""): Serializable {
    companion object {
        val REQUEST_OK = "0000"  //請求成功的code碼
        val REQUEST_ERROR = "-1" //請求失敗的code碼
    }
}

ResponseResult:

/**
 * @name cn.onestravel.library.kotlin.rxrequest.common.ResponseResult
 * @description 請求返回結(jié)果數(shù)據(jù) 符合 {"code":"0000","msg":"","data":{},"datas":[]} 的基類
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
class ResponseResult :BaseResponse(), Serializable

6绿饵、BaseObserver1<DATA: Serializable>

package:cn.onestravel.library.kotlin.rxrequest.common

RxJava+Retrofit 請求的觀察者,返回特定數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)瓶颠,并進(jìn)行相應(yīng)的處理拟赊。

具體實(shí)現(xiàn)如下:

/**
 * @name cn.onestravel.library.kotlin.rxrequest.common.BaseObserver
 * @description 請求返回結(jié)果,返回json數(shù)據(jù)必須符合  {"code":"0000","msg":"","data":{},"datas":[]},data 和 datas 的數(shù)據(jù) bean 相同
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
abstract class BaseObserver1<DATA : Serializable> : Observer<ResponseResult1<DATA>> {

    /**
     * 請求開始 處理基本的loading框的顯示等
     *
     * @param d
     */
    fun onStart(d: Disposable) {
        Log.e(
            TAG,
            "===========單個接口請求開始  =========="
        )
    }

    /**
     * 此方法必須實(shí)現(xiàn)
     *
     * @param result 請求成功的結(jié)果
     */
    abstract fun onSuccess(result: ResponseResult1<DATA>)

    /**
     * 請求失敗
     *
     * @param code 錯誤碼
     * @param msg  錯誤提示語
     */
    fun onFailure(code: String, msg: String?) {
        Log.e(
            TAG,
            "接口請求失敗============code = " + code + "errorMsg =" + msg    )
    }

    /**
     * 請求都完成時之行此方法
     */
    open fun onFinish() {

    }

    override fun onSubscribe(d: Disposable) {
        onStart(d)
    }

    override fun onNext(result: ResponseResult1<DATA>) {
        if (BaseResponse.REQUEST_OK == result.code) {
            onSuccess(result)
            Log.i(TAG, "請求成功responseBody====" + JSON.toJSONString(result))
        } else {
            onFailure(result.code, result.msg)
        }

    }

    override fun onError(e: Throwable) {
        var errorMsg = ""
        var errorCode = 0
        if (e is HttpException) {
            val httpException = e as HttpException
            errorCode = httpException.response().code()
            if (404 == errorCode || 500 == errorCode) {
                errorMsg = "請求異常粹淋,請稍候重試吸祟!"
            } else {

            }

        } else {
            //todo 設(shè)置固定的錯誤碼及錯誤提示
        }
        onFailure(errorCode.toString(), errorMsg)
    }

    override fun onComplete() {
        onFinish()
    }

    companion object {
        private val TAG = "request"
    }
}

ResponseResult1:

/**
 * @name cn.onestravel.library.kotlin.rxrequest.common.ResponseResult
 * @description 請求返回結(jié)果數(shù)據(jù) 符合 {"code":"0000","msg":"","data":{},"datas":[]} 的基類
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
class ResponseResult1<DATA:Serializable>(
    val data: DATA?,
    val datas: MutableList<DATA>? = ArrayList()
) :BaseResponse(), Serializable


7、BaseObserver2<DATA : Serializable,ITEM:Serializable>

package:cn.onestravel.library.kotlin.rxrequest.common

RxJava+Retrofit 請求的觀察者廓啊,返回特定數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)欢搜,并進(jìn)行相應(yīng)的處理。

具體實(shí)現(xiàn)如下:

package cn.onestravel.library.kotlin.rxrequest.common

import android.util.Log
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import retrofit2.HttpException
import java.io.Serializable

/**
 * @name cn.onestravel.library.kotlin.rxrequest.common.BaseObserver2
 * @description 請求返回結(jié)果谴轮,返回json數(shù)據(jù)必須符合 {"code":"0000","msg":"","data":{},"datas":[]},data 和 datas 的數(shù)據(jù) bean 可以不相同
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
abstract class BaseObserver2<DATA : Serializable,ITEM:Serializable> : Observer<ResponseResult2<DATA,ITEM>>, ObserverResult<ResponseResult2<DATA,ITEM>> {
    /**
     * 請求開始 處理基本的loading框的顯示等
     *
     * @param d
     */
    override fun onStart(d: Disposable) {
        Log.e(
             BaseObserver2.TAG,
            "===========單個接口請求開始  =========="
        )
    }

    /**
     * 此方法必須實(shí)現(xiàn)
     *
     * @param result 請求成功的結(jié)果
     */
    abstract override fun onSuccess(result: ResponseResult2<DATA, ITEM>)

    /**
     * 請求失敗
     *
     * @param code 錯誤碼
     * @param msg  錯誤提示語
     */
    override fun onFailure(code: String, msg: String?) {
        Log.e(
             BaseObserver2.TAG,
            "接口請求失敗============code = " + code + "errorMsg =" + msg    )
    }

    /**
     * 請求都完成時之行此方法
     */
    override fun onFinish() {

    }

    override fun onSubscribe(d: Disposable) {
        onStart(d)
    }
    override fun onNext(baseObject: ResponseResult2<DATA,ITEM>) {
        //        Log.i("responseBody====",)
        if (BaseResponse.REQUEST_OK == baseObject.code) {
            onSuccess(baseObject)
        } else {
            onFailure(baseObject.code, baseObject.msg)
        }
    }

    /**
     *
     */
    override fun onError(e: Throwable) {
        var errorMsg = ""
        var errorCode = 0
        if (e is HttpException) {
            val httpException = e as HttpException
            errorCode = httpException.response().code()
            if (404 == errorCode || 500 == errorCode) {
                errorMsg = "請求異常,請稍候重試吹埠!"
            } else {

            }

        } else {
            //todo 設(shè)置固定的錯誤碼及錯誤提示
        }
        onFailure(errorCode.toString(), errorMsg)
    }

    override fun onComplete() {
        onFinish()
    }

    companion object {
        private val TAG = "RequestBaseObserver2"
    }
}

ResponseResult2:

/**
 * @name cn.onestravel.library.kotlin.rxrequest.common.ResponseResult
 * @description 請求返回結(jié)果數(shù)據(jù) 符合 {"code":"0000","msg":"","data":{},"datas":[]} 的基類
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
class ResponseResult2<DATA:Serializable,ITEM:Serializable>(
    val data: DATA?,
    val datas: MutableList<ITEM>? = ArrayList()
) :BaseResponse(), Serializable


8第步、BaseLoader

package:cn.onestravel.library.kotlin.rxrequest.loader

公共的Loader疮装,處理observe針對請求進(jìn)行線程切換

abstract class BaseLoader<S : BaseService> {
    protected val mServiceManager: RetrofitServiceManager by lazy { RetrofitServiceManager.INSTANCE }
    protected val mService: S by lazy { createService() }

    /**
     * 創(chuàng)建 Service 實(shí)例
     */
    abstract fun createService(): S

    /**
     * 設(shè)置Observable的工作線程
     * @param observable
     * @param <T>
     * @return
    </T> */
    fun <T> observe(observable: Observable<T>): Observable<T> {
        return observable.subscribeOn(Schedulers.io())
            .unsubscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
    }


}

9、BaseService

package:cn.onestravel.library.kotlin.rxrequest.service

所有 Retrofit 請求的 Service 的接口基類粘都,目前只用于規(guī)范子類廓推,可聲明對應(yīng)公用方法

10、RetrofitServiceManager

package:cn.onestravel.library.kotlin.rxrequest.service

生成接口service實(shí)例的管理類翩隧,初始化Retrofit 實(shí)例樊展,設(shè)置請求相關(guān)的一些攔截器、超時時間等配置堆生,定義Http請求的公共URL

/**
 * @name cn.onestravel.library.kotlin.rxrequest.service.RetrofitServiceManager
 * @description 生成接口實(shí)例的管理類
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
class RetrofitServiceManager private constructor() {
    private val mRetrofit: Retrofit
    init {
        val interceptorBuild = HttpCommonInterceptor.Builder()
     
        val logging = HttpLoggingInterceptor()
        logging.level = HttpLoggingInterceptor.Level.BODY
        val okHttpClientBuild = OkHttpClient.Builder()
        okHttpClientBuild.connectTimeout(CONNECTION_TIMEOUT.toLong(), TimeUnit.SECONDS)
            .readTimeout(READ_TIMEOUT.toLong(), TimeUnit.SECONDS)
            .writeTimeout(WRITE_TIMEOUT.toLong(), TimeUnit.SECONDS)
            .addInterceptor(interceptorBuild.build())//攔截器添加公共請求參數(shù)
            .addInterceptor(RetryInterceptor(2))//重試三次的攔截
                        .addInterceptor(logging)//請求日志打印

        //初始化Retrofit
        mRetrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(okHttpClientBuild.build())
            .build()

    }



    /**
     * 生成對應(yīng)接口的實(shí)例
     *
     * @param service
     * @param <T>
     * @return
    </T> */
    fun <T:BaseService> create(service: Class<T>): T {
        return mRetrofit.create(service)

    }

    companion object {
        val INSTANCE by lazy { RetrofitServiceManager() }
        private const val CONNECTION_TIMEOUT = 5
        private const val READ_TIMEOUT = 20
        private const val WRITE_TIMEOUT = 10
        private const val BASE_URL = "http://192.168.1.12:9090/"
    }
}

三专缠、采用Mvp架構(gòu)封裝的文件介紹

1、BaseMvpActivity<V : BaseMvpView, P : BaseMvpPresenter<V>>

package:cn.onestravel.library.kotlin.mvp.activity

所有Mvp架構(gòu)的 Activity 的基類,自BaseActivity 淑仆,擁有BaseActivity的所有特性,處理了P層的相關(guān)生命周期涝婉。

/**
 * @name  BaseMvpActivity
 * @description 所有Mvp架構(gòu)的 Activity 的基類
 * @createTime 2018/12/12 17:00
 * @author onestravel
 * @version 1.0.0
 */
abstract class BaseMvpActivity<V : BaseMvpView, P : BaseMvpPresenter<V>> : BaseActivity(), BaseMvpView {
    private val presenter by lazy { createPresenter() }
    private var mLoadingDialog: LoadingDialog? = null
    protected abstract fun createPresenter(): P

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (presenter == null) {
            throw  NullPointerException("Presenter is null! Do you return null in createPresenter()?")
        }
        presenter.onMvpAttachView(this as V, savedInstanceState)
    }


    override fun onStart() {
        super.onStart()
        presenter.let {
            it.onMvpStart()
        }
    }

    override fun onResume() {
        super.onResume()
        presenter.let {
            it.onMvpResume()
        }
    }

    override fun onPause() {
        presenter.let {
            it.onMvpPause()
        }
        super.onPause()
    }

    override fun onStop() {
        presenter.let {
            it.onMvpStop()
        }
        super.onStop()
    }


    override fun onSaveInstanceState(outState: Bundle?) {
        super.onSaveInstanceState(outState)
        presenter?.let {
            it.onMvpSaveInstanceState(outState)
        }
    }

    override fun onDestroy() {
        presenter?.let {
            it.onMvpDetachView(false)
            it.onMvpDestroy()
        }
        mLoadingDialog?.let {
            it.destroy()
            mLoadingDialog = null
        }
        super.onDestroy()
    }

    override fun showLoading(content: String?) {
        if (mLoadingDialog == null) {
            mLoadingDialog = LoadingDialog.getInstance(this)
            mLoadingDialog!!.title = content?:"正在加載..."
            if (!mLoadingDialog!!.isShowing) {
                mLoadingDialog!!.show()
            }
        }
    }

    override fun hideLoading() {
        mLoadingDialog?.let {
            mLoadingDialog!!.dismiss()
        }
    }

    override fun onResponseError(msg: String?) {
        msg?.let {
            showToast(msg)
        }
    }

}

2、BaseMvpListActivity<V : BaseMvpView, P : BaseMvpPresenter<V>>

package:cn.onestravel.library.kotlin.mvp.activity

所有Mvp架構(gòu)的 ListActivity 的基類,自BaseListActivity 蔗怠,擁有BaseListActivity的所有特性墩弯,并且處理了P層的相關(guān)生命周期。

3寞射、BaseRxMvpActivity<V : BaseMvpView, P : BaseMvpPresenter<V>>

package:cn.onestravel.library.kotlin.mvp.activity

所有Mvp架構(gòu)的 采用RxJava+Retrofit 請求的Activity 的基類渔工,繼承自BaseRxActivity ,擁有BaseRxActivity的所有特性桥温,并且處理了P層的相關(guān)生命周期引矩。

4、BaseRxMvpListActivity<V : BaseMvpView, P : BaseMvpPresenter<V>>

package:cn.onestravel.library.kotlin.mvp.activity

所有Mvp架構(gòu)的 采用RxJava+Retrofit 請求的帶有列表的Activity策治,繼承自BaseRxListActivity 脓魏,擁有BaseRxListActivity的所有特性,并且處理了P層的相關(guān)生命周期通惫。

5茂翔、Fragment 有與前4個Activity功能相同F(xiàn)ragment,就不多做介紹了履腋。

package:cn.onestravel.library.kotlin.mvp.fragment

6珊燎、BaseMvpModel

package:cn.onestravel.library.kotlin.mvp.model

Mvp模式中所有Model層的基類,是一個接口遵湖,可以聲明共同的方法悔政,交由子類去實(shí)現(xiàn)。

7延旧、BaseMvpPresenter

package:cn.onestravel.library.kotlin.mvp.presenter

Mvp模式中所有presenter層的基類谋国,是一個接口,聲明了presenter層相關(guān)的生命周期方法迁沫,由子類去實(shí)現(xiàn)芦瘾。

/**
 * @name  BaseMvpPresenterImpl
 * @description 所有界面presenter的接口類
 * @createTime 2018/12/12 16:27
 * @author onestravel
 * @version 1.0.0
 */

interface BaseMvpPresenter<in V : BaseMvpView> {
    fun onMvpAttachView(view: V, savedInstanceState: Bundle?)

    fun onMvpStart()

    fun onMvpResume()

    fun onMvpPause()

    fun onMvpStop()

    fun onMvpSaveInstanceState(savedInstanceState: Bundle?)

    fun onMvpDetachView(retainInstance: Boolean)

    fun onMvpDestroy()

}

8捌蚊、BaseMvpPresenterImpl<V: BaseMvpView>

package:cn.onestravel.library.kotlin.mvp.presenter.impl

Mvp模式中所有presenter層的接口的實(shí)現(xiàn)類,對presenter層相關(guān)的生命周期方法進(jìn)行實(shí)現(xiàn)近弟;并且實(shí)現(xiàn)與View層的綁定缅糟,持有View層的引用。

/**
 * @name  BaseMvpPresenterImpl
 * @description 所有界面presenter的接口類
 * @createTime 2018/12/12 16:27
 * @author onestravel
 * @version 1.0.0
 */

interface BaseMvpPresenter<in V : BaseMvpView> {
    fun onMvpAttachView(view: V, savedInstanceState: Bundle?)

    fun onMvpStart()

    fun onMvpResume()

    fun onMvpPause()

    fun onMvpStop()

    fun onMvpSaveInstanceState(savedInstanceState: Bundle?)

    fun onMvpDetachView(retainInstance: Boolean)

    fun onMvpDestroy()

}

9祷愉、BaseMvpView

package:cn.onestravel.library.kotlin.mvp.view

Mvp模式中所有View層的接口類窗宦,聲明了一些View層常用的加載進(jìn)度顯示與隱藏,請求失敗提示等公用的方法二鳄。

/**
 * @name  BaseMvpPresenterImpl
 * @description 所有界面presenter的接口類
 * @createTime 2018/12/12 16:27
 * @author onestravel
 * @version 1.0.0
 */

interface BaseMvpPresenter<in V : BaseMvpView> {
    fun onMvpAttachView(view: V, savedInstanceState: Bundle?)

    fun onMvpStart()

    fun onMvpResume()

    fun onMvpPause()

    fun onMvpStop()

    fun onMvpSaveInstanceState(savedInstanceState: Bundle?)

    fun onMvpDetachView(retainInstance: Boolean)

    fun onMvpDestroy()

}

聲明:

針對Kotlin項(xiàng)目的一些常用封裝赴涵,到這里就介紹完了,后面還會增加MVVM模式的一些封裝泥从,敬請期待>湔肌!

在封裝或者介紹過程中躯嫉,如有什么不正確或者不明白的地方纱烘,期待與您進(jìn)行交流,共同提高祈餐!

聯(lián)系郵件:server@onestravel.cn

鳴謝@奚丁!帆阳!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哺壶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜒谤,更是在濱河造成了極大的恐慌山宾,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳍徽,死亡現(xiàn)場離奇詭異资锰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)阶祭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門绷杜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人濒募,你說我怎么就攤上這事鞭盟。” “怎么了瑰剃?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵齿诉,是天一觀的道長。 經(jīng)常有香客問我,道長鹃两,這世上最難降的妖魔是什么遗座? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任舀凛,我火速辦了婚禮俊扳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猛遍。我一直安慰自己馋记,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布懊烤。 她就那樣靜靜地躺著梯醒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪腌紧。 梳的紋絲不亂的頭發(fā)上茸习,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機(jī)與錄音壁肋,去河邊找鬼号胚。 笑死,一個胖子當(dāng)著我的面吹牛浸遗,可吹牛的內(nèi)容都是我干的猫胁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼跛锌,長吁一口氣:“原來是場噩夢啊……” “哼弃秆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起髓帽,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤菠赚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后郑藏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衡查,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年译秦,在試婚紗的時候發(fā)現(xiàn)自己被綠了峡捡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡筑悴,死狀恐怖们拙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阁吝,我是刑警寧澤砚婆,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響装盯,放射性物質(zhì)發(fā)生泄漏坷虑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一埂奈、第九天 我趴在偏房一處隱蔽的房頂上張望迄损。 院中可真熱鬧,春花似錦账磺、人聲如沸芹敌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氏捞。三九已至,卻和暖如春冒版,著一層夾襖步出監(jiān)牢的瞬間液茎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工辞嗡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捆等,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓欲间,卻偏偏與公主長得像楚里,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子猎贴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容