Массив словарей с базой данных Unity и Firebase - Получить значения из ключа - PullRequest
0 голосов
/ 02 января 2019

Прежде всего - я довольно новичок в Unity.

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

Итак ... Мой способ сделать это:

1: Создать массив словарей для хранения моих данных:

[System.Serializable]
public class Global
{
   public static Dictionary<string, object>[] offers;
}

2: обработать данные из базы данных и сохранить их в массиве:

void Handle_ChildAdded(object sender, ChildChangedEventArgs e)
    {
        if (e.DatabaseError != null)
        {
            Debug.LogError(e.DatabaseError.Message);
            return;
        }
        // Do something with the data in args.Snapshot
        if (e.Snapshot.Value != null)
        {
            var dict = e.Snapshot.Value as Dictionary<string, object>;

            if (dict != null)
            {
                Debug.Log(dict);
                Global.offers = new Dictionary<string, object>[Global.storesCount+1];
                Global.offers[Global.storesCount] = dict;
                Global.storesCount++;
                hasHaded = true;
            }
        }
    }

Итак, теперь я поместил снимки из моей базы данных в мой массив Global.offers. Структура снимка, который я должен выглядеть примерно так: enter image description here

Время показывать данные из моего массива

До этого момента все работало нормально - потому что теперь мне нужно показать только что сохраненные данные в моем массиве Global.offers. Я пытаюсь сделать это с помощью цикла. Я зацикливаю массив и ищу ключи в моей базе данных и создаю данные внутри префаба игрового объекта , например:

 for (int i = 0; i < Global.storesCount; i++)
        {
            Transform scrollViewObj = Instantiate(prefab, new Vector3(0, (downSize * i) - firstY, 0), Quaternion.identity);
            scrollViewObj.transform.SetParent(scrollContent.transform, false);
            scrollViewObj.transform.Find("Overskift").gameObject.GetComponent<Text>().text = Global.offers[i]["Store"] as string;
            scrollViewObj.transform.Find("Text (1)").gameObject.GetComponent<Text>().text = Global.offers[i]["Headline"] as string;
            scrollViewObj.transform.Find("Text (2)").gameObject.GetComponent<Text>().text = "Din pris: " + Global.offers[i]["Price"] as string + " kr.";
            scrollViewObj.transform.Find("Text (3)").gameObject.GetComponent<Text>().text = "Spar: " + Global.offers[i]["AndresPris"] as string + " kr.";
        }

Вот тут у меня проблема. По некоторым причинам Global.offers [i] ["Store"] как string == null, ведь конечно, это означает, что я не могу создать экземпляр объекта. Я получаю эту ошибку:

NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта LoadOffers.Start () (в разделе Активы / Сценарии / LoadOffers.cs: 36)

Это так странно, потому что, когда я пытаюсь отладить, я получаю противоречивые результаты:

Длина массива равна 19. Так что он не пустой.

Когда я пытаюсь отладить. Выгрузить массив, я получаю:

System.Collections.Generic.Dictionary`2 [System.String, System.Object] []

Но когда я ищу значения с ключами вроде:

Debug.Log(Global.offers[0]["Store"]);

Все, что я получаю, равно нулю. Я неправильно ищу после значений? Или кто-нибудь еще может увидеть, что я делаю не так?

1 Ответ

0 голосов
/ 03 января 2019

Проблема

Ваша основная проблема в том, что Global.offers является массивом и поэтому имеет фиксированную длину и не может быть динамически увеличена настолько просто (вам придется копировать массив каждый раз!)

Вы пытались решить эту проблему в Handle_ChildAdded, но в строке

Global.offers = new Dictionary<string, object>[Global.storesCount+1];

на самом деле вы создаете новый пустой (!) Массив словарей длиной Global.storeCount+1.Вы не копируете текущие значения в новый массив.

, поэтому после всех выполнений вы получаете массив только с null.Только последний элемент массива будет иметь содержимое, поступающее из

Global.offers[Global.storeCount] = dict;

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

{null, null, null, null, ..., Dictionary<string, object> }

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

Global.offers[0]

, то есть null.


Solution

Я бы порекомендовал не использоватьмассив, но вместо этого List, который, в отличие от массива, может динамически расти

[System.Serializable]
public class Global
{
   public static List<Dictionary<string, object>> offers = new List<Dictionary<string, object>>();
}

, и, прежде чем начинать заполнять список, добавляя все словари, вы должны где-то вызвать

Global.offers.Clear();

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

И позже добавьте свои элементы в

void Handle_ChildAdded(object sender, ChildChangedEventArgs e)
{
    if (e.DatabaseError != null)
    {
        Debug.LogError(e.DatabaseError.Message);
        return;
    }
    // Do something with the data in args.Snapshot
    if (e.Snapshot.Value != null)
    {
        var dict = e.Snapshot.Value as Dictionary<string, object>;

        if (dict != null)
        {
            Debug.Log(dict);
            Global.offers.Add(dict);
            hasHaded = true;
        }
    }
}

Позже вы получите доступ к элементам в List так же, как в массиве

Debug.Log(Global.offers[0]["Store"]);

Обратите внимание, что вам также не нужна переменная storeCount ни в вашем решении - вы могли бы просто использовать

Global.offers.Length

, ни в этом новом решении - вы можете просто использовать

Global.offers.Count
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...