MvvmCross ViewTypeResolver не разрешает тег (фрагмент или пользовательский тип)

StackOverflow https://stackoverflow.com//questions/10698638

  •  12-12-2019
  •  | 
  •  

Вопрос

Реальная ситуация такова, что я добавил в MvxViewTypeResolver классифицируйте случай «Фрагмент», чтобы он выглядел так:

 #region Copyright
// <copyright file="MvxViewTypeResolver.cs" company="Cirrious">
// (c) Copyright Cirrious. http://www.cirrious.com
// This source is subject to the Microsoft Public License (Ms-PL)
// Please see license.txt on http://opensource.org/licenses/ms-pl.html
// All other rights reserved.
// </copyright>
// 
// Project Lead - Stuart Lodge, Cirrious. http://www.cirrious.com
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.Views;
using Cirrious.MvvmCross.Binding.Android.Interfaces.Binders;

namespace Cirrious.MvvmCross.Binding.Android.Binders
{
    public class MvxViewTypeResolver : IMvxViewTypeResolver
    {
        private Dictionary<string, Type> _cache = new Dictionary<string, Type>();

        public IDictionary<string, string> ViewNamespaceAbbreviations { get; set; }

        #region IMvxViewTypeResolver Members

        public virtual Type Resolve(string tagName)
        {
            Type toReturn;
            if (_cache.TryGetValue(tagName, out toReturn))
                return toReturn;

            var unabbreviatedTagName = UnabbreviateTagName(tagName);

            var longLowerCaseName = GetLookupName(unabbreviatedTagName);
            var viewType = typeof(View);

#warning AppDomain.CurrentDomain.GetAssemblies is only the loaded assemblies - so we might miss controls if not already loaded
            var query = from assembly in AppDomain.CurrentDomain.GetAssemblies()
                        from type in assembly.GetTypes()
                        where viewType.IsAssignableFrom(type)
                        where (type.FullName ?? "-").ToLowerInvariant() == longLowerCaseName
                        select type;

            toReturn = query.FirstOrDefault();
            _cache[tagName] = toReturn;

            return toReturn;
        }

        private string UnabbreviateTagName(string tagName)
        {
            var filteredTagName = tagName;
            if (ViewNamespaceAbbreviations != null)
            {
                var split = tagName.Split(new char[] {'.'}, 2, StringSplitOptions.RemoveEmptyEntries);
                if (split.Length == 2)
                {
                    var abbreviate = split[0];
                    string fullName;
                    if (ViewNamespaceAbbreviations.TryGetValue(abbreviate, out fullName))
                    {
                        filteredTagName = fullName + "." + split[1];
                    }
                }
            }
            return filteredTagName;
        }

        #endregion

        protected string GetLookupName(string tagName)
        {
            var nameBuilder = new StringBuilder();

            switch (tagName)
            {
                case "View":
                case "ViewGroup":
                    nameBuilder.Append("android.view.");
                    break;
                case "fragment":
                    nameBuilder.Append("android.app.");
                    break;
                default:
                    if (!IsFullyQualified(tagName))
                        nameBuilder.Append("android.widget.");
                    break;
            }

            nameBuilder.Append(tagName);
            return nameBuilder.ToString().ToLowerInvariant();
        }

        private static bool IsFullyQualified(string tagName)
        {
            return tagName.Contains(".");
        }
    }
}

Теперь он отправляет правильные longLowerCaseTagName (android.app.fragment), но в запросе он не может определить тип.

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

Также, если я добавлю собственный тип (присвоив тег Mvx.MyCustomType в axml) он не решается.Нужно ли мне что-то добавить в MvxBindingAttributes.xml в этом случае?

Спасибо за помощь!

Это было полезно?

Решение

Сначала объяснение кода:

Пользовательская фабрика надувателя XML, используемая MvvmCross Binder, пытается загрузить представления аналогично стандартному наполнителю XML для Android версии 2.x.

Код по умолчанию для разрешения типа представления действительно находится в: https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross.Binding/Android/Binders/MvxViewTypeResolver.cs

Если ваш xml содержит такое имя, как <MyCompany.MyProject.MyViews.MyFirstView /> затем преобразователь типа представления:

  • сначала проверяет сокращения и расширяет их до полных пространств имен. По умолчанию единственным известным сокращением является Mvx. который расширен до: Cirrious.MvvmCross.Binding.Android.Views..Если вы хотите добавить больше сокращений, переопределите ViewNamespaceAbbreviations в https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross.Binding/Android/MvxBaseAndroidBindingSetup.cs

  • затем проверяет, является ли несокращенное имя именем без пространства имен.Если это так, то предполагается, что класс является пространством имен Android, и добавляется к нему android.view. или android.widget.

  • затем преобразует полное имя в пространстве имен в строчные буквы в качестве ключа поиска без учета регистра

  • использует эту клавишу нижнего регистра для поиска всех типов, производных от View, во всех загруженных сборках.

  • кэширует результат (неважно, нулевой он или нет), чтобы ускорить последующие инфляции.

Все это поведение было разработано так, чтобы соответствовать коду инфляции представления Android xml по умолчанию в http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.6_r1/android/view/LayoutInflater.java#LayoutInflater.createViewFromTag%28java.lang.String% 2Candroid.util.AttributeSet%29


Если не считать этого объяснения, вот ответ на ваши вопросы:


MvvmCross в настоящее время не содержит поддержки фрагментов.Официальная поддержка фрагментов MonoDroid была выпущена только на прошлой неделе, и мне еще никто не запрашивал фрагменты - «фрагментация» Android, похоже, удерживает большинство людей от кода на основе действий и диалогов.

Коротко просматривая документацию, fragment не является представлением Android - похоже, что фрагмент наследуется непосредственно от Java.Lang.Object - см. http://developer.android.com/reference/android/app/Fragment.html

По этой причине MvvmCross ViewTypeResolver в настоящее время не может работать с фрагментами.

Я бы предположил, что если вам сегодня нужны и mvvmcross, и фрагменты, то лучше всего заменить преобразователь по умолчанию (с использованием IoC) на свой собственный преобразователь, но я не могу дать много советов по этому поводу, поскольку я еще не полностью прочитал и понял документацию по дроиду http://developer.android.com/guide/topics/fundamentals/fragments.html

Судя по моему опыту создания текущего кода инфляции, я думаю, что при этом вы найдете источник, необходимый для чтения - например.видеть : http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/view/LayoutInflater.java#LayoutInflater.createViewFromTag%28android.view.View% 2Cjava.lang.String%2Candroid.util.AttributeSet%29

Я не могу дать вам никакой информации о том, когда будет доступна официальная поддержка фрагментов mvvmcross — на данный момент это не запланировано.


Пользовательские представления поддерживаются, но обычно не размещаются в Mvx. сокращенное пространство имен.

Они с гораздо большей вероятностью будут жить в пространстве имен вашего приложения пользовательского интерфейса или в какой-либо общей библиотеке.

Чтобы увидеть настраиваемое представление в действии, см. пример PullToRefresh в руководстве: https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20Tutorial/Tutorial/Tutorial.UI.Droid/Resources/Layout/Page_PullToRefreshView.axml

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top