maui icon indicating copy to clipboard operation
maui copied to clipboard

[Android] Fix app crash caused by dynamic template switching in ListView

Open BagavathiPerumal opened this issue 1 year ago • 18 comments

Exception I – Object reference not set to an instance of an object at GraphicsExtensions.AsColor :

During the execution of the device test case - ChangingTemplateTypeDoesNotCrash, a fatal exception was thrown, causing a crash.

Root Cause

The root cause of the NullReferenceException was identified as a failure to check for a valid context or color before calling the AsColor method. Specifically, the line of code responsible for this was:

var color = Current?.Windows?.Count > 0 
            ? Current.Windows[0].MauiContext.Context?.GetAccentColor() 
            : null;

In the UpdateSeparatorColor method, when returning null for Application.AccentColor , the method requests: bline.SetBackgroundColor(separatorColor.ToPlatform(Application.AccentColor)); Since no default separator color was set, this led to the issue. The failure was particularly observed in our test case that enabled grouping, which is why only the ChangingTemplateTypeDoesNotCrash test case was failing.

Description of Change

To resolve this issue, the following modifications were implemented in the relevant code segment:

Default Color Implementation: A fallback mechanism was implemented to provide a default color (e.g., Color.FromRgba(50, 79, 133, 255)) when the window.count resource is unavailable. This approach prevents the application from crashing and ensures that the UI continues to function smoothly even in command line device test cases.

Exception II – The specified child already has a parent. you must call removeView() on the child’s parent first at ViewGroup.addViewInner.

Root cause

In the ViewCellRenderer class, the platform view was being recreated for each cell without properly removing the existing parent view (i.e., the ViewCellContainer ) before attempting to add the new view. This caused an exception:'The specified child already has a parent. You must call removeView() on the child's parent first. 'The issue arose due to improper handling of the platform view's parent when switching between different DataTemplates in a ListView using the RetainElement caching strategy in .NET MAUI.

Description of Issue Fix

The fix involved checking if the platformView already had a parent (i.e., ViewGroup) and ensuring that the parent was removed before adding the platformView to the new container. By introducing this conditional check, the system prevents the platform view from being associated with multiple parents, which caused the "The specified child already has a parent" exception. This change ensures that dynamic template changes in the ListView are handled correctly, improving view recycling and maintaining stable rendering without conflicts.

Tested the behavior in the following platforms.

  • [x] Android
  • [x] Windows
  • [x] iOS
  • [x] Mac

Issues Fixed

Fixes #24701

Output

Before fix:

ListView_BeforeFix

After fix:

ListView_AfterFix

Testcase:

The Testcase is already available for this fix. Please refer to the PR link below for reference.

Clear out prototype cell when changing ItemSource by PureWeen · Pull Request #24700 · dotnet/maui (github.com)

BagavathiPerumal avatar Sep 17 '24 15:09 BagavathiPerumal

/azp run

PureWeen avatar Sep 18 '24 13:09 PureWeen

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Sep 18 '24 13:09 azure-pipelines[bot]

Can you re-enable this device test for android?

https://github.com/dotnet/maui/pull/24700/files#diff-9ef75bbb1d7dbaf152e43bba50d7dfc6ed46b9db1b351e0ff5da3272718f811aR36-R41

@PureWeen, I have modified changes. Could you please validate it once and let me know if there are any further concerns.

BagavathiPerumal avatar Sep 23 '24 06:09 BagavathiPerumal

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Sep 23 '24 07:09 azure-pipelines[bot]

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Sep 25 '24 11:09 azure-pipelines[bot]

/rebase

jfversluis avatar Sep 27 '24 12:09 jfversluis

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Sep 27 '24 12:09 azure-pipelines[bot]

/rebase

praveenkumarkarunanithi avatar Oct 03 '24 11:10 praveenkumarkarunanithi

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Oct 03 '24 12:10 azure-pipelines[bot]

Looks like the test is failing

09-23 03:31:56.106  4471  4471 E AndroidRuntime: FATAL EXCEPTION: main
09-23 03:31:56.106  4471  4471 E AndroidRuntime: Process: com.microsoft.maui.controls.devicetests, PID: 4471
09-23 03:31:56.106  4471  4471 E AndroidRuntime: android.runtime.JavaProxyThrowable: [System.NullReferenceException]: Object reference not set to an instance of an object.
09-23 03:31:56.106  4471  4471 E AndroidRuntime: 	at Microsoft.Maui.Graphics.Platform.GraphicsExtensions.AsColor(Unknown Source:0)
09-23 03:31:56.106  4471  4471 E AndroidRuntime: 	at Microsoft.Maui.Platform.ColorExtensions.ToPlatform(Unknown Source:0)
09-23 03:31:56.106  4471  4471 E AndroidRuntime: 	at Microsoft.Maui.Platform.ColorExtensions.ToPlatform(Unknown Source:0)
09-23 03:31:56.106  4471  4471 E AndroidRuntime: 	at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewAdapter.UpdateSeparatorColor(Unknown Source:0)
09-23 03:31:56.106  4471  4471 E AndroidRuntime: 	at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewAdapter.GetView(Unknown Source:0)
09-23 03:31:56.106  4471  4471 E AndroidRuntime: 	at Microsoft.Maui.Controls.Handlers.Compatibility.ListViewRenderer.GetDesiredSize(Unknown Source:0)
09-23 03:31:56.106  4471  4471 E AndroidRuntime: 	at Microsoft.Maui.Controls.Handlers.Compatibility.VisualElementRenderer`1[[Microsoft.Maui.Controls.ListView, Microsoft.Maui.Controls, Version=1.0.0.0, Culture=neutral, 

@PureWeen, The test failure is caused by the UpdateSeparatorColor method, which calls the default separator color through Application.AccentColor. We have addressed this issue by implementing a fix at this line of code, where a default color is now provided to prevent a NullReferenceException.

BagavathiPerumal avatar Oct 11 '24 09:10 BagavathiPerumal

/azp run

jsuarezruiz avatar Oct 11 '24 11:10 jsuarezruiz

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Oct 11 '24 11:10 azure-pipelines[bot]

/rebase

praveenkumarkarunanithi avatar Oct 14 '24 09:10 praveenkumarkarunanithi

/azp run

jsuarezruiz avatar Oct 14 '24 10:10 jsuarezruiz

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Oct 14 '24 10:10 azure-pipelines[bot]

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Oct 16 '24 13:10 azure-pipelines[bot]

/azp run

jsuarezruiz avatar Oct 24 '24 14:10 jsuarezruiz

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Oct 24 '24 14:10 azure-pipelines[bot]

/azp run

jsuarezruiz avatar Oct 28 '24 11:10 jsuarezruiz

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Oct 28 '24 11:10 azure-pipelines[bot]

/azp run

jsuarezruiz avatar Oct 30 '24 08:10 jsuarezruiz

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Oct 30 '24 08:10 azure-pipelines[bot]

/rebase

praveenkumarkarunanithi avatar Nov 04 '24 08:11 praveenkumarkarunanithi

/azp run

jsuarezruiz avatar Nov 06 '24 10:11 jsuarezruiz

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Nov 06 '24 10:11 azure-pipelines[bot]

/rebase

praveenkumarkarunanithi avatar Nov 12 '24 09:11 praveenkumarkarunanithi

/azp run

jsuarezruiz avatar Nov 12 '24 11:11 jsuarezruiz

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Nov 12 '24 11:11 azure-pipelines[bot]