Как я могу инициализировать AndroidMode ViewModel из данных, подлежащих продаже? - PullRequest
2 голосов
/ 31 марта 2020

В моем приложении Android я передаю пользовательские данные (UByteArray) из одного действия в другое, используя интерфейс для передачи.

Я использую эти данные внутри нескольких фрагментов, поэтому я переписал класс данных для расширения androidx ViewModel и открыть свойства LiveData для фрагментов. Теперь обновления пользовательского интерфейса намного приятнее, но я думаю, что использую их неправильно, потому что я перезаписываю все значения ViewModel внутри onCreate.

Теперь мой вопрос: что мне нужно изменить, чтобы инициализировать ViewModel только один раз ? Ниже приведен мой текущий код (сокращенно и переименован для этого вопроса):

class ActivityB : AppCompatActivity() {
  private val bData: ViewModelB by viewModels()
  // ...

  override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    intent.getParcelableExtra<ViewModelB>("id")?.let {
      Log.e(TAG, "Found parceled bData $it")
      // This seems like a very stupid way to do it, is there a better one?
      bData.copyAll(it)
    }
  }
}

Я видел, что можно вставить SavedState в конструктор ViewModelB, но у меня нет сохраненное состояние до сих пор, и данные должны быть переданы только один раз.

Должен ли я изменить инициализацию tagData с by viewModels() на = ViewModelB(intent)?
Или мне нужно как-то расширить ViewModelFactory ?

Любой совет здесь был бы очень признателен, спасибо.

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

Я видел, что можно добавить SavedState в конструктор ViewModelB, но у меня нет сохраненного состояния до сих пор, и данные нужно передавать только один раз.

Официальным решением будет предоставить SavedStateHandle, который инициализируется с defaultArgs как intent.extras вашей Деятельности.

Для этого вам необходимо предоставить реализацию AbstractSavedStateViewModelFactory ИЛИ использовать SavedStateViewModelFactory (в этом случае вы должны определить правильный конструктор, чтобы создать его экземпляр посредством отражения).

class ActivityB : AppCompatActivity() {
  private val bData: ViewModelB by viewModels {
      SavedStateViewModelFactory(application, this, intent.extras)
  }
  // ...

  override fun onCreate(savedInstanceState: Bundle?) {
    // ...
    // intent.getParcelableExtra<ViewModelB>("id")?.let {
    //      Log.e(TAG, "Found parceled bData $it")
  }
}

Затем в вашей ViewModel

@Keep
class ViewModelB(val savedStateHandle: SavedStateHandle): ViewModel() {
    val uByteData = savedStateHandle.get<UByteArray>("id")
}

Или так. Клавиша "id" должна совпадать с той же клавишей, что и в дополнительных функциях.

0 голосов
/ 31 марта 2020

Поскольку у вас есть ViewModel, который реализует Parcelable, вы можете получить свой экземпляр ViewModelB непосредственно из Intent extra.

Intent, который используется для запуска ActivityB может не быть != null в момент создания экземпляра ActivityB, но вы можете использовать

lateinit var bData: ViewModelB

Тогда в onCreate()

bData = if(intent.hasExtra("id")) intent.getParcelableExtra<ViewModelB>("id") else ViewModelProvider(this).get(ViewModelB::class.java)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...