I am working on a Xamarin.Forms Android Project that displays images one after another on a press of a button. My current test device is an HTC Nexus 9 and apparently, due to its limited specs, i get below error when trying to load my 17th image:
java.lang.OutOfMemoryError: Failed to allocate a 11059212 byte allocation with 8286168 free bytes and 7MB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1155)
at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:720)
at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:571)
at android.content.res.Resources.getDrawable(Resources.java:771)
at android.content.Context.getDrawable(Context.java:525)
at androidx.core.content.ContextCompat.getDrawable(ContextCompat.java:455)
at androidx.appcompat.widget.ResourceManagerInternal.getDrawable(ResourceManagerInternal.java:144)
at androidx.appcompat.widget.ResourceManagerInternal.getDrawable(ResourceManagerInternal.java:132)
at androidx.appcompat.content.res.AppCompatResources.getDrawable(AppCompatResources.java:104)
at crc64ee486da937c010f4.ButtonRenderer.n_onClick(Native Method)
at crc64ee486da937c010f4.ButtonRenderer.onClick(ButtonRenderer.java:104)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22433)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
I tried setting the Java Max Heap Size
to 1G
under .Android > Properties > Android Options > Advanced
but nothing changed.
I found a potential solution here but apparently, its for Java based Android App and i don't know where to find a similar manifest file on Xamarin.Forms` Android Project.
Below is a snippet of my code using the simplest MVVM implementation:
.xaml
<Image Source="{Binding ImgSource}"
WidthRequest="960"
HeightRequest="720" />
<!--#region Page1 Controls-->
<Button Command="{Binding Page1DhcpIconCommand}"
IsVisible="{Binding Page1ControlVisible}"
BackgroundColor="{Binding Page1ControlColor}"
Opacity="0.25"
RelativeLayout.XConstraint="57"
RelativeLayout.YConstraint="679"
RelativeLayout.WidthConstraint="46"
RelativeLayout.HeightConstraint="37" />
<!--#endregion-->
<!--#region Page2 Controls-->
<Button Command="{Binding Page2RolesCommand}"
IsVisible="{Binding Page2ControlVisible}"
BackgroundColor="{Binding Page2ControlColor}"
Opacity="0.25"
RelativeLayout.XConstraint="24"
RelativeLayout.YConstraint="85"
RelativeLayout.WidthConstraint="46"
RelativeLayout.HeightConstraint="15" />
<!--#endregion-->
<!--#region Page3 Controls-->
<Button Command="{Binding Page3AddRolesCommand}"
IsVisible="{Binding Page3ControlVisible}"
BackgroundColor="{Binding Page3ControlColor}"
Opacity="0.25"
RelativeLayout.XConstraint="720"
RelativeLayout.YConstraint="199"
RelativeLayout.WidthConstraint="71"
RelativeLayout.HeightConstraint="21" />
<!--#endregion-->
ViewModel.cs
#region Backing Fields
string imgSource;
bool page1ControlVisible;
string page1ControlColor;
bool page2ControlVisible;
string page2ControlColor;
bool page3ControlVisible;
string page3ControlColor;
#endregion
#region Private Variables
private readonly bool _transparentOverride;
#endregion
#region Public Properties
public string ImgSource
{
get => imgSource;
set => SetProperty(ref imgSource, value);
}
#region Page1 Properties & Commands
public bool Page1ControlVisible
{
get => page1ControlVisible;
set => SetProperty(ref page1ControlVisible, value);
}
public string Page1ControlColor
{
get => page1ControlColor;
set => SetProperty(ref page1ControlColor, value);
}
public Command Page1DhcpIconCommand { get; }
#endregion
#region Page2 Properties & Commands
public bool Page2ControlVisible
{
get => page2ControlVisible;
set => SetProperty(ref page2ControlVisible, value);
}
public string Page2ControlColor
{
get => page2ControlColor;
set => SetProperty(ref page2ControlColor, value);
}
public Command Page2RolesCommand { get; }
#endregion
#region Page3 Properties & Commands
public bool Page3ControlVisible
{
get => page3ControlVisible;
set => SetProperty(ref page3ControlVisible, value);
}
public string Page3ControlColor
{
get => page3ControlColor;
set => SetProperty(ref page3ControlColor, value);
}
public Command Page3AddRolesCommand { get; }
#endregion
#endregion
public DHCPConfigurationViewModel()
{
_transparentOverride = true;
ImgSource = "img_dhcp_config_01.jpg";
#region Page1 Properties & Commands
Page1ControlVisible = true;
Page1ControlColor = _transparentOverride ? "Transparent" : "Red";
Page1DhcpIconCommand = new Command(Page1DhcpIcon);
#endregion
#region Page2 Properties & Commands
Page2ControlVisible = false;
Page2ControlColor = _transparentOverride ? "Transparent" : "Orange";
Page2RolesCommand = new Command(Page2Roles);
#endregion
#region Page3 Properties & Commands
Page3ControlVisible = false;
Page3ControlColor = _transparentOverride ? "Transparent" : "Yellow";
Page3AddRolesCommand = new Command(Page3AddRoles);
#endregion
}
private void Page1DhcpIcon()
{
ImgSource = "img_dhcp_config_02.jpg";
Page1ControlVisible = false;
Page2ControlVisible = true;
}
private void Page2Roles()
{
ImgSource = "img_dhcp_config_03.jpg";
Page2ControlVisible = false;
Page3ControlVisible = true;
}
private void Page3AddRoles()
{
ImgSource = "img_dhcp_config_04.jpg";
Page3ControlVisible = false;
Page4ControlVisible = true;
}