Issue
Sometimes when my Xamarin.Android app gets killed and the application needs to recreate its main activity some layouts are not available and the screen displays no views.
By pressing the device back button and then reopening the application, its main activity gets correctly instantiated and displayed.
This is the code responsible for loading the used layouts:
// 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);
See next screenshots (texts were omitted):
Before/after the system automatically recreates the activity.
I am using:
- Xamarin.Android 4.10
- MvvmCross 3.0.13 - Android.Dialog
May some of you point me a direction about how can I fix this issue? I am new to both described technologies. Any help will be appreciated.
Logs retrieved from the DDMS application:
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
I would like to understand why the DroidResources class was initialized when normally opening the application but it is not initialized when the application is just returning from the background. I guess during the background time Android forced its instance to be garbage collected but not the entire application.
I also think I may be wrongly initializing it, that is my Setup.cs
file:
/// <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));
}
}
Until now I am just using the Android.Dialog dlls from the MvvmCross library. But I am going to start accordingly using ViewModels as soon as possible.
Here follows the ApplicationMainActivity source code:
/// <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));
}
}
...
Solution
As you post layer-upon-layer of code in this question, I'm getting increasingly more confused about whether you are actually using MvvmCross.
If you are just using the MvvmCross Android.Dialog port - and not using MvvmCross - then you need to find a way to do for what the error message is asking you to do:
You must call DroidResources.Initialize(Resource.Layout) before using Dialogs
In a "normal" MvvmCross application, this problem is avoided because any MvxActivity
will ensure Setup
is created and initialised before OnCreate
is complete - and Setup
includes:
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);
}
If you want to implement non-MvxActivity
Activities, then you'll need to find some other way to ensure setup is started and/or droid resources are loaded.
Answered By - Stuart
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.