Десериализация XML для встроенных ресурсов замедляет запуск приложений в Xamarin Forms - PullRequest
0 голосов
/ 09 ноября 2018

Я работаю над мобильным приложением с Xamarin Forms для устройств Android и iOS. Существует два файла XML (каждый размером около 12 МБ), которые содержат перевод между двумя языками. В настоящее время эти файлы являются встроенными ресурсами в общем проекте и десериализованы для использования внутри приложения. Я сделал (singleton) менеджер ресурсов для поиска переводов в этих файлах. Менеджер всегда запускает метод инициализации при запуске, чтобы десериализовать XML-файлы и предотвратить загрузку XML-файлов при каждом поиске слова. Это увеличивает время запуска; iOS на iPhone 8 занимает 7 секунд, а Android на Samsung galaxy S8 - 17 секунд.

Мои вопросы:

  1. Правильно ли использовать эти файлы в качестве встроенных ресурсов в общем проекте? Если нет, то как лучше всего минимизировать запуск?
  2. Является ли чтение и десериализация файлов XML лучшим способом использования этих файлов?

Обратите внимание, что я уже искал, но не пришел к какому-либо заключению с точки зрения опыта. Любой совет (особенно с некоторыми примерами) приветствуется.

Обновление:

Вот пример из файла XMl. Но имейте в виду, что в исходном XML-файле содержится более 50000 <word> тегов.

<?xml version="1.0" encoding="utf-8"?>
<MyDictionary>
    <word class="nn" comment="även samklang av andra sinnesintryck; allmänt &amp;quot;överensstämmelse&amp;quot;" lang="sv" value="harmoni">
        <translation comment="also used of harmony of other sensory impressions; generally, &amp;quot;agreement&amp;quot;" value="harmony" />
        <phonetic soundFile="harmoni.swf" value="harmonI:" />
        <paradigm>
            <inflection value="harmonien" />
            <inflection value="harmonier" />
        </paradigm>
        <synonym level="4.4" value="balans" />
        <synonym level="3.2" value="endräkt" />
        <synonym level="3.8" value="samklang" />
        <synonym level="3.3" value="samspel" />
        <synonym level="3.4" value="sämja" />
        <synonym level="3.0" value="välbefinnande" />
        <see type="saldo" value="harmoni||harmoni..1||harmoni..nn.1" />
        <example value="leva i harmoni med naturen">
            <translation value="be at one with Nature" />
        </example>
        <derivation inflection="harmoniskt" value="harmonisk">
            <translation value="harmonious; harmonic" />
        </derivation>
        <definition value="samklang av toner">
            <translation value="the simultaneous combination of musical tones" />
        </definition>
    </word>
</MyDictionary>

Для десериализации сначала была создана модель / объект файла XML с помощью функции Специальная вставка (Вставить XML как классы ) в Visual Studio. Затем для десериализации используется следующий метод.

private MyDictionary Load(string fileName)
{
    try
    {
        var ass = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
        var resourceName = $"LexinApp.XmlResources.{fileName}";
        using (Stream stream = ass.GetManifestResourceStream(resourceName))
        {
            using (StreamReader reader = new StreamReader(stream))
            {
                var serializer = new XmlSerializer(typeof(MyDictionary));
                return serializer.Deserialize(reader) as MyDictionary;
            }
        }
    }
    catch (Exception) { }

    return null;
}

После этого слово ищется по

var a = MyDictionary.word.Where(x => x.value == searchKey.ToLower()).ToList();

1 Ответ

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

Мое лучшее предположение заключается в том, что xmlserializer не самый быстрый в своем роде, тем более что ваш класс слов имеет некоторую сложность.

Как я уже предлагал в своем комментарии, вы можете значительно повысить производительность, отказавшись от сериализатора xml, написав собственный анализатор xml на основе XmlReader и протолкнув через него свои данные.

Другой (или дополнительной) идеей отсоединения сериализации вашего xml от времени запуска вашего приложения будет загрузка вашего xml в асинхронной фоновой задаче, поэтому вашему основному интерфейсу не придется его ждать, и, поскольку у вас есть два файла, Вы также можете попробовать загрузить их, используя параллельную многопоточность (используя System.Collections.Concurrent):

string[] xmlFileNames = new string[] { "filenameA.xml", "filenameB.xml" };

Parallel.ForEach(xmlFileNames, xmlFile =>
                    {
                        Load(xmlFile);
                    });
...