轻松打造Kotlin MVVM框架

kotlin 被宣布成为Google Android开发的官方语言之一的时间已经过去一段时间了,作者将kotlin打造的mvvm的架构完美兼容到之前的项目中,并且使用的非常爽。中间踩过一些坑,也折腾了一段的时间,现在来讲讲是怎么操作的。

准备工作

1、Android Studio2.3.3
2、添加kotlin插件 : setting->plugin->search kotlin , install
3、添加依赖
build.gradle

ext.kotlin_version = '1.1.2-5'
·classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

app.gradle

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

----- 添加databinding 支持(放在android下)
 dataBinding {
        enabled = true
    }

-----  解决databinding 和kotlin的冲突 支持(放在根下)
kapt {
    generateStubs = true
}

----依赖
    compile 'org.jetbrains.kotlin:kotlin-stdlib:1.1.2-5'
    kapt 'com.android.databinding:compiler:2.3.3'//解决databinding 和kotlin的冲突 支持

// retfofit
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
//添加rxjava 依赖 根据自己的版本处理 
我使用的是1.0+版本

4、分包
···
-base
-view
-modle
-viewmodle
-serviceapi
···

打造BaseView

BaseActivity.kt

abstract class BaseAct> : AppCompatActivity() {

    protected lateinit var b: B
    protected lateinit var viewModle: V


    override fun onCreate(savedInstanceState: android.os.Bundle?) {
        super.onCreate(savedInstanceState)

        b = android.databinding.DataBindingUtil.setContentView(this, getLayoutResource())
        viewModle = TUtil.getT(this, 1)!!;
        viewModle.init(this, b, this.baseContext)
    }


    inline fun  Activity.gotoActivity() {
        val intent = Intent(this, T::class.java)
        this.startActivity(intent)
    }


    /**
     * 是否支持滑动返回

     * @return
     */
    protected fun supportSlideBack(): Boolean {
        return true
    }


    private var mSwipeWindowHelper: SwipeWindowHelper? = null

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        if (!supportSlideBack()) {
            return super.dispatchTouchEvent(ev)
        }

        if (mSwipeWindowHelper == null) {
            mSwipeWindowHelper = SwipeWindowHelper(window)
        }
        try {
            return mSwipeWindowHelper!!.processTouchEvent(ev) || super.dispatchTouchEvent(ev)
        } catch (_e: Exception) {
            _e.printStackTrace()
        }

        return false
    }


    /**
     * menu 点击事件
     */
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home// 点击返回图标事件
            -> onBackPressed()
            else -> menuItemSelected(item)
        }
        return super.onOptionsItemSelected(item)
    }


    fun menuItemSelected(item: MenuItem) {
    }

    protected abstract fun getLayoutResource(): Int

    override fun onResume() {
        super.onResume()
        android.util.Log.v(tag(), tag() + "::onResume()")
        viewModle.onResume()
    }

    private fun tag(): String? {
        return this.localClassName
    }

    override fun onPause() {
        super.onPause()
        viewModle.onPause()
        android.util.Log.v(tag(), tag() + "::onPause()")
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        viewModle.onActivityResult(requestCode, resultCode, data)
    }


    override fun onDestroy() {
        android.util.Log.v(tag(), tag() + "::onDestory()")
        super.onDestroy()
        viewModle.onDestory()
    }

}

BaseFragment.kt

abstract class BaseFrag> : Fragment(), java.io.Serializable {

    override fun onCreateView(inflater: android.view.LayoutInflater?, container: android.view.ViewGroup?, savedInstanceState: android.os.Bundle?): android.view.View? {
        return inflater!!.inflate(getLayoutResource(), container, false)
    }

    protected abstract fun getLayoutResource(): Int
    protected lateinit var viewModle: V
    protected lateinit var b: B
    override fun onViewCreated(view: android.view.View?, savedInstanceState: android.os.Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        b = android.databinding.DataBindingUtil.bind(view)
        viewModle = TUtil.getT(this, 1)!!;
        viewModle.init(activity as AppCompatActivity, b, context)
        initView()
    }

    abstract fun initView()




    inline fun  Activity.gotoActivity() {
        val intent = Intent(this, T::class.java)
        activity.startActivity(intent)
    }

    private fun tag(): String? {
        return this.javaClass.simpleName
    }


    protected fun toast(text: String) {
        android.widget.Toast.makeText(context, text, android.widget.Toast.LENGTH_SHORT).show()
    }


    override fun onResume() {
        super.onResume()
        viewModle.onResume()
    }

    override fun onDestroy() {
        super.onDestroy()
        viewModle.onDestory()
    }

    override fun onPause() {
        super.onPause()
        viewModle.onPause()
    }


}

BaseViewModle.kt

abstract class BaseViewModle : ViewModleRecycle {
    protected lateinit var b: B
    protected lateinit var act: AppCompatActivity
    protected lateinit var context: Context


    companion object {

    }

    protected fun toast(text: String) {
        Toast.makeText(context, text, Toast.LENGTH_SHORT).show()
    }

    fun initToolBar(toolbar: Toolbar, title: String) {
        toolbar.setTitle(title)
        toolbar.setTitleTextColor(context.resources.getColor(R.color.colorAccent))
        act.setSupportActionBar(toolbar)
        act.supportActionBar!!.setDisplayHomeAsUpEnabled(false)
    }


    fun init(act: AppCompatActivity, b: B, c: Context) {
        this.b = b
        this.act = act
        context = c
        initUI()
        initNet()
    }

    inline fun  Activity.gotoActivity() {
        var intent = Intent(this, T::class.java)
        act.startActivity(intent)
    }


    abstract fun initUI()
    abstract fun initNet()


    fun clear() {

    }

    override fun onResume() {

    }

    override fun onPause() {

    }

    override fun onDestory() {

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

    }

}

搞定!!!

使用

  • 干货的来源api

view

class GirlsFragment : BaseFrag() {
    override fun initView() {
        initToolBar(b!!.toobar, "妹纸")
    }

    companion object {
        fun newInstance(): GirlsFragment {
            val fragment = GirlsFragment()
            return fragment
        }
    }

    override fun getLayoutResource(): Int {
        return R.layout.fragment_girls
    }


}

viewmodle


/**
 * Created by apanda on 2017/6/13.
 */
class GrilsViewModle : BaseViewModle(), BaseBindingItemPresenter {
    public override fun onItemClick(position: Int, itemData: Result) {
        toast("itemClicked")
    }


    private var adapter: SingleTypeBindingAdapter? = null
    override fun initUI() {
        adapter = SingleTypeBindingAdapter(context, null, R.layout.item_girls)
        adapter!!.setItemPresenter(this)
        b!!.recylerview.adapter = adapter
        b!!.recylerview.layoutManager = GridLayoutManager(context, 2)
    }


    override fun initNet() {
        val api = Service.Factory.create()
        api.getData("福利", 20, 1)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe({ result ->
                    adapter!!.refresh(result.results)
                }, { _ ->
                })
    }
}

api

interface Service {
    @GET("api/data/{type}/{pageSize}/{pageNumber}")
    fun getData(@Path("type") type: String,
                @Path("pageSize") pageSize: Int,
                @Path("pageNumber") pageNumber: Int): Observable>>


    companion object Factory {
        fun create(): Service {

            val logging = HttpLoggingInterceptor()
            logging.level = HttpLoggingInterceptor.Level.BASIC
            val client = OkHttpClient.Builder()
                    .addInterceptor(logging)
                    .build()

            val retrofit = Retrofit
                    .Builder()
                    .client(client)
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl("http://gank.io/")
                    .build()

            return retrofit.create(Service::class.java)
        }
    }

}

下篇文章将会使用该框架实现 钉钉在聊天框 粘贴html地址,实现内容预览的功能。
另外自己使用的框架中还实现了一个上下拉刷新加载的BaseViewLoadingDataModle,有需要的童鞋,可以跟我交流。

项目地址: http://git.oschina.net/apandas/kotlinframe

Copyright (c) 2017 Copyright Holder All Rights Reserved.
原创文章,转载需说明出处,版权归作者所有。

你可能感兴趣的:(轻松打造Kotlin MVVM框架)