From 857963b336dcf51acccc6400e5ee7f97bd9bee5a Mon Sep 17 00:00:00 2001 From: JosJuice Date: Wed, 17 Nov 2021 21:29:11 +0100 Subject: [PATCH] Android: Make GameFileCacheManager use LiveData, part 1 --- .../services/GameFileCacheManager.java | 30 +++++------ .../dolphinemu/ui/main/MainPresenter.java | 54 +++++++++---------- 2 files changed, 38 insertions(+), 46 deletions(-) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java index f4ce251be1..5ff51c1b43 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java @@ -5,6 +5,8 @@ package org.dolphinemu.dolphinemu.services; import android.content.Context; import android.content.Intent; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.dolphinemu.dolphinemu.DolphinApplication; @@ -19,18 +21,12 @@ import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; /** * Loads game list data on a separate thread. */ public final class GameFileCacheManager { - /** - * This is broadcast when the contents of the cache change. - */ - public static final String CACHE_UPDATED = "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_UPDATED"; - /** * This is broadcast when the service is done with all requested work, regardless of whether * the contents of the cache actually changed. (Maybe the cache was already up to date.) @@ -39,8 +35,8 @@ public final class GameFileCacheManager "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_DONE_LOADING"; private static GameFileCache gameFileCache = null; - private static final AtomicReference gameFiles = - new AtomicReference<>(new GameFile[]{}); + private static final MutableLiveData gameFiles = + new MutableLiveData<>(new GameFile[]{}); private static final ExecutorService executor = Executors.newFixedThreadPool(1); private static final AtomicBoolean loadInProgress = new AtomicBoolean(false); @@ -50,9 +46,14 @@ public final class GameFileCacheManager { } + public static LiveData getGameFiles() + { + return gameFiles; + } + public static List getGameFilesForPlatform(Platform platform) { - GameFile[] allGames = gameFiles.get(); + GameFile[] allGames = gameFiles.getValue(); ArrayList platformGames = new ArrayList<>(); for (GameFile game : allGames) { @@ -66,7 +67,7 @@ public final class GameFileCacheManager public static GameFile getGameFileByGameId(String gameId) { - GameFile[] allGames = gameFiles.get(); + GameFile[] allGames = gameFiles.getValue(); for (GameFile game : allGames) { if (game.getGameId().equals(gameId)) @@ -81,7 +82,7 @@ public final class GameFileCacheManager { GameFile matchWithoutRevision = null; - GameFile[] allGames = gameFiles.get(); + GameFile[] allGames = gameFiles.getValue(); for (GameFile otherGame : allGames) { if (game.getGameId().equals(otherGame.getGameId()) && @@ -155,7 +156,7 @@ public final class GameFileCacheManager // Common case: The game is in the cache, so just grab it from there. // (Actually, addOrGet already checks for this case, but we want to avoid calling it if possible // because onHandleIntent may hold a lock on gameFileCache for extended periods of time.) - GameFile[] allGames = gameFiles.get(); + GameFile[] allGames = gameFiles.getValue(); for (GameFile game : allGames) { if (game.getPath().equals(gamePath)) @@ -189,7 +190,6 @@ public final class GameFileCacheManager if (gameFileCache.getSize() != 0) { updateGameFileArray(); - sendBroadcast(CACHE_UPDATED); } } } @@ -218,14 +218,12 @@ public final class GameFileCacheManager if (changed) { updateGameFileArray(); - sendBroadcast(CACHE_UPDATED); } boolean additionalMetadataChanged = gameFileCache.updateAdditionalMetadata(); if (additionalMetadataChanged) { updateGameFileArray(); - sendBroadcast(CACHE_UPDATED); } if (changed || additionalMetadataChanged) @@ -243,7 +241,7 @@ public final class GameFileCacheManager { GameFile[] gameFilesTemp = gameFileCache.getAllGames(); Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle())); - gameFiles.set(gameFilesTemp); + gameFiles.postValue(gameFilesTemp); } private static void sendBroadcast(String action) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java index 9aa95f3998..13caef1fc0 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java @@ -2,7 +2,6 @@ package org.dolphinemu.dolphinemu.ui.main; -import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -11,6 +10,7 @@ import android.content.IntentFilter; import android.net.Uri; import androidx.appcompat.app.AlertDialog; +import androidx.core.app.ComponentActivity; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.dolphinemu.dolphinemu.BuildConfig; @@ -42,14 +42,14 @@ public final class MainPresenter private static boolean sShouldRescanLibrary = true; private final MainView mView; - private final Context mContext; + private final ComponentActivity mActivity; private BroadcastReceiver mBroadcastReceiver = null; private String mDirToAdd; - public MainPresenter(MainView view, Context context) + public MainPresenter(MainView view, ComponentActivity activity) { mView = view; - mContext = context; + mActivity = activity; } public void onCreate() @@ -57,8 +57,9 @@ public final class MainPresenter String versionName = BuildConfig.VERSION_NAME; mView.setVersionString(versionName); + GameFileCacheManager.getGameFiles().observe(mActivity, (gameFiles) -> mView.showGames()); + IntentFilter filter = new IntentFilter(); - filter.addAction(GameFileCacheManager.CACHE_UPDATED); filter.addAction(GameFileCacheManager.DONE_LOADING); mBroadcastReceiver = new BroadcastReceiver() { @@ -67,23 +68,20 @@ public final class MainPresenter { switch (intent.getAction()) { - case GameFileCacheManager.CACHE_UPDATED: - mView.showGames(); - break; case GameFileCacheManager.DONE_LOADING: mView.setRefreshing(false); break; } } }; - LocalBroadcastManager.getInstance(mContext).registerReceiver(mBroadcastReceiver, filter); + LocalBroadcastManager.getInstance(mActivity).registerReceiver(mBroadcastReceiver, filter); } public void onDestroy() { if (mBroadcastReceiver != null) { - LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mBroadcastReceiver); + LocalBroadcastManager.getInstance(mActivity).unregisterReceiver(mBroadcastReceiver); } } @@ -142,10 +140,10 @@ public final class MainPresenter if (sShouldRescanLibrary && !GameFileCacheManager.isRescanning()) { - new AfterDirectoryInitializationRunner().run(mContext, false, () -> + new AfterDirectoryInitializationRunner().run(mActivity, false, () -> { mView.setRefreshing(true); - GameFileCacheManager.startRescan(mContext); + GameFileCacheManager.startRescan(mActivity); }); } @@ -172,20 +170,20 @@ public final class MainPresenter if (Arrays.stream(childNames).noneMatch((name) -> FileBrowserHelper.GAME_EXTENSIONS.contains( FileBrowserHelper.getExtension(name, false)))) { - AlertDialog.Builder builder = new AlertDialog.Builder(mContext, R.style.DolphinDialogBase); - builder.setMessage(mContext.getString(R.string.wrong_file_extension_in_directory, + AlertDialog.Builder builder = new AlertDialog.Builder(mActivity, R.style.DolphinDialogBase); + builder.setMessage(mActivity.getString(R.string.wrong_file_extension_in_directory, FileBrowserHelper.setToSortedDelimitedString(FileBrowserHelper.GAME_EXTENSIONS))); builder.setPositiveButton(R.string.ok, null); builder.show(); } - ContentResolver contentResolver = mContext.getContentResolver(); + ContentResolver contentResolver = mActivity.getContentResolver(); Uri canonicalizedUri = contentResolver.canonicalize(uri); if (canonicalizedUri != null) uri = canonicalizedUri; int takeFlags = result.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION; - mContext.getContentResolver().takePersistableUriPermission(uri, takeFlags); + mActivity.getContentResolver().takePersistableUriPermission(uri, takeFlags); mDirToAdd = uri.toString(); } @@ -196,24 +194,22 @@ public final class MainPresenter { boolean success = WiiUtils.installWAD(path); int message = success ? R.string.wad_install_success : R.string.wad_install_failure; - return mContext.getResources().getString(message); + return mActivity.getResources().getString(message); }); } public void importWiiSave(String path) { - final Activity mainPresenterActivity = (Activity) mContext; - CompletableFuture canOverwriteFuture = new CompletableFuture<>(); runOnThreadAndShowResult(R.string.import_in_progress, 0, () -> { BooleanSupplier canOverwrite = () -> { - mainPresenterActivity.runOnUiThread(() -> + mActivity.runOnUiThread(() -> { AlertDialog.Builder builder = - new AlertDialog.Builder(mContext, R.style.DolphinDialogBase); + new AlertDialog.Builder(mActivity, R.style.DolphinDialogBase); builder.setMessage(R.string.wii_save_exists); builder.setCancelable(false); builder.setPositiveButton(R.string.yes, (dialog, i) -> canOverwriteFuture.complete(true)); @@ -252,14 +248,14 @@ public final class MainPresenter message = R.string.wii_save_import_error; break; } - return mContext.getResources().getString(message); + return mActivity.getResources().getString(message); }); } public void importNANDBin(String path) { AlertDialog.Builder builder = - new AlertDialog.Builder(mContext, R.style.DolphinDialogBase); + new AlertDialog.Builder(mActivity, R.style.DolphinDialogBase); builder.setMessage(R.string.nand_import_warning); builder.setNegativeButton(R.string.no, (dialog, i) -> dialog.dismiss()); @@ -281,33 +277,31 @@ public final class MainPresenter private void runOnThreadAndShowResult(int progressTitle, int progressMessage, Supplier f) { - final Activity mainPresenterActivity = (Activity) mContext; - - AlertDialog progressDialog = new AlertDialog.Builder(mContext, R.style.DolphinDialogBase) + AlertDialog progressDialog = new AlertDialog.Builder(mActivity, R.style.DolphinDialogBase) .create(); progressDialog.setTitle(progressTitle); if (progressMessage != 0) - progressDialog.setMessage(mContext.getResources().getString(progressMessage)); + progressDialog.setMessage(mActivity.getResources().getString(progressMessage)); progressDialog.setCancelable(false); progressDialog.show(); new Thread(() -> { String result = f.get(); - mainPresenterActivity.runOnUiThread(() -> + mActivity.runOnUiThread(() -> { progressDialog.dismiss(); if (result != null) { AlertDialog.Builder builder = - new AlertDialog.Builder(mContext, R.style.DolphinDialogBase); + new AlertDialog.Builder(mActivity, R.style.DolphinDialogBase); builder.setMessage(result); builder.setPositiveButton(R.string.ok, (dialog, i) -> dialog.dismiss()); builder.show(); } }); - }, mContext.getResources().getString(progressTitle)).start(); + }, mActivity.getResources().getString(progressTitle)).start(); } public static void skipRescanningLibrary()