小编Ma2*_*340的帖子

接收流的Android单元测试视图模型

我有一个 ViewModel 与用例对话并返回一个流,即Flow<MyResult>. 我想对我的 ViewModel 进行单元测试。我是使用流程的新手。需要帮助请。这是下面的视图模型 -

class MyViewModel(private val handle: SavedStateHandle, private val useCase: MyUseCase) : ViewModel() {

        private val viewState = MyViewState()

        fun onOptionsSelected() =
            useCase.getListOfChocolates(MyAction.GetChocolateList).map {
                when (it) {
                    is MyResult.Loading -> viewState.copy(loading = true)
                    is MyResult.ChocolateList -> viewState.copy(loading = false, data = it.choclateList)
                    is MyResult.Error -> viewState.copy(loading = false, error = "Error")
                }
            }.asLiveData(Dispatchers.Default + viewModelScope.coroutineContext)
Run Code Online (Sandbox Code Playgroud)

MyViewState 看起来像这样 -

 data class MyViewState(
        val loading: Boolean = false,
        val data: List<ChocolateModel> = emptyList(),
        val error: …
Run Code Online (Sandbox Code Playgroud)

android junit4 kotlin android-mvvm kotlin-coroutines

15
推荐指数
1
解决办法
7702
查看次数

具有多个发射的 Android 单元测试流程

我的用例与存储库通信并发出多个数据,如下所示 -

class MyUseCase(private val myRepoInterface: MyRepoInterface) : MyUseCaseInterface {

    override fun performAction(action: MyAction) = flow {
        emit(MyResult.Loading)
        emit(myRepoInterface.getData(action))
    }
}
Run Code Online (Sandbox Code Playgroud)

相同的单元测试如下所示 -

class MyUseCaseTest {

    @get:Rule
    val instantExecutorRule = InstantTaskExecutorRule()

    @Mock
    private lateinit var myRepoInterface: MyRepoInterface

    private lateinit var myUseCaseInterface: MyUseCaseInterface

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        myUseCaseInterface = MyUseCase(myRepoInterface)
    }

    @After
    fun tearDown() {
    }

    @Test
    fun test_myUseCase_returnDataSuccess() {
        runBlocking {
            `when`(myRepoInterface.getData(MyAction.GetData))
                .thenReturn(MyResult.Data("data"))

            // Test
            val flow = myUseCaseInterface.performAction(MyAction.GetData)

            flow.collect { data ->
                Assert.assertEquals(data, MyResult.Loading)
                Assert.assertEquals(data, MyResult.Data("data"))
            }
        } …
Run Code Online (Sandbox Code Playgroud)

junit android android-livedata kotlin-coroutines

7
推荐指数
1
解决办法
3127
查看次数

Android 导航组件使用 safeArgs 和深层链接传递参数

我有一个导航 xml,其功能如下 -

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_featureB.xml"
    app:startDestination="@id/FragmentB">

    <fragment
        android:id="@+id/FragmentB"
        android:name="FragmentB"
        android:label="FragmentB">
        <deepLink app:uri="App://FragmentB" />
    </fragment>
</navigation>
Run Code Online (Sandbox Code Playgroud)

在我的FeatureA片段中,我执行以下操作 -

val uri = Uri.parse("App://FragmentB")
findNavController().navigate(uri)
Run Code Online (Sandbox Code Playgroud)

我知道如何使用safeArgs没有深层链接。如何将数据传递到具有深层链接的其他功能?

android kotlin android-jetpack android-jetpack-navigation

7
推荐指数
1
解决办法
1万
查看次数

使用工作管理器的 Android 定期位置更新

我正在使用 WorkManager 如下 -

class LocationWorker(
    ctx: Context, params: WorkerParameters
) : CoroutineWorker(ctx, params), KoinComponent {

    private val locationDataRepository: LocationDataRepository by inject()

    override suspend fun doWork(): Result {
        return try {
            locationDataRepository.triggerLocationUpdates()
            Result.success()
        } catch (e: Exception) {
            Result.failure()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我将 Worker 触发为 -

val myWorker =
            PeriodicWorkRequestBuilder<LocationWorker>(
                15,
                TimeUnit.MINUTES
            ).addTag(
                "location"
            ).build()
        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "location",
            ExistingPeriodicWorkPolicy.KEEP,
            myWorker
        )
Run Code Online (Sandbox Code Playgroud)

如您所见,WorkManager 的最短时间为 15 分钟。我想在很短的时间间隔内跟踪位置,比如每隔几秒钟,我也希望即使在手机屏幕关闭时也能跟踪位置。WorkManager 是满足我要求的正确选择还是您会建议我一些其他 API?

android coroutine kotlin android-workmanager

6
推荐指数
1
解决办法
4066
查看次数

使用 livedata 进行 Android 视图模型单元测试

我正在对我的视图模型进行单元测试,并且我总是不断地获得NullPointerException.

这是我的视图模型代码 -

class LoginViewModel(private val myUseCase: MyUseCase) :BaseViewModel() {

    private val viewState = LoginViewState()

    fun onLoginClicked() =
        Transformations.map(
            myUseCase.performUseCaseAction(
                MyAction.LoginUser(
                    email,password)
            )
        ) {
            when (it) {
                is MyResult.Loading -> viewState.copy(loading = true)
                is MyResult.UserLoggedIn -> viewState.copy(
                    loading = false,
                    userLoggedIn = true
                )
                is MyResult.Error -> viewState.copy(loading = false, error = it.error)
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

这是 MyUseCase 接口代码 -

interface MyUseCase {

    fun performUseCaseAction(action: MyAction): LiveData<MyResult>
}
Run Code Online (Sandbox Code Playgroud)

这是相同的单元测试 -

@RunWith(MockitoJUnitRunner::class)
class LoginViewModelTest {

    @get:Rule
    val instantExecutorRule …
Run Code Online (Sandbox Code Playgroud)

junit android kotlin android-mvvm kotlin-coroutines

6
推荐指数
1
解决办法
2994
查看次数

Android 视图模型转换地图不起作用

我有一个带有按钮的视图 -

我的查看代码 -

private val viewModel: MyViewModel by viewModel()

    override fun onCreateView(...): View? {
        //Button click
        view.getMyData.setOnClickListener {
            viewModel.onGetDataClicked.observe(this, Observer {
            view?.progressBar?.isVisible = it.loading
            view?.description?.text = it.data.value
        })
        }
        return view
    }
Run Code Online (Sandbox Code Playgroud)

我的视图模型代码 -

val viewState = MyViewState()

    val onGetDataClicked =
        Transformations.map(myDomain.getData(MyAction.GetMyDataAction)) {
            when (it) {
                is MyResult.Loading -> viewState.copy(loading = true, error = null)
                is MyResult.Success -> viewState.copy(
                    loading = false,
                    data = it.data,
                    error = null
                )
                is MyResult.Error -> viewState.copy(
                    loading = false,
                    error = it.error …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-livedata

4
推荐指数
1
解决办法
3444
查看次数

使用 Github Actions 编辑 JSON 数组内的值

我有一个像这样的 JSON 存储在执行我的 Github 操作的文件夹/路径中 -

{
   "version":"1",
   "sampleArray":[
      {
         "id":"1"
      }
   ],
   "secondArray":[
      {
         "secondId":"2"
      }
   ]
}
Run Code Online (Sandbox Code Playgroud)

使用 Github 操作如何编辑值,id例如:将id值设置为“5”,sampleArray以便我的 JSON 具有更新的值?

javascript continuous-integration json github github-actions

3
推荐指数
1
解决办法
5989
查看次数

在 Kotlin StateFlow 中使用 emmit

到目前为止,我一直在使用Flow并将其映射到LiveData如下所示 -

看起来MyService像这样——

override fun provideData(action: MyAction) = flow {
   emit(MyResult.Loading)
   emit(dataRepository.getNewData())
}
Run Code Online (Sandbox Code Playgroud)

看起来ViewModel像这样——

fun getData() = myService.provideData(MyAction.GetData).map {
                
}.asLiveData(Dispatchers.Default + viewModelScope.coroutineContext)
Run Code Online (Sandbox Code Playgroud)

我想搬到StateFlow. 我怎样才能emitStateFlow使用Flow.

android kotlin android-livedata kotlin-coroutines

1
推荐指数
1
解决办法
2021
查看次数

当应用程序从后台转到前台时,Android launchWhenResumed 不会被调用

在我的片段中,

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        Log.e(TAG, "Inside on view created")

        lifecycleScope.launchWhenResumed {
            Log.e(TAG, "Inside lifecyclescope get data")
            viewModel.getData().collect {
              // ....
            
            }
        }
    }

    override fun onResume() {
        Log.e(TAG, "Inside on resume")
        super.onResume()
    }
Run Code Online (Sandbox Code Playgroud)

以下是不同场景下的日志序列 -

  1. 当应用程序刚刚打开时 -

    视图内部已创建

    简历里面

    在生命周期范围内获取数据

  2. 当从一个片段回到这个片段时 -

    视图内部已创建

    简历里面

    在生命周期范围内获取数据

现在问题来了...

  1. 当应用程序从后台进入前台时 -

    简历里面

如您所见,我只看到onResume()日志,但我也希望日志Inside lifecyclescope get data出现。我在这里做错了什么吗?

android android-lifecycle kotlin kotlin-coroutines

1
推荐指数
1
解决办法
4953
查看次数