Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.ColorStateList;
import android.graphics.BlendMode;
import android.graphics.BlendModeColorFilter;
Expand Down Expand Up @@ -37,6 +38,8 @@
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.TintTypedArray;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import androidx.window.layout.WindowMetricsCalculator;
Expand Down Expand Up @@ -66,6 +69,67 @@

public class PlatformInterop {

/**
* Checks if the given context is destroyed.
* This is similar to the C# IsDestroyed extension method in ContextExtensions.cs
* @param context The context to check
* @return true if the context is destroyed, false otherwise
*/
private static boolean isContextDestroyed(Context context) {
if (context == null) {
return true;
}

Activity activity = getActivity(context);
if (activity instanceof FragmentActivity) {
FragmentActivity fragmentActivity = (FragmentActivity) activity;

// Check if activity is finishing or destroyed
if (fragmentActivity.isFinishing() || fragmentActivity.isDestroyed()) {
return true;
}

// Check lifecycle state
try {
if (fragmentActivity.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
return true;
}
} catch (Exception e) {
// If there's an exception getting the lifecycle state, consider it destroyed
return true;
}
} else if (activity != null) {
// For regular Activity, check if finishing or destroyed
if (activity.isFinishing() || activity.isDestroyed()) {
return true;
}
}

return false;
}

/**
* Gets the Activity from a Context, similar to the C# GetActivity extension method.
* @param context The context to get the activity from
* @return The activity if found, null otherwise
*/
private static Activity getActivity(Context context) {
if (context == null) {
return null;
}

if (context instanceof Activity) {
return (Activity) context;
}

if (context instanceof ContextWrapper) {
Context baseContext = ((ContextWrapper) context).getBaseContext();
return getActivity(baseContext);
}

return null;
}

public static void requestLayoutIfNeeded(View view) {

// If the view isn't currently in the layout process, then we simply request
Expand Down Expand Up @@ -363,13 +427,21 @@ public static void loadImageFromFont(ImageView imageView, @ColorInt int color, S
}

public static void loadImageFromFile(Context context, String file, ImageLoaderCallback callback) {
if (isContextDestroyed(context)) {
callback.onComplete(false, null, null);
return;
}
RequestBuilder<Drawable> builder = Glide
.with(context)
.load(file);
load(builder, context, true, callback, file);
}

public static void loadImageFromUri(Context context, String uri, boolean cachingEnabled, ImageLoaderCallback callback) {
if (isContextDestroyed(context)) {
callback.onComplete(false, null, null);
return;
}
Uri androidUri = Uri.parse(uri);
if (androidUri == null) {
callback.onComplete(false, null, null);
Expand All @@ -382,13 +454,21 @@ public static void loadImageFromUri(Context context, String uri, boolean caching
}

public static void loadImageFromStream(Context context, InputStream inputStream, ImageLoaderCallback callback) {
if (isContextDestroyed(context)) {
callback.onComplete(false, null, null);
return;
}
RequestBuilder<Drawable> builder = Glide
.with(context)
.load(inputStream);
load(builder, context, false, callback, inputStream);
}

public static void loadImageFromFont(Context context, @ColorInt int color, String glyph, Typeface typeface, float textSize, ImageLoaderCallback callback) {
if (isContextDestroyed(context)) {
callback.onComplete(false, null, null);
return;
}
FontModel fontModel = new FontModel(color, glyph, textSize, typeface);
RequestBuilder<Drawable> builder = Glide
.with(context)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.microsoft.maui.glide;

import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Lifecycle;

import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
Expand All @@ -25,6 +29,71 @@ public class MauiCustomTarget extends CustomTarget<Drawable> implements MauiTarg
private final String resourceLogIdentifier;
private boolean completed;

/**
* Checks if the given context is destroyed.
* @param context The context to check
* @return true if the context is destroyed, false otherwise
*/
private static boolean isContextDestroyed(Context context) {
if (context == null) {
return true;
}

Activity activity = getActivity(context);
if (activity instanceof FragmentActivity) {
FragmentActivity fragmentActivity = (FragmentActivity) activity;

// Check if activity is finishing or destroyed
if (fragmentActivity.isFinishing() || fragmentActivity.isDestroyed()) {
return true;
}

// Check lifecycle state
try {
if (fragmentActivity.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
return true;
}
} catch (Exception e) {
// If there's an exception getting the lifecycle state, consider it destroyed
return true;
}
} else if (activity != null) {
// For regular Activity, check if finishing or destroyed
if (activity.isFinishing() || activity.isDestroyed()) {
return true;
}
}

return false;
}

/**
* Gets the Activity from a Context.
* @param context The context to get the activity from
* @return The activity if found, null otherwise
*/
private static Activity getActivity(Context context) {
if (context == null) {
return null;
}

if (context instanceof Activity) {
return (Activity) context;
}

if (context instanceof ContextWrapper) {
Context baseContext = ((ContextWrapper) context).getBaseContext();
return getActivity(baseContext);
}

return null;
}

private final Context context;
private final ImageLoaderCallback callback;
private final String resourceLogIdentifier;
private boolean completed;

public MauiCustomTarget(Context context, ImageLoaderCallback callback, Object model) {
this.completed = false;
this.context = context;
Expand Down Expand Up @@ -84,9 +153,11 @@ private void clear() {
// TODO: it looks like no one is really disposing the result on C# side
// we must fix it there to release the Glide cache entry properly
post(() -> {
Glide
.with(context)
.clear(this);
if (!isContextDestroyed(context)) {
Glide
.with(context)
.clear(this);
}
});
}
}
Loading