Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delayed unsubscribe timing to unsubscribe after displaying the last i… #2298

Closed

Conversation

matsuhiro
Copy link

@matsuhiro matsuhiro commented Aug 28, 2017

…mage

Description

I want to stop/start animation gif.
I delay unsubscribe timing to fix an animation gif bug.

Motivation and Context

Current code of master branch, when you call stop() method of Animation interface, callback will be unsubscribed soon.
Then, in background thread, new bitmap for next frame is prepared and previous bitmap is recycled.
But, callback is already unsubscribed, so new bitmap will not be applied and previous bitmap will be used to draw other gif animation frame.
As a result, it seems that a image which is stopped animation is changed by other animation.

About reproduce:
More than two GIF animation are played, and when you stop animation of one file by using stop() method, you will find a bug.
The bug is that animating gif file will change image of not animating gif image.
You can reproduce it with this repo (https://github.com/matsuhiro/glide/tree/reproduce_bug).
(You can reproduce it by applying this patch matsuhiro@9359a7f)

  1. Launch sample of giphy
  2. Click some animating gif image.
  3. You will find other image change the image which is click at step 2.

For reproducing, it is easy to understand that images of the same size are being played at the same time.

@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed, please reply here (e.g. I signed it!) and we'll verify. Thanks.


  • If you've already signed a CLA, it's possible we don't have your GitHub username or you're using a different email address. Check your existing CLA data and verify that your email is set on your git commits.
  • If your company signed a CLA, they designated a Point of Contact who decides which employees are authorized to participate. You may need to contact the Point of Contact for your company and ask to be added to the group of authorized contributors. If you don't know who your Point of Contact is, direct the project maintainer to go/cla#troubleshoot.
  • In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again.

@matsuhiro
Copy link
Author

I signed it!

@@ -103,6 +104,7 @@ Bitmap getFirstFrame() {
}

void subscribe(FrameCallback frameCallback) {
unsubscribeRegisteredCallback();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if subscribe is never called again?

Copy link
Author

@matsuhiro matsuhiro Aug 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just fail safe.
Normally, unsubscribeRegisteredCallback() is called inside onFrameReady() and then callbacks will be unsubscribed.
When an user click image repeat quickly, subscribe() may be called before onFrameReady() is called.

@sjudd
Copy link
Collaborator

sjudd commented Sep 1, 2017

Thanks for putting this up, I really appreciate the detail and the repro case. This is definitely a complicated problem. I'm sorry for the delay, it took me a bit to wrap my head around this.

I think this solution isn't quite complete though. Let's say you have the same GIF animating in two views at the same time. Then, you stop both GifDrawables, one at a time, allowing exactly one additional frame to render before stopping the next GifDrawable.

When the first GifDrawable is stopped, after your change, it will end on frame N+1. Frame N will be cleared when frame N+1 loads.

When the second GifDrawable is stopped, one frame later, it will end on frame N+2. But, frame N+1, still in use by the first GifDrawable, will be cleared when frame N+2 loads.

We really should be assigning ownership of the frame to the stopped GifDrawable. The stopped GifDrawable should make a request to load the frame it currently has in view when stop() is called, which will ensure that the frame is not garbaged collected or re-used, even if the Target owned by the GifFrameLoader is cleared. When the stopped GifDrawable resumes or is destroyed, it can clear the Target it obtained in stop() and release the resource.

One way to do this might be to have stop() in the GifFrameLoader run the load and return a Target, then allow start() in GifFrameLoader to accept a @Nullable Target that could be cleared if the GifDrawable were resumed. I haven't tried that and you may also be able to come up with a better way to do even if that would work.

@sjudd
Copy link
Collaborator

sjudd commented Sep 1, 2017

Targeting this for 4.2 since I'm already a day late for 4.1.

@sjudd sjudd added this to the 4.2 milestone Sep 1, 2017
@sjudd sjudd added the bug label Sep 1, 2017
@matsuhiro
Copy link
Author

Thank you for your reply and your detailed opinion
I will try to improve my pull-request.

@googlebot
Copy link

CLAs look good, thanks!

@sjudd sjudd modified the milestones: 4.2, 4.3 Sep 21, 2017
@sjudd sjudd removed this from the 4.3 milestone Oct 10, 2017
@sjudd
Copy link
Collaborator

sjudd commented Oct 30, 2017

I believe this was fixed in #2526.

@sjudd sjudd closed this Oct 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants