Mvvmcross:无法创建偏好活动

时间:2017-09-26 14:04:24

标签: android mvvmcross

我正在开发一个与MvvmCross一起运行的Xamarin项目。我试图在Android中添加偏好视图,但我无法让它工作。

当我尝试导航到MvxPreferenceFragment时,我收到以下错误:

[0:] mvx:Diagnostic: 12.11 Activity host with ViewModelType PreferenceTest.Droid.Activities.MainPreferenceActivity is not CurrentTopActivity. Showing Activity before showing Fragment for PreferenceTest.Core.ViewModels.Fragments.PreferenceViewModel
An unhandled exception occured.

09-26 13:54:45.753 I/MonoDroid(12779): UNHANDLED EXCEPTION:
09-26 13:54:45.810 I/MonoDroid(12779): System.Collections.Generic.KeyNotFoundException: Could not find view for PreferenceTest.Droid.Activities.MainPreferenceActivity
09-26 13:54:45.810 I/MonoDroid(12779):   at MvvmCross.Core.Views.MvxViewsContainer.GetViewType (System.Type viewModelType) [0x0006a] in C:\projects\mvvmcross\MvvmCross\Core\Core\Views\MvxViewsContainer.cs:72 
09-26 13:54:45.810 I/MonoDroid(12779):   at MvvmCross.Droid.Support.V7.AppCompat.MvxAppCompatViewPresenter.ShowHostActivity (MvvmCross.Droid.Views.Attributes.MvxFragmentPresentationAttribute attribute) [0x00000] in C:\projects\mvvmcross\MvvmCross-AndroidSupport\MvvmCross.Droid.Support.V7.AppCompat\MvxAppCompatViewPresenter.cs:166 
09-26 13:54:45.810 I/MonoDroid(12779):   at MvvmCross.Droid.Support.V7.AppCompat.MvxAppCompatViewPresenter.ShowFragment (System.Type view, MvvmCross.Droid.Views.Attributes.MvxFragmentPresentationAttribute attribute, MvvmCross.Core.ViewModels.MvxViewModelRequest request) [0x0007d] in C:\projects\mvvmcross\MvvmCross-AndroidSupport\MvvmCross.Droid.Support.V7.AppCompat\MvxAppCompatViewPresenter.cs:196 
09-26 13:54:45.810 I/MonoDroid(12779):   at MvvmCross.Droid.Views.MvxAndroidViewPresenter.<RegisterAttributeTypes>b__39_2 (System.Type view, MvvmCross.Core.Views.MvxBasePresentationAttribute attribute, MvvmCross.Core.ViewModels.MvxViewModelRequest request) [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewPresenter.cs:188 
09-26 13:54:45.810 I/MonoDroid(12779):   at MvvmCross.Droid.Views.MvxAndroidViewPresenter.Show (MvvmCross.Core.ViewModels.MvxViewModelRequest request) [0x00055] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewPresenter.cs:295 
09-26 13:54:45.810 I/MonoDroid(12779):   at MvvmCross.Droid.Views.MvxAndroidViewDispatcher+<>c__DisplayClass2_0.<ShowViewModel>b__0 () [0x00000] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewDispatcher.cs:26 
09-26 13:54:45.810 I/MonoDroid(12779):   at MvvmCross.Droid.Views.MvxAndroidMainThreadDispatcher.RequestMainThreadAction (System.Action action, System.Boolean maskExceptions) [0x00020] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidMainThreadDispatcher.cs:20 
09-26 13:54:45.811 I/MonoDroid(12779):   at MvvmCross.Droid.Views.MvxAndroidViewDispatcher.ShowViewModel (MvvmCross.Core.ViewModels.MvxViewModelRequest request) [0x00014] in C:\projects\mvvmcross\MvvmCross\Droid\Droid\Views\MvxAndroidViewDispatcher.cs:26 
09-26 13:54:45.811 I/MonoDroid(12779):   at MvvmCross.Core.Navigation.MvxNavigationService+<Navigate>d__32.MoveNext () [0x0003a] in C:\projects\mvvmcross\MvvmCross\Core\Core\Navigation\MvxNavigationService.cs:179 
09-26 13:54:45.811 I/MonoDroid(12779): --- End of stack trace from previous location where exception was thrown ---
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at MvvmCross.Core.Navigation.MvxNavigationService+<Navigate>d__40.MoveNext () [0x00078] in C:\projects\mvvmcross\MvvmCross\Core\Core\Navigation\MvxNavigationService.cs:293 
09-26 13:54:45.811 I/MonoDroid(12779): --- End of stack trace from previous location where exception was thrown ---
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at PreferenceTest.Core.ViewModels.FirstViewModel+<ExecutePreferences>d__8.MoveNext () [0x00026] in C:\git\PreferenceTest\PreferenceTest\PreferenceTest\PreferenceTest.Core\ViewModels\FirstViewModel.cs:28 
09-26 13:54:45.811 I/MonoDroid(12779): --- End of stack trace from previous location where exception was thrown ---
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__6_0 (System.Object state) [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in <2e14bb2dd93a405e81838369ed72695b>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in <2e14bb2dd93a405e81838369ed72695b>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <2e14bb2dd93a405e81838369ed72695b>:0 
09-26 13:54:45.811 I/MonoDroid(12779):   at (wrapper dynamic-method) System.Object:a278159c-f25c-4da4-ac29-d4bae0d2de73 (intptr,intptr)

这是我试图运行的代码(有关完整代码,请参阅下面的github链接): 首先,我在xml文件夹(名为preference.xml)

中创建了一个视图
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
  <EditTextPreference android:title="Your Name"
                      android:key="username"
                      android:summary="Please provide your username"></EditTextPreference>
  <CheckBoxPreference android:title="Application Updates"
                      android:defaultValue="false"
                      android:summary="This option if selected will allow the application to check for latest versions."
                      android:key="applicationUpdates" />
  <ListPreference     android:title="Download Details"
                      android:summary="Select the kind of data that you would like to download"
                      android:key="downloadType"
                      android:defaultValue="1"
                      android:entries="@array/listArray"
                      android:entryValues="@array/listValues" />
  <CheckBoxPreference
    android:key="prefer wifi"
    android:title="Prefer WiFi" />
</PreferenceScreen>

片段代码:

[MvxFragmentPresentation(typeof(MainPreferenceActivity), Resource.Id.content_frame, true)]
[Register(nameof(PreferenceFragment))]
public class PreferenceFragment : MvxPreferenceFragment<PreferenceViewModel>
{
    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        base.OnCreateView(inflater, container, savedInstanceState);
        var view = this.BindingInflate(Resource.Xml.preferences, container, false);
        return view;
    }
}

使用导航服务进行呼叫:

private async void ExecutePreferences()
{
    await _navigationService.Navigate<PreferenceViewModel>();
}

我找不到此代码的错误:)。

以下是样本的a github link

1 个答案:

答案 0 :(得分:5)

第一个问题是使用MvxFragmentPresentation第一个参数是用于主机活动的ViewModel的类型,而不是活动本身的类型。在您的情况下,MainPreferenceViewModel

下一个问题是,当您使用MvxAppCompatViewPresenter演示者时,您需要使用MvxPreferenceFragmentCompatMvxPreferenceFragmentCompat可以在MvvmCross.Droid.Support.V7.Preference NuGet包中找到。

[MvxFragmentPresentation(typeof(MainPreferenceViewModel), Resource.Id.content_frame)]
[Register(nameof(PreferenceFragment))]
public class PreferenceFragment : MvxPreferenceFragmentCompat<PreferenceViewModel>
{
    public override void OnCreatePreferences(Bundle savedInstanceState, string rootKey)
    {
        SetPreferencesFromResource(Resource.Xml.preferences, rootKey);
    }
}

最后,您需要为活动中的偏好设置主题

<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>

我已经使用Xamarin.Android.Support.v14.Preference中的材料设计主题,但你也可以使用其中一个:

  • @style/PreferenceThemeOverlay
  • @style/PreferenceThemeOverlay.v14

有关更改的完整详情,请参阅pull request

MvxPreferenceFragmentCompat example