Kotlin如何實現MVP架構
最近MVP火的不要不要的,我也來湊盤熱鬧,其實MVP的文章看了好多了,但是一直還停留在概念階段,這幾天對Google Android的todoapp的程式碼進行了解析,然後使用Kotlin翻譯了一下,算了對MVP有了一個大概的認識,那麼MVP究竟是什麼,網上一搜一大堆,我就把名字複述一下,MVP的全稱為Model-View-Presenter,即模型-檢視-協調器(主持者),最重要的功能還是解耦,程式碼也更容易擴充套件和維護,下面我們還是來看具體的例子:demo還是做一個乾貨的列表頁:
先看目錄結構,
Paste_Image.png
這裡單獨建了個MVP的包,base中定義了兩個介面BaseView和BasePresenter
BaseView
package com.vslimit.kotlindemo.mvp.base /** * Created by vslimit on 17/1/6. */ interface BaseView{ fun setPresenter(presenter: T) }
BasePresenter
package com.vslimit.kotlindemo.mvp.base /** * Created by vslimit on 17/1/6. */ interface BasePresenter { fun start() }
實現Contract
GanksContract
package com.vslimit.kotlindemo.mvp.ganks import com.vslimit.kotlindemo.model.Gank import com.vslimit.kotlindemo.mvp.base.BasePresenter import com.vslimit.kotlindemo.mvp.base.BaseView /** * Created by vslimit on 17/1/10. */ interface GanksContract { interface View : BaseView{ fun showGanks(ganks: List ) fun showTip(message:String) fun showLoading() fun hideLoading() } interface Presenter : BasePresenter { fun loadGanks() } }
介面中定義了需要實現想要展示的View,而Presenter處理互動,下面我們來看具體的實現類:
GanksPresenter
package com.vslimit.kotlindemo.mvp.ganks import com.vslimit.kotlindemo.model.Gank import com.vslimit.kotlindemo.model.GankListResult import com.vslimit.kotlindemo.service.RestfulService import com.vslimit.kotlindemo.service.ServiceFactory import rx.Subscriber import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers /** * Created by vslimit on 17/1/11. */ class GanksPresenter : GanksContract.Presenter { var mGanksView: GanksContract.View? = null constructor(ganksView: GanksContract.View) { mGanksView = checkNotNull(ganksView) mGanksView!!.setPresenter(this) } override fun loadGanks() { mGanksView!!.showLoading() val service = ServiceFactory.createRetrofitService(RestfulService::class.java, RestfulService.GANK_SERVICE_ENDPOINT) service.loadGanks().subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : Subscriber() { override fun onCompleted() { mGanksView!!.hideLoading() } override fun onError(e: Throwable) { mGanksView!!.showTip(e.toString()) } override fun onNext(result: GankListResult) { processGanks(result.results) } }) } override fun start() { loadGanks() } fun processGanks(ganks: List ) { mGanksView!!.showGanks(ganks) } }
這裡只實現了一個互動,即從服務端獲取ganks資料,獲取資料的實現請參考之前的文章,既然資料OK了,那我們就來看看View是如何展示的:
GanksFragment
package com.vslimit.kotlindemo.mvp.ganks import android.os.Bundle import android.support.v7.widget.LinearLayoutManager import android.view.View import com.vslimit.kotlindemo.R import com.vslimit.kotlindemo.adapter.BaseAdapter import com.vslimit.kotlindemo.extensions.loading import com.vslimit.kotlindemo.fragment.BaseFragment import com.vslimit.kotlindemo.model.Gank import com.vslimit.kotlindemo.util.Const import kotlinx.android.synthetic.main.fragment_ganks.* import kotlinx.android.synthetic.main.item_list_gank.view.* import org.jetbrains.anko.info import org.jetbrains.anko.onClick import org.jetbrains.anko.support.v4.act import org.jetbrains.anko.support.v4.toast /** * Created by vslimit on 17/1/10. */ class GanksFragment : BaseFragment(), GanksContract.View { override val layoutResourceId: Int = R.layout.fragment_ganks var mPresenter: GanksContract.Presenter? = null var adapter: BaseAdapter? = null companion object { fun getInstance(): GanksFragment { return GanksFragment() } } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val layoutManager: LinearLayoutManager = LinearLayoutManager(act) gankListRv.layoutManager = layoutManager adapter = BaseAdapter(R.layout.item_list_gank, arrayListOf()) { view: View, item: Gank -> view.item_gank_title.text = item.desc view.item_gank_who.text = item.who view.item_gank_date.text = item.publishedAt view.onClick { showTip("") } } gankListRv.adapter = adapter } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } override fun hideLoading() { loading(Const.HIDE) } override fun showLoading() { loading(Const.SHOW) } override fun showTip(message: String) { toast(message) } override fun setPresenter(presenter: GanksContract.Presenter) { mPresenter = checkNotNull(presenter) info("demo") } override fun onResume() { super.onResume() mPresenter?.start() } override fun showGanks(ganks: List ) { adapter!!.items = ganks adapter!!.notifyDataSetChanged() } }
在這個fragment同樣使用了之前文章封裝的通用RecycleView.Adapter,有興趣的朋友可以回頭看看之前的文章,最後我們來看看Activity都實現了什麼:
GanksActivity
package com.vslimit.kotlindemo.mvp.ganks import android.os.Bundle import android.support.design.widget.NavigationView import android.support.v4.view.GravityCompat import android.support.v4.widget.DrawerLayout import android.view.MenuItem import com.vslimit.kotlindemo.R import com.vslimit.kotlindemo.activity.BaseActivity import com.vslimit.kotlindemo.ui.DrawerLayoutManager import org.jetbrains.anko.find /** * Created by vslimit on 17/1/10. */ class GanksActivity(override val layoutResourceId: Int = R.layout.activity_tasks) :BaseActivity(),DrawerLayoutManager{ override val drawerLayout by lazy { find(R.id.drawer_layout) } val navigationView by lazy { find (R.id.nav_view) } var mGanksPresenter: GanksPresenter? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setupDrawerContent(navigationView, R.id.drawLayoutTask) val ganksFragment = GanksFragment.getInstance() if (savedInstanceState == null) { initFragment(ganksFragment) } mGanksPresenter = GanksPresenter(ganksFragment) } override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { android.R.id.home -> { drawerLayout.openDrawer(GravityCompat.START) return true } } return super.onOptionsItemSelected(item) } }
至此,基於Kotlin的MVP已經實現,從程式碼中不難看出,model與view實現瞭解耦,那麼問題來了,是不是MVP適用於所有場景,就我個人的感覺,如果頁面UI設計複雜,互動多,那應該使用MVP,這樣,能達到解耦的目的和效果,並且便於以後的維護和擴充套件,但是,如果只是單一的互動,比如登入或者像本文的只是個列表展示或詳情,那就直接用Activity和Fragment即可,畢竟殺雞用牛刀確實有點小題大做的感覺;至於說專案中究竟用MVC還是MVP要看具體場景以及個人喜好。
哦,對了,效果圖(懶得截圖,就使用之前的了,不過點選按鈕在側滑選單中,列表效果是一樣的):
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/964/viewspace-2813741/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android應用架構之MVP實現Android應用架構MVP
- 帶你動手實現 MVP+Clean架構!MVP架構
- MVP+Dagger2設計,MVP架構模式實現新思路 (Demo)MVP架構模式
- Java轉Kotlin MVP架構的一點小問題JavaKotlinMVP架構
- Android架構系列-MVP架構的實際應用Android架構MVP
- Android MVP 架構AndroidMVP架構
- 如何實現彈性架構架構
- Android-MVP架構AndroidMVP架構
- MVP應用架構模式MVP應用架構模式
- MVP架構設計 初探MVP架構
- Android MVP架構改造~如何重用頂層業務AndroidMVP架構
- iOS開發-MVP架構模式iOSMVP架構模式
- 唯品會架構師是如何實現架構重構的架構
- iOS 架構模式–解密 MVC,MVP,MVVM以及VIPER架構iOS架構模式解密MVCMVPMVVM
- 轉享:表現層架構模式比較:MVP(SC),MVP(PV),PM,MVVM 和 MVC架構模式MVPMVVMMVC
- 【Android】Dagger2實現更為規範化的MVP架構AndroidMVP架構
- 【譯】使用Kotlin和RxJava測試MVP架構的完整示例 – 第2部分KotlinRxJavaMVP架構
- 【譯】使用Kotlin和RxJava測試MVP架構的完整示例 - 第3部分KotlinRxJavaMVP架構
- 【譯】使用Kotlin和RxJava測試MVP架構的完整示例 - 第2部分KotlinRxJavaMVP架構
- 【譯】使用Kotlin和RxJava測試MVP架構的完整示例 - 第1部分KotlinRxJavaMVP架構
- MVP:有呼吸的Android架構MVPAndroid架構
- MVP那些事兒 (2) 初探MVC架構MVPMVC架構
- Android架構系列-基於MVP建立適合自己的架構Android架構MVP
- Android MVP架構從入門到精通-真槍實彈AndroidMVP架構
- iOS MVC、MVVM、MVP架構模式淺淺析iOSMVCMVVMMVP架構模式
- iOS架構淺談從 MVC、MVP 到 MVVMiOS架構MVCMVPMVVM
- 看完不會寫MVP架構我跪搓板MVP架構
- Android 架構選型 (MVP+DataBinding)Android架構MVP
- 架構設計的歷史·MVC·MVP·MVVM架構MVCMVPMVVM
- 開源專案Philm的MVP架構分析MVP架構
- TencentHub的架構實現架構
- iOS MVP模式重構實踐iOSMVP模式
- 79、概述struts,以及struts如何實現MVC架構的?MVC架構
- 如何在SSR架構中實現離線可用?(一)架構
- ASP.NET安全架構--如何實現.NET安全ASP.NET架構
- MVP+Kotlin原始碼體驗MVPKotlin原始碼
- 關於MVP分層架構在專案中的實際運用MVP架構
- [譯]iOS架構模式——解密MVC、MVP、MVVM和VIPERiOS架構模式解密MVCMVPMVVM