天天看點

Android Jetpack 最佳開發姿勢

在Android架構元件基礎上,融入Kotlin 協程+retrofit,模拟網絡,全面快速開發。

Navigation

NavController在 NavHost 中管理應用導航的對象,沿導航圖中的特定路徑導航至特定目标,或直接導航至特定目标。

首先,定義 layout/activity_main.xml

<fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@id/nav_view"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />           

其次,定義 navigation/mobile_navigation.xml

Activity的添加,需要先在Project建立對應的Activity,即可在布局設計器處理。
           
<navigation  
 <fragment
     android:id="@+id/navigation_home"
     android:name="com.android.myapplication.ui.home.HomeFragment"
     android:label="@string/title_home"
     tools:layout="@layout/fragment_home">

        <action
         android:id="@+id/action_navigation_home_to_detail_activity"
         app:destination="@id/detail_activity" />
 </fragment>
   ...
 <activity
     android:id="@+id/detail_activity"
     android:name="com.android.myapplication.ui.detail.DetailActivity"
     android:label="DetailActivity">
     <argument
         android:name="detailId"
         app:argType="string" />
 </activity>
</navigation>
           

最後,頁面跳轉,參數傳遞

val direction =  HomeFragmentDirections.actionNavigationHomeToDetailActivity(plantId)
    view.findNavController().navigate(direction)           

參數接收:

private val args: DetailActivityArgs by navArgs()           

Databinding

在onCreateView()中直接使用控件,會報空指針異常,這個姿勢 binding.tvNavigation 是可以的。

val binding = FragmentHomeBinding.inflate(inflater, container, false)
binding.tvNavigation.setOnClickListener {
            navigateToDetailPage("1", it)
        }
           

布局檔案中,字元串拼接,如跟ViewModel一起使用:

android:text='@{"Data From Network-> "+viewModel.response}'           

ViewModel

以生命周期的方式存儲和管理界面相關的資料。

Kotlin協程 viewModelScope, 如果 ViewModel 已清除,則在此範圍内啟動的協程都會自動取消。

private val homeViewModel: HomeViewModel by viewModels {
        InjectorUtils.provideHomeViewModelFactory(requireContext())
    }

viewModelScope.launch {
           ...
        }           

LiveData

一種可觀察的資料存儲器類,具有生命周期感覺能力,意指它遵循其他應用元件(如 Activity、Fragment 或 Service)的生命周期。

var plantName = gardenPlantings.map {
        ...
    }           

map 實作LiveData的轉換

Room

建立應用資料的緩存, SQLite 的基礎上提供了一個抽象層,充分利用 SQLite 的強大功能,更強健的資料庫通路機制。

使用 Room 引用複雜資料,Room 提供了在基本類型和包裝類型之間進行轉換的功能,但不允許實體之間進行對象引用。

要為自定義類型添加此類支援,您需要提供一個 TypeConverter,它可以在自定義類與 Room 可以保留的已知類型之間來回轉換。

class Converters {//TypeConverters
    ...
}           

将 @TypeConverters 注釋添加到 AppDatabase 類中,以便 Room 可以使用您為該 AppDatabase 中的每個實體和 DAO 定義的轉換器:

@Database(entities = table, version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
   ...
}
           
@Insert
suspend fun insertPlant(plant: Plant): Long           

認為是協程suspend

WorkManager

使用 WorkManager API 可以輕松地排程即使在應用退出或裝置重新開機時仍應運作的可延遲異步任務。

val workManagerConfiguration = Configuration.Builder()
            .setWorkerFactory(RefreshDataWork.Factory())
            .build()

 WorkManager.initialize(appContext, workManagerConfiguration)
        val constraints = Constraints.Builder()
            .setRequiresCharging(true)
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

val work = PeriodicWorkRequestBuilder<RefreshDataWork>(2, TimeUnit.HOURS)
            .setConstraints(constraints)
            .build()

WorkManager.getInstance(appContext)
            .enqueueUniquePeriodicWork(RefreshDataWork::class.java.name, KEEP, work)
           

PeriodicWorkRequest 用于重複或重複工作,最小間隔應為15分鐘。

OneTimeWorkRequest 一次性申請,不重複工作。

WorkManager按順序執行,單例模式,app啟動時執行一次。

代碼Github的下載下傳位址:

https://github.com/AlbertShen0211/Android-architecture-components

為了更好的了解代碼,附圖如下