Skip to content

Commit

Permalink
Android: Fixed #354 - Images in list getting mixed up
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-luberda committed Nov 4, 2016
1 parent 15192d2 commit 3a6fe68
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 81 deletions.
18 changes: 8 additions & 10 deletions source/FFImageLoading.Common/Work/ImageLoaderTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,21 +174,22 @@ public virtual bool UsesSameNativeControl(IImageLoaderTask anotherTask)

public void Cancel()
{
ImageService.RemovePendingTask(this);

if (!_isDisposed)
{
Target?.SetImageLoadingTask(null);
ImageService.RemovePendingTask(this);

try
{
CancellationTokenSource?.Cancel();
}
catch (ObjectDisposedException)
{
}
}

if (Configuration.VerboseLoadingCancelledLogging)
Logger.Debug(string.Format("Image loading cancelled: {0}", Key));
if (Configuration.VerboseLoadingCancelledLogging)
Logger.Debug(string.Format("Image loading cancelled: {0}", Key));
}
}

public void CancelIfNeeded()
Expand All @@ -203,10 +204,7 @@ public void CancelIfNeeded()

protected virtual void BeforeLoading(TImageContainer image, bool fromMemoryCache) { }

protected virtual void AfterLoading(TImageContainer image, bool fromMemoryCache)
{
Target?.SetImageLoadingTask(null);
}
protected virtual void AfterLoading(TImageContainer image, bool fromMemoryCache) { }

public async virtual Task<bool> TryLoadFromMemoryCacheAsync()
{
Expand Down Expand Up @@ -423,7 +421,7 @@ await MainThreadDispatcher.PostAsync(() =>
MemoryCache.Clear();
}

if (ex is OperationCanceledException)
if (ex is OperationCanceledException || ex is ObjectDisposedException)
{
if (Configuration.VerboseLoadingCancelledLogging)
{
Expand Down
45 changes: 18 additions & 27 deletions source/FFImageLoading.Common/Work/WorkScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public virtual async void LoadImage(IImageLoaderTask task)
if (task == null)
return;

if (task.IsCancelled || task.IsCompleted)
if (task.IsCancelled || task.IsCompleted || ExitTasksEarly)
{
task?.Dispose();
return;
Expand All @@ -195,32 +195,6 @@ public virtual async void LoadImage(IImageLoaderTask task)
{
try
{
EvictStaleTasks();

if (task.IsCancelled || task.IsCompleted)
{
task?.Dispose();
return;
}

if (!task.Parameters.Preload)
{
lock (_pendingTasksLock)
{
foreach (var pendingTask in PendingTasks.ToList()) // FMT: here we need a copy since cancelling will trigger them to be removed, hence collection is modified during enumeration
{
if (pendingTask.ImageLoadingTask != null && pendingTask.ImageLoadingTask.UsesSameNativeControl(task))
pendingTask.ImageLoadingTask.CancelIfNeeded();
}
}
}

if (task.IsCancelled || ExitTasksEarly)
{
task?.Dispose();
return;
}

QueueImageLoadingTask(task);
}
catch (Exception ex)
Expand All @@ -235,9 +209,26 @@ protected void QueueImageLoadingTask(IImageLoaderTask task)
int position = Interlocked.Increment(ref _currentPosition);
var currentPendingTask = new PendingTask() { Position = position, ImageLoadingTask = task, FrameworkWrappingTask = CreateFrameworkTask(task) };

if (task.IsCancelled || task.IsCompleted || ExitTasksEarly)
{
task?.Dispose();
return;
}

PendingTask similarRunningTask = null;
lock (_pendingTasksLock)
{
if (!task.Parameters.Preload)
{
foreach (var pendingTask in PendingTasks.ToList()) // FMT: here we need a copy since cancelling will trigger them to be removed, hence collection is modified during enumeration
{
if (pendingTask.ImageLoadingTask != null && pendingTask.ImageLoadingTask.UsesSameNativeControl(task))
pendingTask.ImageLoadingTask.CancelIfNeeded();
}

EvictStaleTasks();
}

similarRunningTask = PendingTasks.FirstOrDefault(t => t.ImageLoadingTask.Key == task.Key);
if (similarRunningTask == null)
{
Expand Down
6 changes: 3 additions & 3 deletions source/FFImageLoading.Droid/Targets/ImageViewTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public override bool IsValid
public override bool IsTaskValid(IImageLoaderTask task)
{
var controlTask = Control?.ImageLoaderTask;

return IsValid && (controlTask == null || controlTask == task);
}

Expand All @@ -38,7 +37,8 @@ public override void SetAsEmpty(IImageLoaderTask task)
var control = Control;
if (control == null)
return;


control.ImageLoaderTask = null;
control.SetImageResource(global::Android.Resource.Color.Transparent);
}

Expand Down Expand Up @@ -72,7 +72,7 @@ public override bool UsesSameNativeControl(IImageLoaderTask task)
if (control == null || otherControl == null)
return false;

return control.Handle == otherControl.Handle;
return control.Handle == otherControl.Handle;
}

public override ImageViewAsync Control
Expand Down
2 changes: 2 additions & 0 deletions source/FFImageLoading.Droid/TaskParameterExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public static class TaskParameterExtensions
/// <param name="imageView">Image view that should receive the image.</param>
public static IScheduledWork Into(this TaskParameter parameters, ImageViewAsync imageView)
{
imageView.CancelLoading();

var target = new ImageViewTarget(imageView);

if (parameters.Source != ImageSource.Stream && string.IsNullOrWhiteSpace(parameters.Path))
Expand Down
5 changes: 0 additions & 5 deletions source/FFImageLoading.Droid/Views/ImageViewAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ protected override void OnDetachedFromWindow()
base.OnDetachedFromWindow();
}*/

public void CancelLoading()
{
ImageService.Instance.CancelWorkFor(ImageLoaderTask);
}

protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
if (Drawable == null)
Expand Down
61 changes: 25 additions & 36 deletions source/FFImageLoading.Droid/Views/ManagedImageView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,54 +60,43 @@ protected override void OnDetachedFromWindow()

public IImageLoaderTask ImageLoaderTask { get; set; }

public void CancelLoading()
{
if (ImageLoaderTask != null)
{
ImageService.Instance.CancelWorkFor(ImageLoaderTask);
ImageLoaderTask = null;
}

}

public override void SetImageDrawable(Drawable drawable)
{
try
{
var previous = Drawable;
var previous = Drawable;

_drawableRef = new WeakReference<Drawable>(drawable);
base.SetImageDrawable(drawable);
_drawableRef = new WeakReference<Drawable>(drawable);
base.SetImageDrawable(drawable);

UpdateDrawableDisplayedState(drawable, true);
UpdateDrawableDisplayedState(previous, false);
}
finally
{
ImageLoaderTask = null;
}
UpdateDrawableDisplayedState(drawable, true);
UpdateDrawableDisplayedState(previous, false);
}

public override void SetImageResource(int resId)
{
try
{
var previous = Drawable;
// Ultimately calls SetImageDrawable, where the state will be updated.
_drawableRef = null;
base.SetImageResource(resId);
UpdateDrawableDisplayedState(previous, false);
}
finally
{
ImageLoaderTask = null;
}
var previous = Drawable;
// Ultimately calls SetImageDrawable, where the state will be updated.
_drawableRef = null;
base.SetImageResource(resId);
UpdateDrawableDisplayedState(previous, false);
}

public override void SetImageURI(global::Android.Net.Uri uri)
{
try
{
var previous = Drawable;
// Ultimately calls SetImageDrawable, where the state will be updated.
_drawableRef = null;
base.SetImageURI(uri);
UpdateDrawableDisplayedState(previous, false);
}
finally
{
ImageLoaderTask = null;
}
var previous = Drawable;
// Ultimately calls SetImageDrawable, where the state will be updated.
_drawableRef = null;
base.SetImageURI(uri);
UpdateDrawableDisplayedState(previous, false);
}

private void UpdateDrawableDisplayedState(Drawable drawable, bool isDisplayed)
Expand Down

0 comments on commit 3a6fe68

Please sign in to comment.