3

实际情况是,我在MvxViewTypeResolver类中添加了“Fragment”-Case,所以它看起来像这样:

 #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在这种情况下我必须添加一些东西吗?

谢谢您的帮助!

4

1 回答 1

2

先解释一下代码:

MvvmCross Binder 使用的自定义 XML 充气器工厂尝试以与标准 2.x Android XML 充气器非常相似的方式加载视图。

视图类型解析的默认代码确实在: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.. 如果您想添加更多缩写,请ViewNamespaceAbbreviationshttps://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross.Binding/Android/MvxBaseAndroidBindingSetup.cs中覆盖

  • 然后检查未缩写名称是否为非命名空间名称。如果是,则假定该类是 Android 命名空间并在其前面加上android.view.orandroid.widget.

  • 然后将完全命名空间的名称转换为全小写作为不区分大小写的查找键

  • 使用该小写键在所有加载的程序集中搜索从 View 派生的所有类型。

  • 缓存结果(无论是否为空)以加速后续的膨胀。

所有这些行为都旨在匹配http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.6_r1/android/中的默认 Android xml 视图膨胀代码视图/LayoutInflater.java#LayoutInflater.createViewFromTag%28java.lang.String%2Candroid.util.AttributeSet%29


有了这个解释 - 这是您问题的答案:


MvvmCross 目前还不包含任何 Fragment 支持。官方的 MonoDroid 片段支持本身仅在上周发布,我还没有任何人请求片段 - Android“片段化”似乎让大多数人回到基于 Activity 和 Dialog 的代码。

简而言之;查看文档,fragment这不是 Android 视图 - 看起来 Fragment 直接继承自 Java.Lang.Object - 请参阅http://developer.android.com/reference/android/app/Fragment.html

因此,MvvmCross ViewTypeResolver 目前无法处理片段。

我建议如果您今天需要 mvvmcross 和 Fragments,那么您最好的选择是用您自己的解析器替换默认解析器(使用 IoC) - 但我对此无法提供太多建议,因为我还没有完全阅读并了解http://developer.android.com/guide/topics/fundamentals/fragments.html上的 droid 文档

根据我在创建当前通货膨胀代码方面的经验,我认为您会在执行此操作时找到必要的源代码 - 例如,请参阅: 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.缩写命名空间中。

它们更有可能存在于您的 UI 应用程序命名空间或某些共享库中。

要查看实际的自定义视图,请参阅教程中的 PullToRefresh 示例 - https://github.com/slodge/MvvmCross/blob/master/Sample%20-%20Tutorial/Tutorial/Tutorial.UI.Droid/Resources/Layout /Page_PullToRefreshView.axml

于 2012-05-22T09:39:34.487 回答