Ваша формулировка намекает на некоторый дизайн fl aws, а именно: Вы ссылаетесь на свои данные как на переменную объекта и делаете их доступными в любое время, когда вы решили использовать ViewModel. Для меня это звучит так, что вы переосмыслили свои варианты.
Предложение
Жизненный цикл вашего объекта, кажется, управляется вручную самостоятельно. Поэтому вы должны просто использовать переменную stati c. Это означает Kotlin как свойство внутри (сопутствующего) объекта. Я предлагаю вам объявить пользовательский класс Application в вашем манифесте и в * onCreate
-методе вы выделяете свой объект и помещаете его в объект-компаньон этого класса. Конечно, вы можете выделить его в любое время позже. Это приведет к следующему:
- Доступ всегда возможен через
YourApplication.mData
в вашем коде. - Объектами, которые зависят от реализаций вне JVM, можно правильно управлять. Например: если вы уже привязаны к порту, вы не сможете сделать это при последовательном вызове - например, когда viewModel восстанавливает свое состояние. Возможно, базовая реализация не сообщила об ошибке обратно Java, но выделение не удалось. Чтобы продемонстрировать это предположение, вам необходимо предоставить описание вашей объектной переменной. Но в качестве известного примера в мире Android для такого поведения попробуйте создать soundPool через SystemServices. Вы получите сообщения о правильном использовании этого объекта.
- Снятие выделения может быть выполнено с помощью метода
onTerminate()
вашего Application.class // edit_4: Do c из super. onTerminate () говорит, что система просто убьет ваше приложение. Поэтому нужно освободить место в вашей деятельности. Смотрите фрагменты кода ниже.
Пояснение
Модель представления компонентов JetPack в основном отвечает за сохранение и восстановление состояния представления и привязку к его модели. Смысл в том, что он обрабатывает жизненный цикл между действиями, фрагментами и, возможно, представлениями. Вот почему вы должны использовать действие в качестве владельца жизненного цикла на тот случай, если вы захотите поделиться моделью представления между несколькими фрагментами. Но я все же полагаю, что ваш объект сложнее, чем просто POJO, и мое приведенное выше предложение приводит к вашему ожидаемому поведению. Также обратите внимание, что при многопоточности вы не должны полагаться на правильный порядок методов жизненного цикла. Существуют только ограниченные обратные вызовы жизненного цикла, которые гарантированно будут вызываться в определенном порядке c системой android, но, к сожалению, часто используемые здесь не включены. В этом случае вы должны начать обработку в более подходящее время.
Несмотря на то, что данные должны быть аналогичны предыдущему состоянию, точная ссылка зависит от реализации hashCode, но это спецификация JVM c.
/ / edit:
ParentFragment также является некорректным наименованием, поскольку вы создали класс, который другие наследуют, а не ссылаются на него. Если вы хотите получить доступ к определенной переменной c во всех ваших фрагментах, это необходимо реализовать как объект (Singleton), поскольку компонент Navigation не позволит вам напрямую обращаться к фрагменту менеджера. Проще говоря, android, один фрагмент всегда может ссылаться на его parentFragment, если , этот parentFragment использовал свой собственный childFragmentManager для фиксации фрагментаTransaction. Это означает также, что фрагменты, добавленные вашим Activity -gmentManager, никогда не имеют parentFragment.
// edit_2 + 3:
ViewModelProvider(activity!!, ViewModelFactory())[clazz]
- это правильный вызов для создания и доступа к sharedViewModel: владельцем жизненного цикла должна быть операция, иначе после каждой выполненной фрагмента транзакции произойдет обратный вызов метода onCleared () и viewModel освобождают все ссылки, чтобы избежать утечек памяти.
// edit_4: то, что ваш объект не был правильно инициализирован, было лишь предположением, которое может возникнуть, если вы попытаетесь инициализировать его снова. Например, если вы используете метод get () для val, где это не подходит. Тем не менее, обработка вашего объекта таким образом гарантирует, что его жизненный цикл находится за пределами ваших фрагментов. Вот пример кода, чтобы прояснить мою формулировку:
// edit_5: чтобы утверждать, что ссылка на объект не повреждена, включите проверку нуля (только если конструкция CustomClass не тривиальна)
Объявите свое пользовательское приложение
class CustomApplication : Application() {
companion object SharedInstances {
/**
* Reference to an object accessed in various places in your application.
*
* This property is initialized at a later point in time. In your case, once
* the user completed a required workflow in some fragment.
*
* @Transient shall indicate that the state could also be not Serializable/Parcelable
* This _could_ require manually releasing the object.
* Also prohibits passing via safeArgs
*/
@Transient var complex: CustomClass? = null
}
}
Инициализация и использование в ваших классах:
class InitializeComplexStateFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (complex != null) return@onViewCreated // prohibit successive initialization.
if (savedInstanceState != null) { /* The fragment was recreated but the object appears to be lost. */ }
// do your heavy lifting and initialize your data at any point.
CustomApplication.SharedInstances.complex = object : CustomClass() {
val data = "forExampleAnSessionToken"
/* other objects could need manual release / deallocation, like closing a fileDescriptor */
val cObject = File("someFileDescriptorToBindTo")
}
}
}
class SomeOtherFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
CustomApplication.SharedInstances.complex?.let {
// do processing
}
?: propagateErrorStateInFragment()
}
private fun propagateErrorStateInFragment() { throw NotImplementedError("stub") }
}
Отключение при необходимости
class SomeActivity: Activity() {
override fun onStop() {
super.onStop()
/* with multiple activities the effort increases */
CustomApplication.complex?.close()
}
}