1

有时,当我的Xamarin.Android应用程序被杀并且应用程序需要重新创建其主要活动时,某些布局不可用,并且屏幕不显示任何视图。无效的布局资源

通过按设备返回按钮,然后重新打开应用程序,其主要活动得到正确实例化和显示。

这是负责加载用于布局代码:

// Returns null whenever trying to recreate views right after the application got killed by Android (Due to some multi-tasking reasons). Otherwise, it returns valid instances. 
var layout = DroidResources.LoadLayout (context, parent, layoutName); 

见下截图(文中略):

前/后系统将自动重新创建活动。

Before After

我使用:

  • Xamarin.Android 4.10
  • MvvmCross 3.0.13 - Android.Dialog

可能有些你点我一个方向关于如何解决这个问题? 我对这两种描述的技术都很陌生。任何帮助将不胜感激。从DDMS应用程序检索


日志:

E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): ViewElement: Failed to load resource: MenuSeparator 
E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): LoadLayout failed: You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 
E/Android.Dialog(9171): ViewElement: Failed to load resource: MenuSeparator 

我想明白为什么当正常打开应用程序的DroidResources类被初始化,但它没有被初始化当应用程序只是从背景返回。我猜在后台时间Android强制它的实例被垃圾收集,但不是整个应用程序。

我也觉得我可能是错初始化它,那是我Setup.cs文件:

/// <summary> 
/// MvvmCross setup class. 
/// Allows Android.Dialog usage during application lifecycle 
/// </summary> 
public class Setup : MvxAndroidDialogSetup 
{ 
    public Setup (Context applicationContext) 
     : base (applicationContext) 
    { 
    } 

    protected override IMvxApplication CreateApp() 
    { 
     return new MvvmCrossApplication(); 
    } 
} 


// MvvmCross internal application. 
public class MvvmCrossApplication : MvxApplication 
{ 
    public override void Initialize() 
    { 
     // Setup initial application view which will be loaded as soon as the MvvmCross framework 
     // initialization has been completed. 
     RegisterAppStart<ApplicationViewModel>(); 
    } 
} 

// 
// These next classes ApplicationViewModel and ApplicationView are auxiliary classes 
// needed by the MvvmCross framework to ensure that others application classes are loaded 
// only after the MvvmCross initilization has been completed. 
public class ApplicationViewModel : MvxViewModel 
{ 
} 

[Activity (Theme = "@style/Theme.Transparent", NoHistory = true)] 
public class ApplicationView : MvxActivity 
{ 
    protected override void OnResume() 
    { 
     base.OnResume(); 

     // Start the application main activity. 
     StartActivity (typeof(ApplicationMainActivity)); 
    } 
} 

直到现在我只是用从MvvmCross库Android.Dialog的DLL。但是我会尽快使用ViewModel来启动。

这里遵循ApplicationMainActivity源代码:

/// <summary> 
/// Application activity. 
/// </summary> 
/// <remarks>A transparent activity used to recreate current application screens workflow.</remarks> 
[Activity (Theme = "@style/Theme.Transparent", NoHistory = true)] 
public class ApplicationMainActivity : ClientUserActivity 
{ 
    #region Lifecycle methods 

    protected override void OnCreate (Bundle bundle) 
    { 
     base.OnCreate (bundle); 

     if (ClientUser.IsLoggedIn()) { 

      if (ClientUser.ShouldShowWizard()) { 

        // Show the wizard screen 
        StartActivity (wizardActivity); 

       } else { 

        // Show the main menu screen 
        StartActivity (typeof(NavigationDrawerActivity)); 
       } 

     } else { 
      // Show the welcome screen 
      StartActivity (typeof(WelcomeActivity)); 
     } 
    } 
    ... 
+0

什么'var layout = DroidResources.LoadLayout(context,parent,layoutName);'确实做? – Cheesebaron

+0

嗨@Cheesebaron,这里遵循DroidResources类的源代码:https://github.com/MvvmCross/MvvmCross/blob/162a816d148df224df0b8f635aeafe30c0910de9/CrossUI/CrossUI.Droid/DroidResources.cs它应该使用分配的layoutName加载Android布局。 – georgepiva

+0

什么是“ApplicationMainActivity”,为什么每次ApplicationView活动恢复时都要启动它? – Stuart

回答

3

正如你在这个问题张贴层在层的代码,我得到越来越多的困惑,你是否实际使用MvvmCross。

如果您只是使用MvvmCross Android。对话口 - 而不是使用MvvmCross - 那么你需要找到一种方式,做了错误信息,要求你做:

You must call DroidResources.Initialize(Resource.Layout) before using Dialogs 

在一个“正常” MvvmCross应用程序,就可以避免这个问题,因为任何MvxActivity将确保SetupOnCreate之前创建和初始化完成了 - Setup包括:

protected virtual void InitializeDialogBinding() 
    { 
     var finder = Mvx.Resolve<IMvxAppResourceTypeFinder>(); 
     var resourceType = finder.Find(); 
     var nestedResourceType = resourceType.GetNestedTypes().FirstOrDefault(x => x.Name == "Layout"); 
     DroidResources.Initialize(nestedResourceType); 
    } 

看到https://github.com/MvvmCross/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Dialog.Droid/MvxAndroidDialogSetup.cs#L40

如果你想实现non-MvxActivity活动,那么你需要找到一些其他方式来确保启动设置和/或加载droid资源。