mirror of
https://github.com/tuskyapp/Tusky
synced 2025-02-04 01:47:51 +01:00
Christophe Beyls
c668cdc633
Optimize Glide emoji targets (#4467)
The current code loads emojis using Glide into basic custom `Target`s and doesn't keep a hard reference to the Target. This creates a few problems: - Unlike images loaded into `ImageViewTarget`s, Emoji animations are not paused when the Activity/Fragment becomes invisible. GIF decoding use resources in the background. - When `TextView`s get recycled in a RecyclerView, the loading of emojis for the previous bind are not canceled when binding the new text and starting the load of the new emojis. This is also handled automatically when using `ImageViewTarget` but not for custom targets. Also, when the obsolete emojis complete loading, the `TextView` will be unnecessarily invalidated and redrawn. - Since Glide's `RequestManager` doesn't keep hard references to Targets after they are loaded and the emoji Target is currently not stored in any View, emojis don't get an opportunity to clean up (at least stop their animation) when the Activity/Fragment is destroyed. Depending on the Drawable implementation, animations may run forever in the background and cause memory leaks. This pull request aims to properly track the lifecycle of emoji Targets, cancel their loading an stop animations when appropriate. It also reimplements `emojify()` to be more efficient. - Add extension functions `View.setEmojiTargets()` and `View.clearEmojiTargets()` to store and clear lists of emoji targets in View tags, keeping a hard reference to them as long as the View is used. When clearing emoji targets, pending requests will be canceled and animations will be stopped to free memory. This is similar to what `ImageViewTarget` does, except here multiple Targets are stored for a single View instead of one. - Add helper extension function `View.updateEmojiTargets()` to automatically clear the View emoji targets, then allowing to call `emojify()` one or more times in the `EmojiTargetScope` of that View, and finally store all the pending targets of the `EmojiTargetScope` in the View. - Reimplement `CharSequence.emojify()` using `View.updateEmojiTargets()`. This is used in RecyclerViews as well and will automatically cancel previous emoji loadings for the same View and stop animations. - The main logic of `emojify()` has been moved to `EmojiTargetScope`. Replace usage of slow regex `Matcher` with faster `CharSequence.indexOf()`. Use `SpannableString` (with `toSpannable()`) instead of `SpannableStringBuilder` to store the `EmojiSpan`s. - Rename `EmojiSpan.getTarget()` to `EmojiSpan.createGlideTarget()` and improve the target to stop/resume the animation according to the parent component lifecycle, and stop the animation when clearing the target. Use a hard reference to the view instead of a weak reference, since the lifecycle of the Target now matches the one of the View and the Target will be cleared at the latest when the View is destroyed. - Use `View.updateEmojiTargets()` in `ReportNotificationViewHolder` in order to store the targets of 2 separate sets of emojis into the same TextView. - Fix: reimplement the code to merge the 2 emoji sets into a single `CharSequence` in `ReportNotificationViewHolder` using `TextUtils.expandTemplate()`. The current code uses `String.format()` which returns a String instead of a Spannable so the computed emojis are lost. - Store the emoji targets in `AnnouncementAdapter` in the parent view after clearing the previous ones. It is a better location than storing one emoji target in each child `Tooltip` view because tooltips are not recycled when refreshing the data and the previous targets would not be canceled properly. - Bonus: update `ViewVideoFragment` to use `CustomViewTarget` instead of `CustomTarget` to load the default artwork into `PlayerView`. The loading will also automatically be canceled when the fragment view is detached.
Tusky
Tusky is a beautiful Android client for Mastodon. Mastodon is an ActivityPub federated social network. That means no single entity controls the whole network, rather, like e-mail, volunteers and organisations operate their own independent servers, users from which can all interact with each other seamlessly.
Features
- Material Design
- Most Mastodon APIs implemented
- Multi-Account support
- Dark, light and black themes with the possibility to auto-switch based on the time of day
- Drafts - compose posts and save them for later
- Choose between different emoji styles
- Optimized for all screen sizes
- Completely open-source - no non-free dependencies like Google services
Testing
The nightly build containing the newest development code is available on Google Play.
Support
Check out our FAQs, your question may already be answered. If you have any bug reports, feature requests or questions please open an issue or send us a message at Tusky@mastodon.social!
Contributing
We always welcome new contributors! Please read our contribution guide to get started.
Development chatroom
Description
Tusky è un client Android per Mastodon. Mastodon è un social network federato ActivityPub. Ciò significa che nessuna singola entità controlla l'intera rete, piuttosto, come la posta elettronica, i volontari e le organizzazioni gestiscono i propri server.
https://mastodon.it/it/app-mastodon-per-android
Languages
Kotlin
90.5%
Java
9.5%