Активность воссоздана после запроса разрешений - PullRequest
0 голосов
/ 08 апреля 2020

Это поток: Activity -> Fragment1 -> Fragment2 -> Fragment3

У меня есть этот Fragment3 с представлением переключателя -> При нажатии на этот переключатель я вызываю viewModel метод, который запрашивает необходимое разрешение для включения этого переключателя.

Проблема в том, что каждый раз, когда я запрашиваю разрешение и разрешаю или запрещаю, действие воссоздается, и Fragment3 умирает, снова показывая первый фрагмент (Fragment1)

Я пытался использовать onSaveInstance состояние, но мне не было ясно, как вернуть экземпляр фрагмента после запроса разрешения вместо воссоздания всего.

Есть идеи, как мне решить эту проблему?

Упражнение:

class Activity : DaggerActivity<DaggerComponent>() {

private val viewModel: ActivityViewModel by injectionViewModels {
    activityComponent.activityViewModel
}

override fun onSafeCreate(savedInstanceState: Bundle?) {
    super.onSafeCreate(savedInstanceState)
    setContentView(R.layout.single_fragment_activity)

    if (savedInstanceState != null) {
        onRestoreInstanceState(savedInstanceState)
    } else
        observeViewModel()
}

override fun onSafeResume() {
    super.onSafeResume()
    viewModel.onCheckFeatureState()
}

private fun observeViewModel() {
    observe(viewModel.areAllPermissionsGiven) { areGiven ->
        if (areGiven) {
            replaceFragment(SettingsFragment(), R.id.fragment_container, false)
        } else {
            replaceFragment(PermissionsFragment(), R.id.fragment_container, false)
        }
    }
}}

MyFragment:

class MyFragment : DaggerFragment<DaggerComponent>() {

private val viewModel: FragmentViewModel by injectionActivityViewModels {
    activityComponent.fragmentViewModel
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.fragment, container, false)
}

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

private fun initialize() {
    viewModel.onViewCreated()
    toolbar.setNavigationOnClickListener { activity?.onBackPressed() }
    initViews()
    initObservables()
}

private fun initViews() {
    switch.onClick {
        viewModel.onToggleMonitoringSecurityClick()
    }
}

private fun initObservables() {
    observe(viewModel.state) { state ->
        switch.isChecked = state.isEnabled
        switchText.isGone = state.hasPermission
    }
}}

Код, который я использую для запроса разрешения и включения функции с использованием общих настроек:

class Option @AssistedInject constructor(
@Assisted private val permission: Permission,
@Assisted private val dataSource: DataSource,
private val permissionStatus: GetPermissionStatusUseCase,
private val permissionRequest: RequestPermissionUseCase) {
fun isEnabled() = dataSource.isEnabled && hasPermission

suspend fun enable() = withContext(Dispatchers.IO) {
    val enable = hasPermission || (permissionRequest(permission) is Response.Success)

    if (enable) {
        dataSource.isEnabled = true
    }

    enable
}

fun disable() {
    dataSource.isEnabled = false
}

suspend fun toggle() {
    if (isEnabled()) {
        disable()
    } else {
        enable()
    }
}

val hasPermission
    get() = permissionStatus.invoke(permission) == PermissionStatus.ENABLED

@AssistedInject.Factory
interface Factory {
    fun create(permission: Permission, dataSource: DataSource): Option
}}

Я использую приведенный выше объектный код домена на useCase, который предоставляет viewModel возвращаемое значение наличия разрешения или нет.

1 Ответ

0 голосов
/ 09 апреля 2020

Вот как я решил свою проблему:

в Манифесте добавьте эту строку для действий

android:launchMode="singleTop"

, например:

<activity
    android:name=".Activity"
    android:label="@string/my_activity"
    android:launchMode="singleTop"
</activity>
...