Проблемы MVVM с Kotlin - Получение некоторой ошибки при модульности - PullRequest
0 голосов
/ 06 февраля 2020

Цель:

Я хотел бы модулировать свой код, но я не очень хорошо знаком с Kotlin / Java - довольно много нового для обоих языков, я кодировал с React Native.

Следующий код - то, как я делал реализацию представления модели. Если у кого-то есть лучшее предложение о том, как сделать MVVM.

, я пытаюсь сделать прямой доступ, как в следующем коде, и я пытаюсь создать экземпляры CustomerModel () и CustomerActivity (), но это дает черный пустой экран.

Этот CustomerModel будет отвечать за подключение к базе данных клиентов с использованием firebase.

CustomerActivity попросит сохранить информацию, загрузить информацию и отобразит информацию, используя консоль базы данных результатов.

Будут другие действия, обращающиеся к CustomerModel (такие действия настройки , просмотр списка действий, ...)

Как я могу заставить этот код работать и лучше обрабатывать все компоненты базы данных вне представления?

Проблемы:

The hasInfo не обновляется. Это всегда ложь, и проверка базы данных верна для моего тестового пользователя

Я получил эту ошибку, я должен сделать какую-то ошибку, но не могу узнать, что:

java .lang.NullPointerException: вы не можете запустить загрузку для еще не прикрепленного представления или фрагмента, где getActivity () возвращает значение null (что обычно происходит, когда getActivity () вызывается до присоединения фрагмента или после уничтожения фрагмента) .

Видимо происходит при попытке обновить TextView и ImageView, возможно, оно еще не создано (мое предположение)

CustomerModel.kt (Модель)

private lateinit var mCustomerDatabase: DatabaseReference

internal fun getUserInfo(uid: String) {
  mUserDatabase = FirebaseDatabase.getInstance().reference.child("Users").child("Customers").child(uid)

  mCustomerDatabase.addValueEventListener(object: ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
      if (dataSnapshot.exists() && dataSnapshot.childrenCount > 0) {
        val map: (Map < String, Any > ) = dataSnapshot.value as(Map < String, Any > )

        if (map["profileImageUrl"] != null) {
          Glide.with(CustomerActivity().application).load(map["profileImageUrl"].toString()).into(CustomerActivity().mNavigationHeaderImage)
        }

        if (map["name"] != null) {
          CustomerActivity().mNavigationHeaderText.text = map["name"].toString()
        }

        if (map["hasCarInfo"] != null) {
          CustomerActivity().hasInfo = map["hasInfo"].toString().toBoolean()
        }
      }
    }
}

CustomerActivity.kt (Просмотр и активность)

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setContentView(R.layout.my_activity)

   (...)

   // load all UI settings
   handleUI()

   // Update User Info
   CustomerDatabase().getUserInfo(mAuth.currentUser!!.uid)
}

override fun onStart(savedInstanceState: Bundle?) {
   super.onStart()
   (...)
   // Update User Info
   CustomerDatabase().getUserInfo(mAuth.currentUser!!.uid)
}

mNavigationHeaderImage импортируется из xml (ImageView)

mNavigationHeaderText импортируется из xml (TextView)

hasInfo - это переменная, используемая для проверки того, есть ли у пользователя информация или нужно по умолчанию выбрать значение false

1 Ответ

0 голосов
/ 06 февраля 2020

Ваша проблема в том, что в вашем getUserInfo вы пытаетесь обновить некоторые текстовые файлы вашего activity, используя следующее понятие

CustomerActivity().mNavigationHeaderText.text = map["name"].toString()

Проблема c Дело в том, что вы пытаетесь создать instance вашего activity с использованием CustomerActivity(). Это неправильно, потому что в Android Instance из activities создаются Android SDK.

Так как вы используете instance вашего activity?

Как вы, наверное, знаете, activities имеет определенный Жизненный цикл , поэтому после создания instance ваших activity и initialization, Android звонки lifecycle functions, такие как onCreate и onRestart, в этих функциях this относится к instance.

* 1042 вашей деятельности * Окончательное решение вашей проблемы - это LiveData , прочитайте это , чтобы узнать о LiveData.

Ниже приведены два альтернативных решения, оба они будут работать, но если вы можете настроить свой проект для использования LiveData, тогда избегайте следующего.

Чтобы решить вашу проблему, простая, но неправильная вещь будет , чтобы сделать следующее, здесь вы передаете instance из activity как parameter в getUserInfo

CustomerDatabase().getUserInfo(this, mAuth.currentUser!!.uid)

Вторым подходом будет использование callback interface. поэтому в своей деятельности определите интерфейс следующим образом:

interface Callback {
   fun onFinished(map: Map <String, Any> )
}

Теперь измените ваш activity для реализации этого interface, поэтому в вашем activity вы будете иметь следующую функцию

onFinished(map: Map <String, Any> ){
    // use map to set your data
}

После этого измените ваш getUserInfo, чтобы он принял параметр типа Callback, и этот обратный вызов будет вызываться getUserInfo при получении данных.

internal fun getUserInfo(uid: String, callback: Callback) {
  mUserDatabase = FirebaseDatabase.getInstance().reference.child("Users").child("Customers").child(uid)
  mCustomerDatabase.addValueEventListener(object: ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
      if (dataSnapshot.exists() && dataSnapshot.childrenCount > 0) {
          val map: (Map < String, Any > ) = dataSnapshot.value as(Map < String, Any > )
          /** When data is available, pass it to activity by calling the callback */
          callback.onFinished(map);
      }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...