From b20230848b5426c4fb4a78cd458b75c713683af6 Mon Sep 17 00:00:00 2001 From: Artur Skubei <41114720+gdlbo@users.noreply.github.com> Date: Sat, 30 Mar 2024 05:54:56 +0300 Subject: [PATCH] Speedup cache injection (#1597) --- .../music/injectors/TracklistInjector.java | 2 +- .../lite/music/cache/MusicCacheImpl.java | 6 +- .../lite/music/cache/db/MusicCacheDb.java | 9 +++ .../lite/music/cache/db/PlaylistCacheDb.java | 56 ++++++++++++++++++- .../cache/delegate/MusicCacheDbDelegate.java | 6 ++ .../delegate/PlaylistCacheDbDelegate.java | 31 ++++++++++ .../music/cache/helpers/PlaylistHelper.java | 31 +++++----- .../music/cache/helpers/TracklistHelper.java | 2 +- .../lite/ui/fragments/MusicFragment.java | 25 ++++++++- 9 files changed, 143 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/ru/vtosters/hooks/music/injectors/TracklistInjector.java b/app/src/main/java/ru/vtosters/hooks/music/injectors/TracklistInjector.java index 380d3ef41..688afdfd5 100644 --- a/app/src/main/java/ru/vtosters/hooks/music/injectors/TracklistInjector.java +++ b/app/src/main/java/ru/vtosters/hooks/music/injectors/TracklistInjector.java @@ -246,7 +246,7 @@ public class TracklistInjector { .put(getCatalogPlaylist()); } - if (!MusicCacheImpl.getAllOwnTracks().isEmpty()) { + if (!PlaylistCacheDbDelegate.isPlaylistEmpty(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1")) { if (MusicCacheImpl.hasPlaylist()) blocks.put(getCatalogSeparator()); blocks.put(getCatalogHeader(AndroidUtils.getString(R.string.cached_tracks_title))) .put(getShuffleButton()) diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheImpl.java b/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheImpl.java index edf93c27c..69858abc9 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheImpl.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheImpl.java @@ -59,12 +59,12 @@ public class MusicCacheImpl { } public static boolean hasPlaylist() { - return PlaylistCacheDbDelegate.getPlaylistsCount(AndroidUtils.getGlobalContext()) != 0; // has playlists or not + return !PlaylistCacheDbDelegate.isPlaylistsDbEmpty(AndroidUtils.getGlobalContext()); // has playlists or not } public static long getTracksCount() { return !LibVKXClient.isIntegrationEnabled() - ? MusicCacheDbDelegate.getTracksCount(AndroidUtils.getGlobalContext()) + ? PlaylistCacheDbDelegate.getTracksCountInPlaylist(AndroidUtils.getGlobalContext(),AccountManagerUtils.getUserId() + "_-1") : LibVKXClient.getInstance().runOnServiceSync( new LibVKXClientImpl.LibVKXActionGeneric() { @Override @@ -89,7 +89,7 @@ public class MusicCacheImpl { } public static boolean isEmpty() { - return !LibVKXClient.isIntegrationEnabled() && getTracksCount() == 0L; + return !LibVKXClient.isIntegrationEnabled() && MusicCacheDbDelegate.isEmpty(AndroidUtils.getGlobalContext()); } public static void clear() { diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/db/MusicCacheDb.java b/app/src/main/java/ru/vtosters/lite/music/cache/db/MusicCacheDb.java index 4fa02fc36..b22ce3807 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/db/MusicCacheDb.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/db/MusicCacheDb.java @@ -174,6 +174,15 @@ public class MusicCacheDb extends SQLiteOpenHelper implements AutoCloseable { // return DatabaseUtils.queryNumEntries(getReadableDatabase(), Constants.TABLE_NAME); } + public boolean isDatabaseEmpty() { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.rawQuery("SELECT EXISTS(SELECT 1 FROM " + Constants.TABLE_NAME + " LIMIT 1)", null); + cursor.moveToFirst(); + boolean isEmpty = cursor.getInt(0) == 0; + cursor.close(); + return isEmpty; + } + public MusicTrack getTrackById(String trackId) { SQLiteDatabase db = getReadableDatabase(); Cursor cursor = db.query(Constants.TABLE_NAME, null, Constants.COLUMN_TRACK_ID + " = ?", new String[]{trackId}, null, null, null); diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/db/PlaylistCacheDb.java b/app/src/main/java/ru/vtosters/lite/music/cache/db/PlaylistCacheDb.java index 2e12653e8..675a35a4b 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/db/PlaylistCacheDb.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/db/PlaylistCacheDb.java @@ -53,8 +53,7 @@ public class PlaylistCacheDb extends SQLiteOpenHelper implements AutoCloseable { Boolean.parseBoolean(cur.getString(cur.getColumnIndex(Constants.COLUMN_IS_EXPLICIT))), cur.getString(cur.getColumnIndex(Constants.COLUMN_TITLE)), cur.getString(cur.getColumnIndex(Constants.COLUMN_DESCRIPTION)), - photo, - 0); + photo); Log.d("Playlist", "generated " + Playlist.U.a(playlist).v1()); @@ -170,6 +169,50 @@ public class PlaylistCacheDb extends SQLiteOpenHelper implements AutoCloseable { return playlists; } + public long getTracksCountInPlaylist(String playlistId) { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.query( + Constants.TABLE_PLAYLIST_TRACKS, + new String[]{Constants.COLUMN_TRACK_ID}, + Constants.COLUMN_PLAYLIST_ID + " = ?", + new String[]{playlistId}, + null, null, null + ); + + long count = cursor.getCount(); + cursor.close(); + return count; + } + + public List getAllPlaylistIds() { + SQLiteDatabase db = getReadableDatabase(); + List playlistIds = new ArrayList<>(); + Cursor cursor = db.query( + Constants.TABLE_NAME, + new String[]{Constants.COLUMN_ID, Constants.COLUMN_OWNER_ID}, + null, null, null, null, null + ); + + if (cursor.moveToFirst()) { + do { + String playlistId = cursor.getString(cursor.getColumnIndexOrThrow(Constants.COLUMN_OWNER_ID)) + "_" + cursor.getString(cursor.getColumnIndexOrThrow(Constants.COLUMN_ID)); + playlistIds.add(playlistId); + } while (cursor.moveToNext()); + } + + cursor.close(); + return playlistIds; + } + + public boolean isPlaylistsDbEmpty() { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.rawQuery("SELECT EXISTS(SELECT 1 FROM " + Constants.TABLE_NAME + " LIMIT 1)", null); + cursor.moveToFirst(); + boolean isEmpty = cursor.getInt(0) == 0; + cursor.close(); + return isEmpty; + } + public void addTrackToPlaylist(String playlistId, String trackId) { ContentValues values = new ContentValues(); values.put(Constants.COLUMN_PLAYLIST_ID, playlistId); @@ -181,6 +224,15 @@ public class PlaylistCacheDb extends SQLiteOpenHelper implements AutoCloseable { getWritableDatabase().delete(Constants.TABLE_PLAYLIST_TRACKS, Constants.COLUMN_PLAYLIST_ID + " = ? AND " + Constants.COLUMN_TRACK_ID + " = ?", new String[]{playlistId, trackId}); } + public boolean isPlaylistEmpty(String playlistId) { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.rawQuery("SELECT EXISTS(SELECT 1 FROM " + Constants.TABLE_PLAYLIST_TRACKS + " WHERE " + Constants.COLUMN_PLAYLIST_ID + " = ? LIMIT 1)", new String[]{playlistId}); + cursor.moveToFirst(); + boolean isEmpty = cursor.getInt(0) == 0; + cursor.close(); + return isEmpty; + } + public List getTracksInPlaylist(String playlistId) { SQLiteDatabase db = getReadableDatabase(); Cursor cursor = db.query( diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/delegate/MusicCacheDbDelegate.java b/app/src/main/java/ru/vtosters/lite/music/cache/delegate/MusicCacheDbDelegate.java index 74d6ac22c..1db4616ba 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/delegate/MusicCacheDbDelegate.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/delegate/MusicCacheDbDelegate.java @@ -55,6 +55,12 @@ public class MusicCacheDbDelegate { } } + public static boolean isEmpty(Context context) { + try (var db = connectToDb(context)) { + return db.isDatabaseEmpty(); + } + } + public static boolean isCachedTrack(Context context, String trackId) { try (var db = connectToDb(context)) { return db.isCachedTrack(trackId); diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/delegate/PlaylistCacheDbDelegate.java b/app/src/main/java/ru/vtosters/lite/music/cache/delegate/PlaylistCacheDbDelegate.java index 15efe803f..f9e653b4c 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/delegate/PlaylistCacheDbDelegate.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/delegate/PlaylistCacheDbDelegate.java @@ -62,6 +62,31 @@ public class PlaylistCacheDbDelegate { } } + public static long getTracksCountInPlaylist(Context context, String playlistId) { + try (var db = connectToDb(context)) { + return db.getTracksCountInPlaylist(playlistId); + } + } + + public static boolean isPlaylistsDbEmpty(Context context) { + try (var db = connectToDb(context)) { + return db.isPlaylistsDbEmpty(); + } + } + + public static void removeAllPlaylists(Context context) { + List playlistIds = getAllPlaylistIds(context); + for (String playlistId : playlistIds) { + deletePlaylist(context, playlistId); + } + } + + public static List getAllPlaylistIds(Context context) { + try (var db = connectToDb(context)) { + return db.getAllPlaylistIds(); + } + } + public static boolean isCachedPlaylist(Context context, String id) { try (var db = connectToDb(context)) { String[] parts = id.split("_"); @@ -112,6 +137,12 @@ public class PlaylistCacheDbDelegate { } } + public static boolean isPlaylistEmpty(Context context, String playlistId) { + try (var db = connectToDb(context)) { + return db.isPlaylistEmpty(playlistId); + } + } + public static void drop(Context context) { context.deleteDatabase(PlaylistCacheDb.Constants.DB_NAME); } diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/helpers/PlaylistHelper.java b/app/src/main/java/ru/vtosters/lite/music/cache/helpers/PlaylistHelper.java index 51420f3b8..d5de9682c 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/helpers/PlaylistHelper.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/helpers/PlaylistHelper.java @@ -7,6 +7,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import ru.vtosters.lite.music.cache.MusicCacheImpl; +import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate; import ru.vtosters.lite.utils.AccountManagerUtils; import ru.vtosters.lite.utils.AndroidUtils; import ru.vtosters.lite.utils.NetworkUtils; @@ -25,19 +26,19 @@ public class PlaylistHelper { public static JSONArray addCachedPlaylists(JSONArray jsonArray, Boolean noPlaylists) { try { if (noPlaylists) { - jsonArray.put(new JSONArray().put(getCachedSongsPlaylist())); - } else { + jsonArray.put(new JSONArray()); + } + + if (!PlaylistCacheDbDelegate.isPlaylistEmpty(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1")) { jsonArray.put(getCachedSongsPlaylist()); } - for (Playlist playlist : MusicCacheImpl.getPlaylists()) { - if (noPlaylists) { - jsonArray.put(new JSONArray().put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, PlaylistUtils.getThumb(playlist), playlist.O))); - } else { - jsonArray.put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, PlaylistUtils.getThumb(playlist), playlist.O)); - } + if (MusicCacheImpl.hasPlaylist()) { + for (Playlist playlist : MusicCacheImpl.getPlaylists()) { + jsonArray.put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, PlaylistUtils.getThumb(playlist))); - Log.d("PlaylistHelper", "Playlist cache added: " + playlist.a + " " + playlist.b + " " + playlist.C + " " + playlist.g + " " + playlist.B); + Log.d("PlaylistHelper", "Playlist cache added: " + playlist.a + " " + playlist.b + " " + playlist.C + " " + playlist.g + " " + playlist.B); + } } } catch (JSONException e) { e.fillInStackTrace(); @@ -45,7 +46,7 @@ public class PlaylistHelper { return jsonArray; } - public static JSONObject generatePlaylist(int id, int owner_id, boolean is_explicit, String title, String description, JSONObject photo, int count) throws JSONException { + public static JSONObject generatePlaylist(int id, int owner_id, boolean is_explicit, String title, String description, JSONObject photo) throws JSONException { JSONObject playlist = new JSONObject() .put("id", id) .put("owner_id", owner_id) @@ -64,7 +65,7 @@ public class PlaylistHelper { .put("subtitle", "") .put("meta", new JSONObject() .put("view", "compact")) - .put("count", count); + .put("count", 0); if (photo != null) { playlist.put("photo", photo); @@ -101,18 +102,18 @@ public class PlaylistHelper { .put("height", 600)) .put("meta", new JSONObject() .put("view", "compact")) - .put("count", MusicCacheImpl.getAllOwnTracks().size()); + .put("count", 0); } public static JSONArray getCachedPlaylistsIds() { JSONArray arr = new JSONArray(); - if (NetworkUtils.isNetworkConnected() && !MusicCacheImpl.getAllOwnTracks().isEmpty()) { + if (NetworkUtils.isNetworkConnected() && !PlaylistCacheDbDelegate.isPlaylistEmpty(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1")) { arr.put(AccountManagerUtils.getUserId() + "_-1"); } - for (var playlist : MusicCacheImpl.getPlaylists()) { - arr.put(playlist.v1()); + for (String playlist : PlaylistCacheDbDelegate.getAllPlaylistIds(AndroidUtils.getGlobalContext())) { + arr.put(playlist); } return arr; diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/helpers/TracklistHelper.java b/app/src/main/java/ru/vtosters/lite/music/cache/helpers/TracklistHelper.java index 400970115..a9beed53e 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/helpers/TracklistHelper.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/helpers/TracklistHelper.java @@ -28,7 +28,7 @@ public class TracklistHelper { boolean doNotinvertOrder = Preferences.getBoolValue("invertCachedTracks", false); - if (!doNotinvertOrder) { + if (doNotinvertOrder) { Collections.reverse(tracks); } diff --git a/app/src/main/java/ru/vtosters/lite/ui/fragments/MusicFragment.java b/app/src/main/java/ru/vtosters/lite/ui/fragments/MusicFragment.java index c3ad88b7d..614b4d92d 100644 --- a/app/src/main/java/ru/vtosters/lite/ui/fragments/MusicFragment.java +++ b/app/src/main/java/ru/vtosters/lite/ui/fragments/MusicFragment.java @@ -20,6 +20,7 @@ import ru.vtosters.lite.music.LastFMScrobbler; import ru.vtosters.lite.music.cache.MusicCacheImpl; import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate; import ru.vtosters.lite.ui.PreferenceFragmentUtils; +import ru.vtosters.lite.utils.AccountManagerUtils; import ru.vtosters.lite.utils.AndroidUtils; import ru.vtosters.lite.utils.LifecycleUtils; @@ -55,7 +56,7 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment { if (MusicCacheImpl.isEmpty()) { AndroidUtils.sendToast(requireContext().getString(com.vtosters.lite.R.string.no_cache_error)); } else { - delcache(requireContext()); + delcache(requireContext(), false); } return true; } @@ -73,6 +74,18 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment { return true; } ); + + PreferenceFragmentUtils.addPreference( + getPreferenceScreen(), + "cached_playlists", + "Удалить все скачанные плейлисты", + null, + null, + preference -> { + delcache(requireContext(), true); + return true; + } + ); } PreferenceFragmentUtils.addPreference( @@ -443,12 +456,18 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment { builder.show(); } - private void delcache(Context ctx) { + private void delcache(Context ctx, boolean isPlaylists) { new VkAlertDialog.Builder(ctx) .setTitle(com.vtosters.lite.R.string.warning) .setMessage(com.vtosters.lite.R.string.cached_tracks_remove_confirm) .setPositiveButton(com.vtosters.lite.R.string.yes, (dialog, which) -> { - executor.submit(MusicCacheImpl::clear); + executor.submit(() -> { + if (isPlaylists) { + PlaylistCacheDbDelegate.removeAllPlaylists(ctx); + } else { + PlaylistCacheDbDelegate.deletePlaylist(ctx, AccountManagerUtils.getUserId() + "_-1"); + } + }); findPreference("cached_tracks").setSummary(String.format(requireContext().getString(com.vtosters.lite.R.string.cached_tracks_counter), MusicCacheImpl.getTracksCount())); }) .setNeutralButton(com.vtosters.lite.R.string.no, (dialog, which) -> dialog.cancel())