Android Weekly Issue #473
Debugging Story: The Case of Rogue Reflection
一個(gè)和反射相關(guān)的問(wèn)題的追蹤過(guò)程.
Kotlin Multiplatform Mobile Codelab
KMP的codelab.
Creating a retro-style game with Jetpack Compose
復(fù)古風(fēng)的游戲.
Scalable Jetpack Compose Navigation
如何擴(kuò)展Jetpack Compose的Navigation.
定義一個(gè)navigation的factory:
// An interface is created to allow a feature module to add their Composable to the NavGraph.
// Defined within a library module
interface ComposeNavigationFactory {
fun create(builder: NavGraphBuilder, navController: NavHostController)
}
然后每個(gè)feature實(shí)現(xiàn)它:
// An implementation of the interface, as well as a Dagger 2 module installed via hilt.
// Defined within a feature module
internal class Feature1ComposeNavigationFactory @Inject constructor() : ComposeNavigationFactory {
override fun create(builder: NavGraphBuilder, navController: NavHostController) {
builder.composable(
route = "feature1",
content = {
Feature1(
navController = navController
)
}
)
}
}
// Defined within the 'feature 1' module
@Module
@InstallIn(SingletonComponent::class)
internal interface ComposeNavigationFactoryModule {
@Singleton
@Binds
@IntoSet
fun bindComposeNavigationFactory(factory: Feature1ComposeNavigationFactory): ComposeNavigationFactory
}
最后注入:
// An example of a set of factories being used to construct a NavHost.
// Potentially defined within the app module
@AndroidEntryPoint
class ExampleActivity: AppCompatActivity {
@Inject
lateinit var composeNavigationFactories: @JvmSuppressWildcards Set<ComposeNavigationFactory>
@Composable
fun JetpackNavigationHiltApp() {
val navController = rememberNavController()
NavHost(navController, startDestination = "feature1") {
composeNavigationFactories.forEach { factory ->
factory.create(this, navController)
}
}
}
}
作者把這個(gè)搞了個(gè)庫(kù):
https://github.com/LachlanMcKee/Hilt-Compose-Navigation-Factory
還有其他方案比如: https://github.com/zsoltk/compose-router
Providing AssistedInject supported ViewModel for Composable using Hilt
AssistedInject: 處理有一些參數(shù)需要運(yùn)行時(shí)提供.
在composable里需要借助EntryPoint這樣搞一波:
@Composable
fun noteDetailViewModel(noteId: String): NoteDetailViewModel {
val factory = EntryPointAccessors.fromActivity(
LocalContext.current as Activity,
MainActivity.ViewModelFactoryProvider::class.java
).noteDetailViewModelFactory()
return viewModel(factory = NoteDetailViewModel.provideFactory(factory, noteId))
}
用的時(shí)候:
NavHost(navController, startDestination = Screen.Notes.route, route = NOTY_NAV_HOST_ROUTE) {
composable(
Screen.NotesDetail.route,
arguments = listOf(navArgument(Screen.NotesDetail.ARG_NOTE_ID) { type = NavType.StringType })
) {
val noteId = it.arguments?.getString(Screen.NotesDetail.ARG_NOTE_ID)!!
NoteDetailsScreen(navController, noteDetailViewModel(noteId))
}
}
底部是一個(gè)全kotlin技術(shù)棧的應(yīng)用:
https://github.com/PatilShreyas/NotyKT
Two-way communication without internet: Nearby Connections (Part 2 of 3)
利用Nearby API, 沒(méi)網(wǎng)的時(shí)候也可以通信.
Using Composition in Kotlin
在kotlin中使用組合.
Advanced Usage of WorkManager in multi-process apps
WorkManager多進(jìn)程的例子:
https://github.com/android/architecture-components-samples/tree/main/WorkManagerMultiprocessSample
Scope Storage Myths
Android 11之后, 如果app不訪問(wèn)別的app擁有的文件, 則不需要請(qǐng)求READ_EXTERNAL_STORAGE權(quán)限.
還可以這樣:
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
Refactoring Kotlin type-signatures for fun and profit
Compose: Strikethru Animation
一個(gè)icon的動(dòng)畫(huà).
Browsing Jetpack Compose samples
看Jetpack Compose Sample的方法.
有一個(gè)Android Code Search的網(wǎng)站:
https://cs.android.com/
有一個(gè)code search plugin:
https://plugins.jetbrains.com/plugin/12578-codesearch
源碼:
https://github.com/guojianhua/code-search
Code
- 筆記應(yīng)用: https://github.com/PatilShreyas/NotyKT
- 一個(gè)要取代ViewModel的小工具: https://github.com/marcellogalhardo/retained
- 選取圖片和照相的庫(kù): https://github.com/SimformSolutionsPvtLtd/SSImagePicker