Skip to content
Permalink
Browse files
Merge pull request #10229 from JosJuice/android-game-list-livedata
Android: Make GameFileCacheManager use LiveData
  • Loading branch information
lioncash committed Nov 17, 2021
2 parents 735fd60 + 2941cf8 commit 8b57aad
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 120 deletions.
@@ -2,16 +2,12 @@

package org.dolphinemu.dolphinemu.activities;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

import androidx.fragment.app.FragmentActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.services.GameFileCacheManager;
@@ -69,22 +65,13 @@ private void initResources()
mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner();
mAfterDirectoryInitializationRunner.run(this, true, () -> tryPlay(playAction));

IntentFilter gameFileCacheIntentFilter = new IntentFilter(GameFileCacheManager.DONE_LOADING);

BroadcastReceiver gameFileCacheReceiver = new BroadcastReceiver()
GameFileCacheManager.isLoading().observe(this, (isLoading) ->
{
@Override
public void onReceive(Context context, Intent intent)
if (!isLoading && DirectoryInitialization.areDolphinDirectoriesReady())
{
if (DirectoryInitialization.areDolphinDirectoriesReady())
{
tryPlay(playAction);
}
tryPlay(playAction);
}
};

LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
broadcastManager.registerReceiver(gameFileCacheReceiver, gameFileCacheIntentFilter);
});

DirectoryInitialization.start(this);
GameFileCacheManager.startLoad(this);
@@ -110,7 +97,7 @@ private void tryPlay(AppLinkHelper.PlayAction action)

// If game == null and the load isn't done, wait for the next GameFileCacheService broadcast.
// If game == null and the load is done, call play with a null game, making us exit in failure.
if (game != null || !GameFileCacheManager.isLoading())
if (game != null || !GameFileCacheManager.isLoading().getValue())
{
play(action, game);
}
@@ -3,11 +3,10 @@
package org.dolphinemu.dolphinemu.services;

import android.content.Context;
import android.content.Intent;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.model.GameFileCache;
import org.dolphinemu.dolphinemu.ui.platform.Platform;
@@ -18,41 +17,32 @@
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.)
*/
public static final String DONE_LOADING =
"org.dolphinemu.dolphinemu.GAME_FILE_CACHE_DONE_LOADING";

private static GameFileCache gameFileCache = null;
private static final AtomicReference<GameFile[]> gameFiles =
new AtomicReference<>(new GameFile[]{});
private static final MutableLiveData<GameFile[]> gameFiles =
new MutableLiveData<>(new GameFile[]{});

private static final ExecutorService executor = Executors.newFixedThreadPool(1);
private static final AtomicBoolean loadInProgress = new AtomicBoolean(false);
private static final AtomicBoolean rescanInProgress = new AtomicBoolean(false);
private static final MutableLiveData<Boolean> loadInProgress = new MutableLiveData<>(false);
private static final MutableLiveData<Boolean> rescanInProgress = new MutableLiveData<>(false);

private GameFileCacheManager()
{
}

public static LiveData<GameFile[]> getGameFiles()
{
return gameFiles;
}

public static List<GameFile> getGameFilesForPlatform(Platform platform)
{
GameFile[] allGames = gameFiles.get();
GameFile[] allGames = gameFiles.getValue();
ArrayList<GameFile> platformGames = new ArrayList<>();
for (GameFile game : allGames)
{
@@ -66,7 +56,7 @@ public static List<GameFile> getGameFilesForPlatform(Platform platform)

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 +71,7 @@ public static GameFile findSecondDisc(GameFile game)
{
GameFile matchWithoutRevision = null;

GameFile[] allGames = gameFiles.get();
GameFile[] allGames = gameFiles.getValue();
for (GameFile otherGame : allGames)
{
if (game.getGameId().equals(otherGame.getGameId()) &&
@@ -107,19 +97,24 @@ public static String[] findSecondDiscAndGetPaths(GameFile gameFile)
}

/**
* Returns true if in the process of either loading the cache or rescanning.
* Returns true if in the process of loading the cache for the first time.
*/
public static boolean isLoading()
public static LiveData<Boolean> isLoading()
{
return loadInProgress.get();
return loadInProgress;
}

/**
* Returns true if in the process of rescanning.
*/
public static boolean isRescanning()
public static LiveData<Boolean> isRescanning()
{
return rescanInProgress;
}

public static boolean isLoadingOrRescanning()
{
return rescanInProgress.get();
return loadInProgress.getValue() || rescanInProgress.getValue();
}

/**
@@ -129,8 +124,9 @@ public static boolean isRescanning()
*/
public static void startLoad(Context context)
{
if (loadInProgress.compareAndSet(false, true))
if (!loadInProgress.getValue())
{
loadInProgress.setValue(true);
new AfterDirectoryInitializationRunner().run(context, false,
() -> executor.execute(GameFileCacheManager::load));
}
@@ -143,8 +139,9 @@ public static void startLoad(Context context)
*/
public static void startRescan(Context context)
{
if (rescanInProgress.compareAndSet(false, true))
if (!rescanInProgress.getValue())
{
rescanInProgress.setValue(true);
new AfterDirectoryInitializationRunner().run(context, false,
() -> executor.execute(GameFileCacheManager::rescan));
}
@@ -155,7 +152,7 @@ public static GameFile addOrGet(String gamePath)
// 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,14 +186,11 @@ private static void load()
if (gameFileCache.getSize() != 0)
{
updateGameFileArray();
sendBroadcast(CACHE_UPDATED);
}
}
}

loadInProgress.set(false);
if (!rescanInProgress.get())
sendBroadcast(DONE_LOADING);
loadInProgress.postValue(false);
}

/**
@@ -218,14 +212,12 @@ private static void rescan()
if (changed)
{
updateGameFileArray();
sendBroadcast(CACHE_UPDATED);
}

boolean additionalMetadataChanged = gameFileCache.updateAdditionalMetadata();
if (additionalMetadataChanged)
{
updateGameFileArray();
sendBroadcast(CACHE_UPDATED);
}

if (changed || additionalMetadataChanged)
@@ -234,21 +226,13 @@ private static void rescan()
}
}

rescanInProgress.set(false);
if (!loadInProgress.get())
sendBroadcast(DONE_LOADING);
rescanInProgress.postValue(false);
}

private static void updateGameFileArray()
{
GameFile[] gameFilesTemp = gameFileCache.getAllGames();
Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle()));
gameFiles.set(gameFilesTemp);
}

private static void sendBroadcast(String action)
{
LocalBroadcastManager.getInstance(DolphinApplication.getAppContext())
.sendBroadcast(new Intent(action));
gameFiles.postValue(gameFilesTemp);
}
}

0 comments on commit 8b57aad

Please sign in to comment.