Sunflower(向日葵)源碼分析


簡介:

Sunflower項目是google發布的kotlin項目,里面主要介紹google 最新的一些工具,使開發者可以快速構建自己的APP項目,具體源碼:https://github.com/googlesamples/android-sunflower

在自己安裝編譯的時候,建議把包名(com.google.samples.apps.sunflower)改動下,因為com.google.xx安裝后提示需要安裝google的插件

一、主要技術

1、MVVM 利用databinding,viewModel,liveData實現MVVM架構,

2、利用navigation框架做導航,APP只有一個Activity,其余的都是Fragment

二、具體說明

1、界面實現

主Activity:GardenActivity 加載了一個布局

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <fragment
            android:id="@+id/nav_host"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_garden"/>

    </FrameLayout>

</layout>

有個<layout/>來封裝其實沒啥用,因為沒有使用Binding的內容,可以去掉

這里用到Navigation,我們來看看nav_garden

//使用navigation來包裝,加載兩個fragment app:startDestination設置主界面
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@+id/view_pager_fragment">

//主fragment <fragment android:id="@+id/view_pager_fragment" android:name="com.gl.samples.apps.sunflower.HomeViewPagerFragment" tools:layout="@layout/fragment_view_pager"> <action android:id="@+id/action_view_pager_fragment_to_plant_detail_fragment" app:destination="@id/plant_detail_fragment" app:enterAnim="@anim/slide_in_right" app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> </fragment> //詳情頁 <fragment android:id="@+id/plant_detail_fragment" android:name="com.gl.samples.apps.sunflower.PlantDetailFragment" android:label="@string/plant_details_title" tools:layout="@layout/fragment_plant_detail"> <argument android:name="plantId" app:argType="string" /> </fragment> </navigation>
這個也不難,HomeViewPagerFragment主界面,PlantDetailFragment植物詳情頁,具體內容可以去了解下Navigation

   HomeViewPagerFragment 主要是一個viewPager,包含兩個Fragment :GardenFragment和 PlantListFragment

class SunflowerPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {

    /**
     * Mapping of the ViewPager page indexes to their respective Fragments
     */
    private val tabFragmentsCreators: Map<Int, () -> Fragment> = mapOf(
        MY_GARDEN_PAGE_INDEX to { GardenFragment() },
        PLANT_LIST_PAGE_INDEX to { PlantListFragment() }
    )

    override fun getItemCount() = tabFragmentsCreators.size

    override fun createFragment(position: Int): Fragment {
        return tabFragmentsCreators[position]?.invoke() ?: throw IndexOutOfBoundsException()
    }
}

viewPager適配器SunflowerPagerAdapter中定義一個map,在創建Fragment的時候通過反射來執行構建Fragment的方法。

這里要注意viewPager和我們以前使用的viewPager並不是一個東西,而是在androidx.viewpager2.widget里面的新的類,主要通過RecyclerView來實現,適配器當然

也是繼承RecyclerView.Adapter實現的,具體實現請查看源碼,具體不細說。

GardenFragment和 PlantListFragment里面就比較簡單,運用DataBinding來把數據綁定到View上,實現數據變化view改變,ViewModel來處理和管理數據,並進行數據通信。

這個里面涉及到的內容比較復雜,可以查看我另一個源碼,比較簡單的介紹DataBinding和ViewModel的用法,傳送門

2、數據加載

這個應用可以說是一個離線應用(數據離線,圖片加載不是),主要的數據都是存儲在plants.json,於是需要把內容都加載出來:

class SeedDatabaseWorker(
    context: Context,
    workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
    override suspend fun doWork(): Result = coroutineScope {
        try {
            applicationContext.assets.open(PLANT_DATA_FILENAME).use { inputStream ->
                JsonReader(inputStream.reader()).use { jsonReader ->
                    val plantType = object : TypeToken<List<Plant>>() {}.type
                    val plantList: List<Plant> = Gson().fromJson(jsonReader, plantType)

                    val database = AppDatabase.getInstance(applicationContext)
                    database.plantDao().insertAll(plantList)

                    Result.success()
                }
            }
        } catch (ex: Exception) {
            Log.e(TAG, "Error seeding database", ex)
            Result.failure()
        }
    }

主要在SeedDatabaseWorker類中,主要使用的是WorkManager這個框架來實現異步加載,加載后把數據存入room數據庫,便於后續使用。

CoroutineWorker是Worker的子類,一般在使用Kotlin開發的時候使用來和協程配合開發,

看這部分代碼可以先去學習下WorkManager,WorkManger介紹視頻:介紹視頻(美麗的小姐姐不會讓你失望的)

當然room數據庫也有小哥哥的視頻:介紹視頻

總結:

Sunflower這個應用主要的技術包括:DataBinding、ViewModel、LiveData、Navigation、WorkManager和Room,

當然還有一些簡單的Android的知識和協程的內容,把這個應用過一遍,對自己也很有幫助。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM