summaryrefslogtreecommitdiff
path: root/Source/Android/app
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2022-11-13 14:59:00 +0100
committerGitHub <noreply@github.com>2022-11-13 14:59:00 +0100
commit2340a7eea6d2fbb93f373dd2630ff55c9ecdafda (patch)
treef3e18b3a40a90d29e6880d9e65243f94f6b55e85 /Source/Android/app
parent1e80bcbd57585b6af9e5214cf66c55eb54d23db1 (diff)
parent6eb50133598941b166ace27346139929e6315aea (diff)
Merge pull request #11248 from t895/offload-unmangle
Android: Offload cover path unmangling to another thread
Diffstat (limited to 'Source/Android/app')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java7
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GlideUtils.java269
4 files changed, 155 insertions, 125 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java
index 21470269a9..01a8b9dddb 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java
@@ -2,6 +2,7 @@
package org.dolphinemu.dolphinemu.adapters;
+import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
@@ -27,14 +28,16 @@ public final class GameAdapter extends RecyclerView.Adapter<GameAdapter.GameView
View.OnLongClickListener
{
private List<GameFile> mGameFiles;
+ private Activity mActivity;
/**
* Initializes the adapter's observer, which watches for changes to the dataset. The adapter will
* display no data until swapDataSet is called.
*/
- public GameAdapter()
+ public GameAdapter(Activity activity)
{
mGameFiles = new ArrayList<>();
+ mActivity = activity;
}
/**
@@ -70,7 +73,7 @@ public final class GameAdapter extends RecyclerView.Adapter<GameAdapter.GameView
{
Context context = holder.itemView.getContext();
GameFile gameFile = mGameFiles.get(position);
- GlideUtils.loadGameCover(holder, holder.binding.imageGameScreen, gameFile);
+ GlideUtils.loadGameCover(holder, holder.binding.imageGameScreen, gameFile, mActivity);
if (GameFileCacheManager.findSecondDisc(gameFile) != null)
{
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java
index b1a0665407..53b0e56861 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java
@@ -50,7 +50,7 @@ public final class GameRowPresenter extends Presenter
GameFile gameFile = (GameFile) item;
holder.imageScreenshot.setImageDrawable(null);
- GlideUtils.loadGameCover(null, holder.imageScreenshot, gameFile);
+ GlideUtils.loadGameCover(null, holder.imageScreenshot, gameFile, null);
holder.cardParent.setTitleText(gameFile.getTitle());
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java
index 80a7a35fac..9b3cd0e87f 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java
@@ -65,7 +65,7 @@ public final class PlatformGamesFragment extends Fragment implements PlatformGam
int columns = getResources().getInteger(R.integer.game_grid_columns);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), columns);
- mAdapter = new GameAdapter();
+ mAdapter = new GameAdapter(requireActivity());
// Set theme color to the refresh animation's background
mSwipeRefresh.setProgressBackgroundColorSchemeColor(
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GlideUtils.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GlideUtils.java
index 0ddf4d44f8..766d9684dc 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GlideUtils.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/GlideUtils.java
@@ -2,11 +2,14 @@
package org.dolphinemu.dolphinemu.utils;
+import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
import android.view.View;
import android.widget.ImageView;
@@ -34,7 +37,9 @@ import java.util.concurrent.Executors;
public class GlideUtils
{
- private static final ExecutorService executor = Executors.newSingleThreadExecutor();
+ private static final ExecutorService saveCoverExecutor = Executors.newSingleThreadExecutor();
+ private static final ExecutorService unmangleExecutor = Executors.newSingleThreadExecutor();
+ private static final Handler unmangleHandler = new Handler(Looper.getMainLooper());
public static void loadGameBanner(ImageView imageView, GameFile gameFile)
{
@@ -61,7 +66,7 @@ public class GlideUtils
}
public static void loadGameCover(GameAdapter.GameViewHolder gameViewHolder, ImageView imageView,
- GameFile gameFile)
+ GameFile gameFile, Activity activity)
{
if (BooleanSetting.MAIN_SHOW_GAME_TITLES.getBooleanGlobal() && gameViewHolder != null)
{
@@ -77,134 +82,156 @@ public class GlideUtils
gameViewHolder.binding.textGameCaption.setVisibility(View.GONE);
}
- String customCoverPath = gameFile.getCustomCoverPath();
- Uri customCoverUri = null;
- boolean customCoverExists = false;
- if (ContentHandler.isContentUri(customCoverPath))
+ unmangleExecutor.execute(() ->
{
- try
+ String customCoverPath = gameFile.getCustomCoverPath();
+ Uri customCoverUri = null;
+ boolean customCoverExists = false;
+ if (ContentHandler.isContentUri(customCoverPath))
{
- customCoverUri = ContentHandler.unmangle(customCoverPath);
- customCoverExists = true;
+ try
+ {
+ customCoverUri = ContentHandler.unmangle(customCoverPath);
+ customCoverExists = true;
+ }
+ catch (FileNotFoundException | SecurityException ignored)
+ {
+ // Let customCoverExists remain false
+ }
}
- catch (FileNotFoundException | SecurityException ignored)
+ else
{
- // Let customCoverExists remain false
+ customCoverUri = Uri.parse(customCoverPath);
+ customCoverExists = new File(customCoverPath).exists();
}
- }
- else
- {
- customCoverUri = Uri.parse(customCoverPath);
- customCoverExists = new File(customCoverPath).exists();
- }
- Context context = imageView.getContext();
- File cover;
- if (customCoverExists)
- {
- Glide.with(context)
- .load(customCoverUri)
- .diskCacheStrategy(DiskCacheStrategy.NONE)
- .centerCrop()
- .listener(new RequestListener<Drawable>()
- {
- @Override public boolean onLoadFailed(@Nullable GlideException e, Object model,
- Target<Drawable> target, boolean isFirstResource)
- {
- GlideUtils.enableInnerTitle(gameViewHolder, imageView);
- return false;
- }
-
- @Override public boolean onResourceReady(Drawable resource, Object model,
- Target<Drawable> target, DataSource dataSource, boolean isFirstResource)
- {
- GlideUtils.disableInnerTitle(gameViewHolder);
- return false;
- }
- })
- .into(imageView);
- }
- else if ((cover = new File(gameFile.getCoverPath(context))).exists())
- {
- Glide.with(context)
- .load(cover)
- .diskCacheStrategy(DiskCacheStrategy.NONE)
- .centerCrop()
- .listener(new RequestListener<Drawable>()
- {
- @Override
- public boolean onLoadFailed(@Nullable GlideException e, Object model,
- Target<Drawable> target, boolean isFirstResource)
- {
- GlideUtils.enableInnerTitle(gameViewHolder, imageView);
- return false;
- }
-
- @Override
- public boolean onResourceReady(Drawable resource, Object model,
- Target<Drawable> target, DataSource dataSource, boolean isFirstResource)
- {
- GlideUtils.disableInnerTitle(gameViewHolder);
- return false;
- }
- })
- .into(imageView);
- }
- else if (BooleanSetting.MAIN_USE_GAME_COVERS.getBooleanGlobal())
- {
- Glide.with(context)
- .load(CoverHelper.buildGameTDBUrl(gameFile, CoverHelper.getRegion(gameFile)))
- .diskCacheStrategy(DiskCacheStrategy.NONE)
- .centerCrop()
- .listener(new RequestListener<Drawable>()
- {
- @Override
- public boolean onLoadFailed(@Nullable GlideException e, Object model,
- Target<Drawable> target, boolean isFirstResource)
- {
- GlideUtils.enableInnerTitle(gameViewHolder, imageView);
- return false;
- }
-
- @Override
- public boolean onResourceReady(Drawable resource, Object model,
- Target<Drawable> target, DataSource dataSource, boolean isFirstResource)
- {
- GlideUtils.disableInnerTitle(gameViewHolder);
- return false;
- }
- })
- .into(new CustomTarget<Drawable>()
- {
- @Override
- public void onResourceReady(@NonNull Drawable resource,
- @Nullable Transition<? super Drawable> transition)
- {
- Bitmap cover = ((BitmapDrawable) resource).getBitmap();
- executor.execute(
- () -> CoverHelper.saveCover(cover, gameFile.getCoverPath(context)));
- imageView.setImageBitmap(cover);
- }
-
- @Override
- public void onLoadCleared(@Nullable Drawable placeholder)
- {
- }
- });
- }
- else
- {
- enableInnerTitle(gameViewHolder, imageView);
- }
+ Context context = imageView.getContext();
+ boolean finalCustomCoverExists = customCoverExists;
+ Uri finalCustomCoverUri = customCoverUri;
+
+ File cover = new File(gameFile.getCoverPath(context));
+ boolean cachedCoverExists = cover.exists();
+ unmangleHandler.post(() ->
+ {
+ // We can't get a reference to the current activity in the TV version.
+ // Luckily it won't attempt to start loads on destroyed activities.
+ if (activity != null)
+ {
+ // We can't start an image load on a destroyed activity
+ if (activity.isDestroyed())
+ {
+ return;
+ }
+ }
+
+ if (finalCustomCoverExists)
+ {
+ Glide.with(imageView)
+ .load(finalCustomCoverUri)
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .centerCrop()
+ .error(R.drawable.no_banner)
+ .listener(new RequestListener<Drawable>()
+ {
+ @Override public boolean onLoadFailed(@Nullable GlideException e, Object model,
+ Target<Drawable> target, boolean isFirstResource)
+ {
+ GlideUtils.enableInnerTitle(gameViewHolder);
+ return false;
+ }
+
+ @Override public boolean onResourceReady(Drawable resource, Object model,
+ Target<Drawable> target, DataSource dataSource, boolean isFirstResource)
+ {
+ GlideUtils.disableInnerTitle(gameViewHolder);
+ return false;
+ }
+ })
+ .into(imageView);
+ }
+ else if (cachedCoverExists)
+ {
+ Glide.with(imageView)
+ .load(cover)
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .centerCrop()
+ .error(R.drawable.no_banner)
+ .listener(new RequestListener<Drawable>()
+ {
+ @Override
+ public boolean onLoadFailed(@Nullable GlideException e, Object model,
+ Target<Drawable> target, boolean isFirstResource)
+ {
+ GlideUtils.enableInnerTitle(gameViewHolder);
+ return false;
+ }
+
+ @Override
+ public boolean onResourceReady(Drawable resource, Object model,
+ Target<Drawable> target, DataSource dataSource, boolean isFirstResource)
+ {
+ GlideUtils.disableInnerTitle(gameViewHolder);
+ return false;
+ }
+ })
+ .into(imageView);
+ }
+ else if (BooleanSetting.MAIN_USE_GAME_COVERS.getBooleanGlobal())
+ {
+ Glide.with(context)
+ .load(CoverHelper.buildGameTDBUrl(gameFile, CoverHelper.getRegion(gameFile)))
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .centerCrop()
+ .error(R.drawable.no_banner)
+ .listener(new RequestListener<Drawable>()
+ {
+ @Override
+ public boolean onLoadFailed(@Nullable GlideException e, Object model,
+ Target<Drawable> target, boolean isFirstResource)
+ {
+ GlideUtils.enableInnerTitle(gameViewHolder);
+ return false;
+ }
+
+ @Override
+ public boolean onResourceReady(Drawable resource, Object model,
+ Target<Drawable> target, DataSource dataSource, boolean isFirstResource)
+ {
+ GlideUtils.disableInnerTitle(gameViewHolder);
+ return false;
+ }
+ })
+ .into(new CustomTarget<Drawable>()
+ {
+ @Override
+ public void onResourceReady(@NonNull Drawable resource,
+ @Nullable Transition<? super Drawable> transition)
+ {
+ Bitmap cover = ((BitmapDrawable) resource).getBitmap();
+ saveCoverExecutor.execute(
+ () -> CoverHelper.saveCover(cover, gameFile.getCoverPath(context)));
+ imageView.setImageBitmap(cover);
+ }
+
+ @Override
+ public void onLoadCleared(@Nullable Drawable placeholder)
+ {
+ }
+ });
+ }
+ else
+ {
+ Glide.with(imageView.getContext())
+ .load(R.drawable.no_banner)
+ .into(imageView);
+ enableInnerTitle(gameViewHolder);
+ }
+ });
+ });
}
- private static void enableInnerTitle(GameAdapter.GameViewHolder gameViewHolder,
- ImageView imageView)
+ private static void enableInnerTitle(GameAdapter.GameViewHolder gameViewHolder)
{
- Glide.with(imageView.getContext())
- .load(R.drawable.no_banner)
- .into(imageView);
-
if (gameViewHolder != null && !BooleanSetting.MAIN_SHOW_GAME_TITLES.getBooleanGlobal())
{
gameViewHolder.binding.textGameTitleInner.setVisibility(View.VISIBLE);