Environment:
- App: OctoDroid (com.gh4a)
- Version:
v4.6.15 (versionCode 78)
The Issue:
Hi, I noticed some main-thread blocking happening when toggling bookmarks, which can cause performance issues in this app.
Right now, hitting the bookmark action in UserActivity or RepositoryActivity runs synchronous ContentResolver and SQLite operations directly on the UI thread.
If you trace onOptionsItemSelected, it calls BookmarksProvider.hasBookmarked(...), which executes a synchronous query(). It then immediately follows up with removeBookmark(...) (triggering a delete()) or saveBookmark(...) (which does another query() followed by an insert()).
Down in BookmarksProvider.delete(...), it's obtaining the writable database and executing these queries synchronously.
Impact:
While it might feel fast enough on high-end devices, doing disk I/O on the main thread scales poorly. On older devices or under heavy I/O pressure, this drops frames and causes noticeable jank. If the DB is locked or busy, it's a prime candidate for an ANR.
Suggested Fix:
We should decouple the storage logic from the UI side effects (like the Toasts) and push the DB work to the background.
A relatively quick fix would be:
- Add internal, background-safe methods in
BookmarksProvider (e.g., removeBookmarkInternal, saveBookmarkInternal) that just do the DB work without showing Toasts.
- In the Activities, wrap the
hasBookmarked -> remove/save flow in a background executor.
- Post back to the main thread to update the menu icon state and show the success Toast.
Environment:
v4.6.15(versionCode 78)The Issue:
Hi, I noticed some main-thread blocking happening when toggling bookmarks, which can cause performance issues in this app.
Right now, hitting the bookmark action in
UserActivityorRepositoryActivityruns synchronousContentResolverand SQLite operations directly on the UI thread.If you trace
onOptionsItemSelected, it callsBookmarksProvider.hasBookmarked(...), which executes a synchronousquery(). It then immediately follows up withremoveBookmark(...)(triggering adelete()) orsaveBookmark(...)(which does anotherquery()followed by aninsert()).Down in
BookmarksProvider.delete(...), it's obtaining the writable database and executing these queries synchronously.Impact:
While it might feel fast enough on high-end devices, doing disk I/O on the main thread scales poorly. On older devices or under heavy I/O pressure, this drops frames and causes noticeable jank. If the DB is locked or busy, it's a prime candidate for an ANR.
Suggested Fix:
We should decouple the storage logic from the UI side effects (like the Toasts) and push the DB work to the background.
A relatively quick fix would be:
BookmarksProvider(e.g.,removeBookmarkInternal,saveBookmarkInternal) that just do the DB work without showing Toasts.hasBookmarked->remove/saveflow in a background executor.