Skip to content

Commit

Permalink
Use WeakRef for Single ViewModel Cache (#4661)
Browse files Browse the repository at this point in the history
* Make reference to cached VM weak

* Navigate to CollectionView with parameters

* Fix sample ditching FFImageLoading and using Glide

* No need for this check

* Fix colors not showing on collection view sample
  • Loading branch information
Cheesebaron committed Aug 1, 2023
1 parent 1850efc commit b351cfd
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 44 deletions.
3 changes: 3 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
</PackageVersion>
<PackageVersion Include="Serilog" Version="3.0.1" />
<PackageVersion Include="Serilog.Extensions.Logging" Version="7.0.0" />
<PackageVersion Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageVersion Include="Serilog.Sinks.Trace" Version="3.0.0" />
<PackageVersion Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageVersion Include="Serilog.Sinks.Xamarin" Version="1.0.0" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.6.0.74858" />
<PackageVersion Include="SourceLink.Create.CommandLine" Version="2.8.3" />
<PackageVersion Include="Xamarin.Android.Glide" Version="4.15.1.2" />
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.6.1.3" />
<PackageVersion Include="Xamarin.AndroidX.AppCompat.AppCompatResources" Version="1.6.1.3" />
<PackageVersion Include="Xamarin.AndroidX.CardView" Version="1.0.0.21" />
Expand Down
5 changes: 2 additions & 3 deletions MvvmCross/Platforms/Android/Views/IMvxSingleViewModelCache.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using Android.OS;
#nullable enable
using MvvmCross.ViewModels;

namespace MvvmCross.Platforms.Android.Views
Expand All @@ -11,6 +10,6 @@ public interface IMvxSingleViewModelCache
{
void Cache(IMvxViewModel toCache, Bundle bundle);

IMvxViewModel GetAndClear(Bundle bundle);
IMvxViewModel? GetAndClear(Bundle bundle);
}
}
39 changes: 21 additions & 18 deletions MvvmCross/Platforms/Android/Views/MvxSingleViewModelCache.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using Android.OS;
#nullable enable
using MvvmCross.ViewModels;

namespace MvvmCross.Platforms.Android.Views
Expand All @@ -14,32 +13,36 @@ public class MvxSingleViewModelCache

private int _counter;

private IMvxViewModel _currentViewModel;
private WeakReference<IMvxViewModel>? _currentViewModel;

public void Cache(IMvxViewModel toCache, Bundle bundle)
{
_currentViewModel = toCache;
_currentViewModel = new WeakReference<IMvxViewModel>(toCache);
_counter++;

if (_currentViewModel == null)
{
return;
}

bundle.PutInt(BundleCacheKey, _counter);
}

public IMvxViewModel GetAndClear(Bundle bundle)
public IMvxViewModel? GetAndClear(Bundle? bundle)
{
var storedViewModel = _currentViewModel;
_currentViewModel = null;

if (bundle == null)
return null;
try
{
if (bundle == null)
return null;

if (_currentViewModel?.TryGetTarget(out var storedViewModel) == true)
{
var key = bundle.GetInt(BundleCacheKey);
var toReturn = key == _counter ? storedViewModel : null;
return toReturn;
}
}
finally
{
_currentViewModel = null;
}

var key = bundle.GetInt(BundleCacheKey);
var toReturn = key == _counter ? storedViewModel : null;
return toReturn;
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@

namespace Playground.Core.ViewModels
{
public class CollectionViewModel : MvxViewModel
public record CollectionViewParameter(int InitialCount = 40);

public class CollectionViewModel : MvxViewModel<CollectionViewParameter>
{
private readonly Random _random;

public MvxObservableCollection<AnimalViewModel> Animals { get; }
= new MvxObservableCollection<AnimalViewModel>();
public MvxObservableCollection<AnimalViewModel> Animals { get; } = new();

public MvxCommand<AnimalViewModel> DeleteAnimalCommand { get; }
public MvxCommand<int> AddAnimalCommand { get; }
Expand All @@ -25,12 +26,14 @@ public CollectionViewModel()
DeleteAnimalCommand = new MvxCommand<AnimalViewModel>(DoDeleteAnimalCommand);
AddAnimalCommand = new MvxCommand<int>(DoAddAnimalCommand);
MarkFavoriteCommand = new MvxCommand<AnimalViewModel>(DoMarkFavoriteCommand);

DoAddAnimalCommand(40);
}

private string[] _catImageUrls = new[]
public override void Prepare(CollectionViewParameter parameter)
{
DoAddAnimalCommand(parameter.InitialCount);
}

private readonly string[] _catImageUrls = {
"https://loremflickr.com/320/240/cat",
"https://www.hillspet.com/content/dam/cp-sites/hills/hills-pet/en_us/exported/cat-care/new-pet-parent/images/mother-cat-and-kitten-sleeping.jpg",
"https://www.hillspet.com/content/dam/cp-sites/hills/hills-pet/en_us/exported/cat-care/new-pet-parent/images/calico-kitten-hiding-under-chair.jpg",
Expand All @@ -41,8 +44,7 @@ public CollectionViewModel()
"https://www.petmd.com/sites/default/files/petmd-kitten-facts.jpg"
};

private string[] _dogImageUrls = new[]
{
private readonly string[] _dogImageUrls = {
"https://loremflickr.com/320/240/dog",
"https://i.imgur.com/KSftE11.jpg",
"https://www.thekennelclub.org.uk/media/220388/puppy_environment_alison_spiers.jpg",
Expand All @@ -52,8 +54,7 @@ public CollectionViewModel()
"https://www.fomobones.com/blog/wp-content/uploads/2018/12/puppy-grows-out.jpg"
};

private string[] _monkeyImageUrls = new[]
{
private readonly string[] _monkeyImageUrls = {
"https://loremflickr.com/320/240/monkey",
"https://allthatsinteresting.com/wordpress/wp-content/uploads/2019/04/baby-primate.jpg",
"https://images.law.com/contrib/content/uploads/sites/403/2018/04/monkey-selfie-Article-201804131946.jpg",
Expand All @@ -64,15 +65,13 @@ public CollectionViewModel()
"https://heritagecorridoraletrail.com/wp-content/uploads/2018/01/babymonkey.jpg"
};

private string[] _names = new[]
{
private readonly string[] _names = {
"Martijn", "Nicolas", "Nick", "Tomasz", "Stuart", "Marc", "Jeremy", "Jonathan", "Maurits", "Kerry",
"Will", "Garfield", "Chris", "Przemyslaw", "Guillaume", "Trevor", "Mihal", "Sylvain", "Andres",
"Erik", "Daniel", "Aaron", "Emmanuel", "Iain", "Martin"
};

private Color[] _colors = new[]
{
private readonly Color[] _colors = {
Color.Yellow, Color.Green, Color.Blue, Color.Red, Color.Brown,
Color.Gold, Color.Orange, Color.Purple, Color.Teal, Color.Pink,
Color.Azure, Color.Crimson, Color.Cyan, Color.Gray, Color.Silver,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public RootViewModel(ILoggerFactory logProvider, IMvxNavigationService navigatio
await NavigationService.Navigate<DictionaryBindingViewModel>());

ShowCollectionViewCommand =
new MvxAsyncCommand(() => NavigationService.Navigate<CollectionViewModel>());
new MvxAsyncCommand(() => NavigationService.Navigate<CollectionViewModel, CollectionViewParameter>(new CollectionViewParameter(50)));

ShowSharedElementsCommand = new MvxAsyncCommand(async () =>
await NavigationService.Navigate<SharedElementRootChildViewModel>());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using Android.App;
using Android.OS;
using MvvmCross.Platforms.Android.Presenters.Attributes;
using MvvmCross.Platforms.Android.Views;
using Playground.Core.ViewModels;
Expand Down
45 changes: 45 additions & 0 deletions Projects/Playground/Playground.Droid/Activities/GlideImageView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Android.Content;
using Android.Runtime;
using Android.Util;
using Bumptech.Glide;

namespace Playground.Droid.Activities;

[Register("playground.droid.GlideImageView")]
public sealed class GlideImageView : ImageView
{
private string _imagePath;

public string ImagePath
{
get => _imagePath;
set
{
if (value == null)
return;

_imagePath = value;
Glide.With(Context).Load(_imagePath).Into(this);
}
}

public GlideImageView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}

public GlideImageView(Context context) : base(context)
{
}

public GlideImageView(Context context, IAttributeSet attrs) : base(context, attrs)
{
}

public GlideImageView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
{
}

public GlideImageView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
{
}
}
5 changes: 3 additions & 2 deletions Projects/Playground/Playground.Droid/Playground.Droid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

<ItemGroup>
<PackageReference Include="Serilog" />
<PackageReference Include="Serilog.Sinks.Async" />
<PackageReference Include="Serilog.Sinks.Trace" />
<PackageReference Include="Serilog.Sinks.Xamarin" />
<PackageReference Include="Serilog.Extensions.Logging" />
<PackageReference Include="Xamarin.FFImageLoading" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData" />
<PackageReference Include="Xamarin.Android.Glide" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="80dp">
<FFImageLoading.Cross.MvxCachedImageView
<GlideImageView
android:id="@+id/image"
android:layout_height="match_parent"
android:layout_width="80dp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="80dp">
<FFImageLoading.Cross.MvxCachedImageView
<GlideImageView
android:id="@+id/image"
android:layout_height="match_parent"
android:layout_width="80dp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="80dp">
<FFImageLoading.Cross.MvxCachedImageView
<GlideImageView
android:id="@+id/image"
android:layout_height="match_parent"
android:layout_width="match_parent"
Expand Down
12 changes: 11 additions & 1 deletion Projects/Playground/Playground.Droid/Setup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using MvvmCross.Binding.Bindings.Target.Construction;
using MvvmCross.DroidX.RecyclerView;
using MvvmCross.Platforms.Android.Core;
using MvvmCross.Plugin;
using MvvmCross.Plugin.Color.Platforms.Android;
using Playground.Core;
using Playground.Droid.Bindings;
using Playground.Droid.Controls;
Expand All @@ -32,6 +34,13 @@ protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry reg
base.FillTargetFactories(registry);
}

public override void LoadPlugins(IMvxPluginManager pluginManager)
{
base.LoadPlugins(pluginManager);

pluginManager.EnsurePluginLoaded<Plugin>();
}

protected override ILoggerProvider CreateLogProvider()
{
return new SerilogLoggerProvider();
Expand All @@ -41,7 +50,8 @@ protected override ILoggerFactory CreateLogFactory()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.AndroidLog()
.WriteTo.Async(a => a.AndroidLog())
.WriteTo.Async(a => a.Trace())
.CreateLogger();

return new SerilogLoggerFactory();
Expand Down

0 comments on commit b351cfd

Please sign in to comment.