美文网首页Android Weekly Notes
Android Weekly Notes #463

Android Weekly Notes #463

作者: 圣骑士wind | 来源:发表于2021-06-20 23:42 被阅读0次

    Android Weekly Issue #463

    Room auto-migrations

    Room 2.4.0-alpha01推出了Auto migration, 让数据库迁移更加容易.

    @Database(
       version = 2,
       entities = [ GoodDoggos.class ],
       autoMigrations = [
            AutoMigration (
                from = 1, 
                to = 2,
                spec = DoggosDatabase.DoggosAutoMigration::class
           )
        ]
    )
    abstract class DoggosDatabase : RoomDatabase {   
      @RenameTable(fromTableName = "Doggos", toTableName = "GoodDoggos")
        class DoggosAutoMigration: AutoMigrationSpec {   }
    }
    

    自动迁移可以和手动迁移结合, 满足开发者的需求.

    对于自动迁移还有测试的支持.

    A Compose & Viewmodel integration test with Hilt

    一个简单的小例子, UI是用Compose, 注入用Hilt.

    ViewModel中的state类型:

    sealed class UiState {
        object Loading : UiState()
        object Empty : UiState()
        data class Content(val items: List<Item> = listOf()) : UiState()
    }
    

    Repository返回flow, flow转UiState的方法:

    private suspend fun Flow<List<Item>>.toUiState(): Flow<UiState> = map {
        if (it.isEmpty()) {
            UiState.Empty
        } else {
            UiState.Content(items = it)
        }
    }.onStart {
        emit(UiState.Loading)
    }
    

    测试的时候, 需要假数据, 所以替换掉了Repository:

    @TestInstallIn(components = [SingletonComponent::class],
        replaces = [InventoryRepositoryModule::class])
    @Module
    object FakeInventoryRepositoryModule {
        @Singleton
        @Provides
        fun provideFakeInventoryRepository() = object : InventoryRepository {
            @ExperimentalCoroutinesApi
            override suspend fun items(): Flow<List<Item>> {
                return flowOf(dummyItems)
            }
        }
    }
    

    需要test runner:

    class HiltTestRunner : AndroidJUnitRunner() {
        override fun newApplication(
            cl: ClassLoader?,
            className: String?,
            context: Context?,
        ): Application {
            return super.newApplication(cl, HiltTestApplication::class.java.name, context)
        }
    }
    

    最后测试写成这样:

    @ExperimentalCoroutinesApi
    @HiltAndroidTest
    class ItemListTest {
    
        @get:Rule(order = 1)
        var hiltTestRule = HiltAndroidRule(this)
    
        @get:Rule(order = 2)
        var composeTestRule = createAndroidComposeRule<MainActivity>()
    
        @Before
        fun setup() {
            hiltTestRule.inject()
            composeTestRule.setContent {
                TallyApp(composeTestRule.activity.viewModels<ListViewModel>().value)
            }
        }
    
        @Test
        fun app_displays_list_of_items() {
            //assert the list is displayed
            composeTestRule.onNodeWithTag(InventoryListTag).assertIsDisplayed()
    
            //assert all items exist within the tree
            dummyItems.forEach { item -> 
                composeTestRule.onNodeWithText(item.name).assertExists()
            }
        }
    }
    

    Tap Response Time: Jetpack Navigation

    关于点击响应时间的进一步探索.

    Navigation Drawer using Jetpack Compose

    Navigation Drawer的Compose实现.

    代码见:
    https://github.com/walnashgit/ComposeNavigationDrawer/tree/feature/ComposeNavDrawerUsingModalDrawer

    Unit testing on Android

    单元测试:

    • ViewModel
    • 自定义View
    • 扩展方法

    测试LiveData还有一个工具类.

    Lessons learned when migrating my app to Jetpack Compose

    一些经验和资源介绍.

    Getting ready for Declarative UIs — Part 3 — Why Declarative UIs on Android?

    为什么要用声明式UI.

    CoroutineScope and coroutineContexts

    关于测试中CoroutineContext的探讨.

    always keep currentCoroutineContext() and coroutineContext pointing to the same value.

    Pi Practice App in Compose

    一个小应用, 之前使用Anko做的, 现在改用Compose做了.

    Code

    相关文章

      网友评论

        本文标题:Android Weekly Notes #463

        本文链接:https://www.haomeiwen.com/subject/rgeaeltx.html