用Kotlin+Retrofit+RxKotlin+MVP擼了一個小專案

藏地情人發表於2018-01-03

作為Android開發者,對於谷歌大大力推的Kotlin肯定是要會用的啦。 最近就使用了豆瓣電影的部分介面擼了一個小Demo來學習。(由於電腦比較渣,開了模擬器錄屏好卡。其實在手機上還是很流暢的。哈哈哈)

簡介

遵循MD風格,採用MVP架構,使用了Kotlin+Retrofit+RxKotlin開發。現在主要有兩個功能:

  • 豆瓣電影正在上映列表與詳情(由於API的限制,部分功能未實現)
  • 使用方向感測器與矩陣實現了圖片隨手機擺動而移動位置(需要真機)

用Kotlin+Retrofit+RxKotlin+MVP擼了一個小專案

關於第一個功能

Kotlin+Retrofit+RxKotlin 一起使用
  • 在ApiServers中定義請求方法
@GET(BaseURL.HOTSCREEN)
    fun getHotScreenList(@QueryMap par: HashMap<String, String>): Observable<HotScreenResult>
複製程式碼
  • 在module層中封裝
override fun loadHotScreenData(page: Int, next: (result: HotScreenResult) -> Unit
                                   , error: (th: Throwable) -> Unit) {
        val parm = HashMap<String, String>()
        parm.put("apikey", getApiKey())
        parm.put("city", "深圳")
        parm.put("start", page.toString())
        parm.put("count", "10")
        parm.put("client", "")
        parm.put("udid", getToken())
        BuildApi.buildApiServers()!!
                .getHotScreenList(parm)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeBy(
                        onNext = next,
                        onError = error)
    }
複製程式碼

Presenter層呼叫

 if (view == null || module == null)
            return
    view?.showLoading()
    module?.loadHotScreenData(page, {
        view!!.notifyList(it)
        view!!.dismissLoading()
        }, {
        it.printStackTrace()
        view!!.dismissLoading()
        view!!.showTipMessage(1, "網路異常")})
複製程式碼
共享元素轉場動畫
  • 在要轉場的xml檔案中分別定義相同的transitionName
<!-- 第一個頁面 -->
<ImageView
            android:id="@+id/item_hot_screen_image"
            android:layout_width="@dimen/dimen_100"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:transitionName="@string/t_movie_list_to_detail"/>


<!-- 第二個頁面 -->
<ImageView
                android:id="@+id/movie_detail_coll_head_photo"
                android:layout_width="@dimen/dimen_150"
                android:layout_height="match_parent"
                android:layout_gravity="center_horizontal"
                android:layout_marginBottom="@dimen/dimen_15"
                android:layout_marginTop="@dimen/dimen_55"
                android:scaleType="centerCrop"
                android:transitionName="@string/t_movie_list_to_detail"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.6" />

複製程式碼
  • 在程式碼中定義
//第一個頁面
val intent = Intent(activity, MovieDetailAct::class.java)
        intent.putExtra("id", mData[position].id)
        //第二個引數:共享元素的view  第三個引數:在xml檔案中定義的transitionName
        val optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
                shareView,
                getString(R.string.t_movie_list_to_detail))
        startActivity(intent, optionsCompat.toBundle())


//第二個頁面
postponeEnterTransition() //延遲動畫
...
...
startPostponedEnterTransition() //開始動畫
複製程式碼
圖片取色

用到了 v7 包中的工具 Palette,需要注意的是由於圖片的複雜性,不一定每張圖片都能取到相應的顏色,所以一定要做非空判斷。

                Palette.from(resource).generate {
                    if (it != null) {
                        val dvs = it.darkVibrantSwatch //暗色有活力的
                        val lvs = it.lightVibrantSwatch //亮色有活力的
                        val dms = it.darkMutedSwatch //暗色柔和的
                        val lms = it.lightMutedSwatch //亮色柔和的
                        var color = when {
                            dvs?.rgb != null -> dvs.rgb
                            lvs?.rgb != null -> lvs.rgb
                            dms?.rgb != null -> dms.rgb
                            lms?.rgb != null -> lms.rgb
                            else -> ContextCompat.getColor(getContext(), R.color.themColor)
                        }
                        window.statusBarColor = color //狀態列
                        movie_detail_coll_head_bg.setBackgroundColor(color)
                        movie_detail_coll_layout.setContentScrimColor(color)
                    }
                }
複製程式碼
定義高階函式
fun setOnItemClickListener(listener: (itemView: View, position: Int, shareView: View) -> Unit) {
        itemClick = listener
    }
 ....
 ....    
 holder?.btn?.setOnClickListener {
            if (itemBtnClick != null)
                itemBtnClick.invoke(it, position)
        }
複製程式碼

關於第二個小功能

第二個功能的效果是看到了今日頭條的一條廣告效果,覺得很有意思,就想自己實現一下。 自己做下來程式碼量不是很多,但是裡面涉及到原理還是值得搞明白的。準備另外寫一篇文章記錄一下,總的下來有一個感受就是: 數學真是個好東西

最後

總的來說覺得Kotlin還是很好用的,值得深入學習。程式碼量很少,適合練手,程式碼以上傳到GitHub

相關文章