Skip to content

Commit 6191fcc

Browse files
authored
Merge pull request #13 from Redth/memory-analyzer-fixes
Memory analyzer fixes
2 parents 1939772 + 3fb3bd8 commit 6191fcc

File tree

8 files changed

+168
-100
lines changed

8 files changed

+168
-100
lines changed

Sample/VirtualListViewSample/Platforms/Android/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3-
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
3+
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
44
<application>
55
</application>
66
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Sample/VirtualListViewSample/VirtualListViewSample.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
<ItemGroup>
2828
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
2929
<PackageReference Include="LiteDb" Version="5.0.17" />
30+
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
31+
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
3032
</ItemGroup>
3133
<ItemGroup>
3234
<EmbeddedResource Include="chinook.litedb" />
Lines changed: 74 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using CoreGraphics;
22
using Foundation;
33
using Microsoft.Maui.Platform;
4+
using System.Diagnostics.CodeAnalysis;
45
using UIKit;
56

67
namespace Microsoft.Maui;
@@ -9,27 +10,41 @@ internal class CvCell : UICollectionViewCell
910
{
1011
public VirtualListViewHandler Handler { get; set; }
1112

12-
public NSIndexPath IndexPath { get; set; }
13+
public WeakReference<NSIndexPath> IndexPath { get; set; }
1314

1415
public PositionInfo PositionInfo { get; set; }
1516

16-
public Action<IView> ReuseCallback { get; set; }
17+
public WeakReference<Action<IView>> ReuseCallback { get; set; }
1718

1819
[Export("initWithFrame:")]
1920
public CvCell(CGRect frame) : base(frame)
2021
{
2122
this.ContentView.AddGestureRecognizer(new UITapGestureRecognizer(() => InvokeTap()));
2223
}
2324

24-
public Action<CvCell> TapHandler { get; set; }
25+
public WeakReference<Action<CvCell>> TapHandler { get; set; }
2526

26-
UIKeyCommand[] keyCommands;
27+
WeakReference<UIKeyCommand[]> keyCommands;
2728

28-
public override UIKeyCommand[] KeyCommands => keyCommands ??= new[]
29+
public override UIKeyCommand[] KeyCommands
2930
{
30-
UIKeyCommand.Create(new NSString("\r"), 0, new ObjCRuntime.Selector("keyCommandSelect")),
31-
UIKeyCommand.Create(new NSString(" "), 0, new ObjCRuntime.Selector("keyCommandSelect")),
32-
};
31+
get
32+
{
33+
if (keyCommands?.TryGetTarget(out var commands) ?? false)
34+
return commands;
35+
36+
var v = new[]
37+
{
38+
UIKeyCommand.Create(new NSString("\r"), 0, new ObjCRuntime.Selector("keyCommandSelect")),
39+
UIKeyCommand.Create(new NSString(" "), 0, new ObjCRuntime.Selector("keyCommandSelect")),
40+
};
41+
42+
keyCommands = new WeakReference<UIKeyCommand[]>(v);
43+
44+
return v;
45+
}
46+
47+
}
3348

3449
[Export("keyCommandSelect")]
3550
public void KeyCommandSelect()
@@ -40,54 +55,85 @@ public void KeyCommandSelect()
4055
void InvokeTap()
4156
{
4257
if (PositionInfo.Kind == PositionKind.Item)
43-
TapHandler?.Invoke(this);
58+
{
59+
if (TapHandler?.TryGetTarget(out var handler) ?? false)
60+
handler?.Invoke(this);
61+
}
62+
}
63+
64+
public void UpdateSelected(bool selected)
65+
{
66+
PositionInfo.IsSelected = selected;
67+
68+
if (VirtualView?.TryGetTarget(out var virtualView) ?? false)
69+
{
70+
if (virtualView is IPositionInfo positionInfo)
71+
{
72+
positionInfo.IsSelected = selected;
73+
virtualView.Handler?.UpdateValue(nameof(PositionInfo.IsSelected));
74+
}
75+
}
4476
}
4577

4678
public override UICollectionViewLayoutAttributes PreferredLayoutAttributesFittingAttributes(UICollectionViewLayoutAttributes layoutAttributes)
4779
{
48-
if (NativeView == null || VirtualView == null)
49-
return layoutAttributes;
80+
if ((NativeView is not null && NativeView.TryGetTarget(out var _))
81+
&& (VirtualView is not null && VirtualView.TryGetTarget(out var virtualView)))
82+
{
83+
var measure = virtualView.Measure(layoutAttributes.Size.Width, double.PositiveInfinity);
5084

51-
var measure = VirtualView.Measure(layoutAttributes.Size.Width, double.PositiveInfinity);
85+
layoutAttributes.Frame = new CGRect(0, layoutAttributes.Frame.Y, layoutAttributes.Frame.Width, measure.Height);
5286

53-
layoutAttributes.Frame = new CGRect(0, layoutAttributes.Frame.Y, layoutAttributes.Frame.Width, measure.Height);
87+
return layoutAttributes;
88+
}
5489

5590
return layoutAttributes;
5691
}
5792

5893
public bool NeedsView
59-
=> NativeView == null;
94+
=> NativeView == null || !NativeView.TryGetTarget(out var _);
6095

61-
public IView VirtualView { get; private set; }
96+
public WeakReference<IView> VirtualView { get; set; }
6297

63-
public UIView NativeView { get; private set; }
98+
public WeakReference<UIView> NativeView { get; set; }
6499

65100
public override void PrepareForReuse()
66101
{
67102
base.PrepareForReuse();
68103

69104
// TODO: Recycle
70-
if (VirtualView != null)
71-
ReuseCallback?.Invoke(VirtualView);
105+
if ((VirtualView?.TryGetTarget(out var virtualView) ?? false)
106+
&& (ReuseCallback?.TryGetTarget(out var reuseCallback) ?? false))
107+
{
108+
reuseCallback?.Invoke(virtualView);
109+
}
72110
}
73111

74112
public void SwapView(IView newView)
75113
{
76-
if (VirtualView == null || VirtualView.Handler == null || NativeView == null)
114+
// Create a new platform native view if we don't have one yet
115+
if (!(NativeView?.TryGetTarget(out var nativeView) ?? false))
116+
{
117+
nativeView = newView.ToPlatform(this.Handler.MauiContext);
118+
nativeView.Frame = this.ContentView.Frame;
119+
nativeView.AutoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth;
120+
this.ContentView.AddSubview(nativeView);
121+
NativeView = new WeakReference<UIView>(nativeView);
122+
}
123+
124+
// Create a new virtual view if we don't have one yet
125+
if (!(VirtualView?.TryGetTarget(out var virtualView) ?? false) || (virtualView?.Handler is null))
77126
{
78-
NativeView = newView.ToPlatform(this.Handler.MauiContext);
79-
VirtualView = newView;
80-
NativeView.Frame = this.ContentView.Frame;
81-
NativeView.AutoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth;
82-
this.ContentView.AddSubview(NativeView);
127+
virtualView = newView;
128+
VirtualView = new WeakReference<IView>(virtualView);
83129
}
84130
else
85131
{
86-
var handler = VirtualView.Handler;
87-
VirtualView.Handler = null;
132+
var handler = virtualView.Handler;
133+
virtualView.Handler = null;
88134
newView.Handler = handler;
89135
handler.SetVirtualView(newView);
90-
VirtualView = newView;
136+
VirtualView.SetTarget(newView);
91137
}
92-
}
138+
}
93139
}

VirtualListView/Apple/CvDataSource.ios.maccatalyst.cs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ public override UICollectionViewCell GetCell(UICollectionView collectionView, NS
4040
};
4141

4242
var cell = collectionView.DequeueReusableCell(nativeReuseId, indexPath) as CvCell;
43-
cell.TapHandler = TapCellHandler;
43+
cell.TapHandler = new WeakReference<Action<CvCell>>(TapCellHandler);
4444
cell.Handler = Handler;
45-
cell.IndexPath = indexPath;
46-
47-
cell.ReuseCallback = rv =>
48-
Handler.VirtualView.ViewSelector.ViewDetached(info, cell.VirtualView);
45+
cell.IndexPath = new WeakReference<NSIndexPath>(indexPath);
46+
47+
cell.ReuseCallback = new WeakReference<Action<IView>>((rv) =>
48+
{
49+
if (cell?.VirtualView?.TryGetTarget(out var cellVirtualView) ?? false)
50+
Handler.VirtualView.ViewSelector.ViewDetached(info, cellVirtualView);
51+
});
4952

5053
if (info.SectionIndex < 0 || info.ItemIndex < 0)
5154
info.IsSelected = false;
@@ -60,12 +63,15 @@ public override UICollectionViewCell GetCell(UICollectionView collectionView, NS
6063

6164
cell.PositionInfo = info;
6265

63-
if (cell.VirtualView is IPositionInfo viewPositionInfo)
64-
viewPositionInfo.IsSelected = info.IsSelected;
66+
if (cell.VirtualView.TryGetTarget(out var cellVirtualView))
67+
{
68+
if (cellVirtualView is IPositionInfo viewPositionInfo)
69+
viewPositionInfo.IsSelected = info.IsSelected;
6570

66-
Handler?.PositionalViewSelector?.ViewSelector?.RecycleView(info, data, cell.VirtualView);
71+
Handler?.PositionalViewSelector?.ViewSelector?.RecycleView(info, data, cellVirtualView);
6772

68-
Handler.VirtualView.ViewSelector.ViewAttached(info, cell.VirtualView);
73+
Handler.VirtualView.ViewSelector.ViewAttached(info, cellVirtualView);
74+
}
6975

7076
return cell;
7177
}

VirtualListView/Apple/CvDelegate.ios.maccatalyst.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ public CvDelegate(VirtualListViewHandler handler, UICollectionView collectionVie
1010
: base()
1111
{
1212
Handler = handler;
13-
NativeCollectionView = collectionView;
13+
NativeCollectionView = new WeakReference<UICollectionView>(collectionView);
1414
}
1515

16-
internal readonly UICollectionView NativeCollectionView;
16+
internal readonly WeakReference<UICollectionView> NativeCollectionView;
1717
internal readonly VirtualListViewHandler Handler;
1818

19-
public Action<NFloat, NFloat> ScrollHandler { get; set; }
19+
public WeakReference<Action<NFloat, NFloat>> ScrollHandler { get; set; }
2020

2121
public override void ItemSelected(UICollectionView collectionView, NSIndexPath indexPath)
2222
=> HandleSelection(collectionView, indexPath, true);
@@ -31,7 +31,7 @@ void HandleSelection(UICollectionView collectionView, NSIndexPath indexPath, boo
3131

3232
if ((selectedCell?.PositionInfo?.Kind ?? PositionKind.Header) == PositionKind.Item)
3333
{
34-
selectedCell.PositionInfo.IsSelected = selected;
34+
selectedCell.UpdateSelected(selected);
3535

3636
var itemPos = new ItemPosition(
3737
selectedCell.PositionInfo.SectionIndex,
@@ -45,7 +45,10 @@ void HandleSelection(UICollectionView collectionView, NSIndexPath indexPath, boo
4545
}
4646

4747
public override void Scrolled(UIScrollView scrollView)
48-
=> ScrollHandler?.Invoke(scrollView.ContentOffset.X, scrollView.ContentOffset.Y);
48+
{
49+
if (ScrollHandler?.TryGetTarget(out var handler) ?? false)
50+
handler?.Invoke(scrollView.ContentOffset.X, scrollView.ContentOffset.Y);
51+
}
4952

5053
public override bool ShouldSelectItem(UICollectionView collectionView, NSIndexPath indexPath)
5154
=> IsRealItem(indexPath);

0 commit comments

Comments
 (0)