前言
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的封装,欲知后事如何,请听下回分解......
网友评论