【架構(gòu)篇2】關(guān)于MVVM的思考

前言
Google為了提高大家應(yīng)用開發(fā)的效率和規(guī)范性,也是操碎了心寇漫,為了大家構(gòu)建強大而優(yōu)質(zhì)的應(yīng)用玛迄,提出了官方應(yīng)用架構(gòu)指南乙墙。

架構(gòu)要遵循最重要的指南是分離關(guān)注點际看。

寫在前面的話
關(guān)于應(yīng)用架構(gòu),大家用的比較多的是MVVM架構(gòu)盖高。MVVM模式都快要淘汰了慎陵,還沒有系統(tǒng)地思考過眼虱。隨著年紀(jì)越來越大,記東西變得越來越難席纽,為了記住MVVM模式捏悬,故寫下這篇思考,便于以后忘記的時候拿出來再次閱讀润梯。

1 概述

MVVMModel–view–viewmodel)是一種軟件架構(gòu)模式

MVVM有助于將圖形用戶界面的開發(fā)與業(yè)務(wù)邏輯的開發(fā)分離開來过牙,這是通過置標(biāo)語言或GUI代碼實現(xiàn)的。MVVM的視圖模型是一個值轉(zhuǎn)換器纺铭, 這意味著視圖模型負(fù)責(zé)從模型中暴露(轉(zhuǎn)換)數(shù)據(jù)對象寇钉,以便輕松管理和呈現(xiàn)對象。在這方面舶赔,視圖模型比視圖做得更多扫倡,并且處理大部分視圖的顯示邏輯。視圖模型可以實現(xiàn)中介者模式竟纳,組織對視圖所支持的用例集的后端邏輯的訪問撵溃。

Talk is cheap, show me the code

1.1 Model層

  • 從webservice獲取數(shù)據(jù)
interface WebService {
   
    @GET("/personal")
    fun getRecommendWallpapers(@QueryMap param: QueryParam): Single<BaseResult<ImageSetObj>>
}
object WebServiceFactory {

    fun <T> createService(env: ServerEnv, serviceClass: Class<T>): T {
        
        val client = OkHttpClient.Builder()
            .addInterceptor(HttpLoggingInterceptor(logger).apply { level = HttpLoggingInterceptor.Level.BODY })
            .hostnameVerifier { _, _ ->
                true
            }.build()

        val retrofit: Retrofit = Retrofit.Builder()
            .baseUrl(env.baseUl)
            .addConverterFactory(PbConvertFactory.create())
            .client(client)
            .build()

        return retrofit.create(serviceClass)
    }
}
//從數(shù)據(jù)庫獲取
class ListRepo {
    suspend fun queryVipGroup(): Int {
        return withContext(Dispatchers.IO) {
            ContactsLogUtils.d(TAG, "queryVipGroup")
            val context = Application.getApplication()
            //耗時操作返回的結(jié)果
            return@withContext 0
        }
    }

    suspend fun queryGroups(): List<ListItem>? {
        return withContext(Dispatchers.IO) {
            val context = Application.getApplication()
            val mutableList: MutableList<ListItem> = mutableListOf()
            //耗時操作返回的結(jié)果
            return@withContext mutableList
        }
    }
}

//從網(wǎng)絡(luò)獲取
class RecommendWallpaperRepo {
    private val webService: WallpaperWebService by lazy {
        WebDomains.MAIN().service(WallpaperWebService::class.java)
    }

    fun loadRecommendWallpapers(): Single<BaseResult<ImageSetObj>> {
        val recommendWallpapers = webService.getRecommendWallpapers(QueryParam.build())
        return recommendWallpapers
    }
}
ViewModel

ViewModel的生命周期
ViewModel對象存在的時間范圍是獲取 ViewModel時傳遞給 ViewModelProviderLifecycleViewModel將一直留在內(nèi)存中锥累,直到限定其存在時間范圍的 Lifecycle永久消失:對于 activity缘挑,是在 activity 完成時;而對于 fragment揩悄,是在 fragment 分離時卖哎。

class ListViewModel : ViewModel() {
    private val mRepo = ListRepo()
    val vipCountLiveData = MutableLiveData<Int>()
    val listItemsLiveData = MutableLiveData<List<ListItem>>()
    
    fun loadVipGroups() {
        viewModelScope.launch {
            val vipCount = mRepo.queryVipGroup()
            vipCountLiveData.postValue(vipCount)
        }
    }
    
    fun loadGroups() {
        viewModelScope.launch {
            val groupItems = mRepo.queryGroups()
            listItemsLiveData.postValue(groupItems)
        }
    }
}
View
class ListFragment : Fragment() {
    private lateinit var mListViewModel: ListViewModel
    private lateinit var mRecyclerView: RecyclerView
    private lateinit var mAdapter: GroupListAdapter
    
    override fun onCreate(saveInstanceState: Bundle?) {
        super.onCreate(saveInstanceState)
        mListViewModel = ViewModelProvider(viewModelStore, ViewModelProvider.NewInstanceFactory()).get(ListViewModel::class.java)
        mListViewModel.vipCountLiveData.observe(this, Observer<Int?> { count ->
            //監(jiān)聽到數(shù)據(jù)變化后進(jìn)行更新顯示
        })
        
        mListViewModel.listItemsLiveData.observe(this, Observer<List<ListItem>?>{
            //監(jiān)聽到數(shù)據(jù)變化后操作
            mAdapter.setData(list)
            mAdapter.notifyDataSetChanged()
        })
    }
}

class GroupListAdapter(
    private var mContext: Context?,
    var mDatas: List<ListItem>?
) : RecyclerView.Adapter<GroupListAdapter.ListItemViewCache>() {
    fun setData(datas: List<ListItem>) {
        mDatas = datas
    }
    
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ListItemViewCache {
        //返回ListItemViewCache
    }
    
    override fun getItemCount(): Int = mDatas?.size ?: 0
    
    override fun onBindViewHolder(
        holder: ListItemViewCache, 
        position: Int
    ) {
    
    }
    
    class ListItemViewCache(
        private val view: View
    ) : RecyclerView.ViewHolder(view) {
        init {
            //初始化
        }
    }
}
Model
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鬼悠,一起剝皮案震驚了整個濱河市删性,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌焕窝,老刑警劉巖蹬挺,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異它掂,居然都是意外死亡巴帮,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門虐秋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來榕茧,“玉大人,你說我怎么就攤上這事客给∮醚海” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵靶剑,是天一觀的道長蜻拨。 經(jīng)常有香客問我池充,道長,這世上最難降的妖魔是什么缎讼? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任收夸,我火速辦了婚禮,結(jié)果婚禮上血崭,老公的妹妹穿的比我還像新娘卧惜。我一直安慰自己,他們只是感情好夹纫,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布序苏。 她就那樣靜靜地躺著,像睡著了一般捷凄。 火紅的嫁衣襯著肌膚如雪忱详。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天跺涤,我揣著相機與錄音匈睁,去河邊找鬼。 笑死桶错,一個胖子當(dāng)著我的面吹牛航唆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播院刁,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼糯钙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了退腥?” 一聲冷哼從身側(cè)響起任岸,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狡刘,沒想到半個月后享潜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡嗅蔬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年剑按,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澜术。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡艺蝴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸟废,到底是詐尸還是另有隱情猜敢,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站锣枝,受9級特大地震影響厢拭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撇叁,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一供鸠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陨闹,春花似錦楞捂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至君账,卻和暖如春繁堡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乡数。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工椭蹄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人净赴。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓绳矩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親玖翅。 傳聞我的和親對象是個殘疾皇子翼馆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

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