No need for the wrapped Lazy instance in image loading.

This commit is contained in:
弘韬 张 2021-05-23 12:28:45 +08:00
parent d813a4732d
commit e8691c210d
2 changed files with 27 additions and 67 deletions

View file

@ -42,7 +42,7 @@
<ColumnDefinition Width="0" /> <ColumnDefinition Width="0" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image x:Name="ImageIcon" Width="32" Height="32" HorizontalAlignment="Left" <Image x:Name="ImageIcon" Width="32" Height="32" HorizontalAlignment="Left"
Source="{Binding Image.Value}" /> Source="{Binding Image}" />
<Grid Margin="5 0 5 0" Grid.Column="1" HorizontalAlignment="Stretch"> <Grid Margin="5 0 5 0" Grid.Column="1" HorizontalAlignment="Stretch">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />

View file

@ -11,61 +11,11 @@ namespace Flow.Launcher.ViewModel
{ {
public class ResultViewModel : BaseModel public class ResultViewModel : BaseModel
{ {
public class LazyAsync<T> : Lazy<ValueTask<T>>
{
private readonly T defaultValue;
private readonly Action _updateCallback;
public new T Value
{
get
{
if (!IsValueCreated)
{
_ = Exercute(); // manually use callback strategy
return defaultValue;
}
if (!base.Value.IsCompletedSuccessfully)
return defaultValue;
return base.Value.Result;
// If none of the variables captured by the local function are captured by other lambdas,
// the compiler can avoid heap allocations.
async ValueTask Exercute()
{
await base.Value.ConfigureAwait(false);
_updateCallback();
}
}
}
public LazyAsync(Func<ValueTask<T>> factory, T defaultValue, Action updateCallback) : base(factory)
{
if (defaultValue != null)
{
this.defaultValue = defaultValue;
}
_updateCallback = updateCallback;
}
}
public ResultViewModel(Result result, Settings settings) public ResultViewModel(Result result, Settings settings)
{ {
if (result != null) if (result != null)
{ {
Result = result; Result = result;
Image = new LazyAsync<ImageSource>(
SetImage,
ImageLoader.DefaultImage,
() =>
{
OnPropertyChanged(nameof(Image));
});
} }
Settings = settings; Settings = settings;
@ -85,44 +35,54 @@ namespace Flow.Launcher.ViewModel
? Result.SubTitle ? Result.SubTitle
: Result.SubTitleToolTip; : Result.SubTitleToolTip;
public LazyAsync<ImageSource> Image { get; set; } private bool ImageLoaded;
private async ValueTask<ImageSource> SetImage() private ImageSource image = ImageLoader.DefaultImage;
public ImageSource Image
{
get
{
if (!ImageLoaded)
{
ImageLoaded = true;
LoadImage();
}
return image;
}
private set => image = value;
}
private async void LoadImage()
{ {
var imagePath = Result.IcoPath; var imagePath = Result.IcoPath;
if (string.IsNullOrEmpty(imagePath) && Result.Icon != null) if (string.IsNullOrEmpty(imagePath) && Result.Icon != null)
{ {
try try
{ {
return Result.Icon(); Image = Result.Icon();
return;
} }
catch (Exception e) catch (Exception e)
{ {
Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e); Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e);
return ImageLoader.DefaultImage;
} }
} }
if (ImageLoader.CacheContainImage(imagePath)) if (ImageLoader.CacheContainImage(imagePath))
{
// will get here either when icoPath has value\icon delegate is null\when had exception in delegate // will get here either when icoPath has value\icon delegate is null\when had exception in delegate
return ImageLoader.Load(imagePath); Image = ImageLoader.Load(imagePath);
return;
}
return await Task.Run(() => ImageLoader.Load(imagePath)); Image = await Task.Run(() => ImageLoader.Load(imagePath)).ConfigureAwait(false);
} }
public Result Result { get; } public Result Result { get; }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
var r = obj as ResultViewModel; return obj is ResultViewModel r && Result.Equals(r.Result);
if (r != null)
{
return Result.Equals(r.Result);
}
else
{
return false;
}
} }
public override int GetHashCode() public override int GetHashCode()