Как завершить несколько действий в одном экземпляре? - PullRequest
0 голосов
/ 26 октября 2018

У меня есть несколько действий с launchMode SingleInstance.Выйдя из системы, я хочу завершить все действия и открыть launchScreen.

val intent = Intent(context, LauncherActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
(context as AppCompatActivity).finishAffinity()
context.startActivity(intent)

Однако, если я нажимаю обратно на Launcher, я перенаправляюсь к ранее запущенным действиям в режиме singleInstance

Ответы [ 5 ]

0 голосов
/ 01 ноября 2018

По моему опыту, расширение класса Application - это более простой и эффективный способ хранения ограниченного объема данных, который необходимо распределить между всеми действиями.

В вашем случае вы можете создать класс, содержащий ваши данные для входа в систему, и сохранить его экземпляр в вашем пользовательском объекте Application, где он будет доступен для всех действий. Они могут проверить доступность входа в систему, подписаться на изменения и получать уведомления, когда им нужно закончить. Сам объект Application может подписаться на изменения и при необходимости начать действие входа в систему.

0 голосов
/ 30 октября 2018

Перед запуском заставки добавьте эту строку

ActivityCompat.finishAffinity(this)
0 голосов
/ 30 октября 2018

У меня есть несколько действий с launchMode SingleInstance. Выйдя из системы, я хочу завершить все действия и открыть запуск экрана.

Вот один из способов:

  1. Пусть все действия расширят пользовательский BaseActivity.
  2. Вы можете использовать LocalBroadcastManager для отправки локальной трансляции (в вашем приложении), когда нажата кнопка выхода из системы.
  3. Внутри базовой деятельности вы можете реализовать слушателя. Вы можете позвонить finish() внутри слушателя.
  4. Поэтому, когда пользователь нажимает кнопку выхода из системы, вы отправляете локальную рассылку всем открытым действиям. Поскольку все ваши действия расширяют общий BaseActivity, слушатель вызывается, и действия заканчиваются.
  5. После отправки трансляции вы можете открыть нужное LauncherActivity.

См. Как использовать LocalBroadcastManager? для большего.

P.S .: Вы можете отменить регистрацию слушателя в onDestroy. Поскольку активность все еще присутствует, onDestroy не будет вызван. А если он уже был уничтожен, у вас есть на один повод для беспокойства.

0 голосов
/ 30 октября 2018

ОБНОВЛЕНИЕ 11/1/2018:

Я протестировал несколько подходов, чтобы справиться с ним, таких как распространение событий, флаги намерений, подсчет экземпляров активности и т. Д. Есть несколько странных сценариев, таких как запуск нескольких singleInstance деятельность последовательно.В этом случае средние действия вообще не запускаются (метод onCreate не вызывается) и после нажатия кнопки назад они будут запущены.Поэтому ни один из предыдущих подходов не работает!Поскольку проблема немного странная, я попытался решить ее немного странным способом.

Мы поддерживаем состояние выхода из системы в одноэлементном объекте с именем LogoutHandler.Он взаимодействует с классом LogoutAwareActivity, который наследуется всеми действиями, кроме LoginActivity, поскольку на него не должен влиять механизм выхода из системы.Когда происходит выход из системы, в LogoutHandler устанавливается флаг до тех пор, пока не закончится последний дочерний элемент LogoutAwareActivity, а затем очищается флаг.

Вот реализация этого:

LogoutHandler:

import java.util.*

object LogoutHandler {

    private var isLogout = false
    private var timerWatchDog: TimerWatchDog? = null

    fun isLogout() = isLogout

    fun onActivityDestroyed() {
        if (isLogout) {
            timerWatchDog?.refresh(Runnable {
                isLogout = false
                timerWatchDog = null
            })
        }
    }

    fun logout() {
        isLogout = true
        timerWatchDog = TimerWatchDog(500)
    }

    private class TimerWatchDog(private val delay: Long) : Runnable {

        private var timer: Timer? = null
        private var runnable: Runnable? = null

        fun refresh(runnable: Runnable) {
            this.runnable = runnable
            timer?.cancel()

            val timerTask = object : TimerTask() {
                override fun run() {
                    Thread(this@TimerWatchDog).start()
                }
            }
            timer = Timer()
            timer?.schedule(timerTask, delay)
        }

        override fun run() {
            runnable?.run()
        }
    }

}

LogoutAwareActivity:

import android.support.v7.app.AppCompatActivity

abstract class LogoutAwareActivity : AppCompatActivity() {

    override fun onResume() {
        super.onResume()
        if (LogoutHandler.isLogout()) {
            finish()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        LoginHandler.onActivityDestroyed()
    }

}

Конкретное действие:

class ActivityA : LogoutAwareActivity() {

    // ...
}

Другой конкретный вид деятельности:

class ActivityB : LogoutAwareActivity() {

    // ...
}

Ваша функция выхода из системы:

fun logout() {
    val intent = Intent(context, LoginActivity::class.java)
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

    LogoutHandler.logout()
    context.startActivity(intent)
}

Визуальный результат:

Все MainActivity, ActivityA, ActivityB и ActivityC являются одним экземпляром.

Переход между действиями нажатием кнопки назад:

enter image description here

Перейдите к LoginActivity, затем нажмите кнопку возврата:

enter image description here

0 голосов
/ 30 октября 2018

Я не знаю, что именно вы пытались сделать, но у меня было ощущение, что вы можете изменить дизайн своего приложения по-другому, чтобы сделать его лучше.

В любом случае, на ваш вопрос - я полагаю, вы можете проверить запуск действий, если пользователь вышел из системы, и если он действительно запустил действие по запуску одного экземпляра, и закройте эти действия с помощью finish().

...