diff --git a/android/src/main/java/com/taobao/power_image/PowerImageEngineContext.java b/android/src/main/java/com/taobao/power_image/PowerImageEngineContext.java new file mode 100644 index 0000000..ae9ecd1 --- /dev/null +++ b/android/src/main/java/com/taobao/power_image/PowerImageEngineContext.java @@ -0,0 +1,125 @@ +package com.taobao.power_image; + +import androidx.annotation.NonNull; + +import com.taobao.power_image.request.PowerImageRequestManager; + +import java.util.List; +import java.util.Map; + +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.EventChannel; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.view.TextureRegistry; + +/** + * created by Yangjiakang on 2022/11/19 + */ +public class PowerImageEngineContext implements MethodChannel.MethodCallHandler { + + private final PowerImageRequestManager powerImageRequestManager; + private final PowerImageEventSink powerImageEventSink; + + /// The MethodChannel that will the communication between Flutter and native Android + /// + /// This local reference serves to register the plugin with the Flutter Engine and unregister it + /// when the Flutter Engine is detached from the Activity + private MethodChannel methodChannel; + private EventChannel eventChannel; + + public PowerImageEngineContext() { + powerImageRequestManager = new PowerImageRequestManager(this); + powerImageEventSink = new PowerImageEventSink(); + } + + public void onAttachedToEngine(@NonNull FlutterPlugin.FlutterPluginBinding flutterPluginBinding) { + methodChannel = new MethodChannel( + flutterPluginBinding.getBinaryMessenger(), "power_image/method"); + methodChannel.setMethodCallHandler(this); + eventChannel = new EventChannel( + flutterPluginBinding.getBinaryMessenger(), "power_image/event"); + eventChannel.setStreamHandler(powerImageEventSink); + + configWithTextureRegistry(flutterPluginBinding.getTextureRegistry()); + } + + public void configWithTextureRegistry(TextureRegistry textureRegistry) { + powerImageRequestManager.configWithTextureRegistry(textureRegistry); + } + + public List> configRequestsWithArguments(List> list) { + return powerImageRequestManager.configRequestsWithArguments(list); + } + + public void startLoadingWithArguments(List arguments) { + powerImageRequestManager.startLoadingWithArguments(arguments); + } + + public List> releaseRequestsWithArguments(List arguments) { + return powerImageRequestManager.releaseRequestsWithArguments(arguments); + } + + public void sendImageStateEvent(Map event, boolean success) { + if (powerImageEventSink != null) { + powerImageEventSink.sendImageStateEvent(event, success); + } + } + + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { + if ("startImageRequests".equals(call.method)) { + if (call.arguments instanceof List) { + List arguments = (List) call.arguments; + List results = configRequestsWithArguments(arguments); + result.success(results); + startLoadingWithArguments(arguments); + } else { + throw new IllegalArgumentException("startImageRequests require List arguments"); + } + } else if ("releaseImageRequests".equals(call.method)) { + if (call.arguments instanceof List) { + List arguments = (List) call.arguments; + List results = releaseRequestsWithArguments(arguments); + result.success(results); + } else { + throw new IllegalArgumentException("stopImageRequests require List arguments"); + } + } else { + result.notImplemented(); + } + } + + public void onDetached() { + if (methodChannel != null) { + methodChannel.setMethodCallHandler(null); + } + if (eventChannel != null) { + eventChannel.setStreamHandler(null); + } + } + + public static class PowerImageEventSink implements EventChannel.StreamHandler { + + private EventChannel.EventSink eventSink; + + @Override + public void onListen(Object arguments, EventChannel.EventSink events) { + eventSink = events; + } + + @Override + public void onCancel(Object arguments) { + eventSink = null; + } + + public void sendImageStateEvent(Map event, boolean success) { + if (eventSink == null || event == null) { + return; + } + event.put("eventName", "onReceiveImageEvent"); + event.put("success", success); + eventSink.success(event); + } + } +} diff --git a/android/src/main/java/com/taobao/power_image/PowerImagePlugin.java b/android/src/main/java/com/taobao/power_image/PowerImagePlugin.java index 495c41e..ba83f94 100644 --- a/android/src/main/java/com/taobao/power_image/PowerImagePlugin.java +++ b/android/src/main/java/com/taobao/power_image/PowerImagePlugin.java @@ -3,32 +3,20 @@ import android.content.Context; -import com.taobao.power_image.dispatcher.PowerImageDispatcher; -import com.taobao.power_image.request.PowerImageRequestManager; +import androidx.annotation.NonNull; -import java.util.List; -import java.util.Map; +import com.taobao.power_image.dispatcher.PowerImageDispatcher; import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.plugin.common.EventChannel; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; /** * PowerImagePlugin */ -public class PowerImagePlugin implements FlutterPlugin, MethodCallHandler { - /// The MethodChannel that will the communication between Flutter and native Android - /// - /// This local reference serves to register the plugin with the Flutter Engine and unregister it - /// when the Flutter Engine is detached from the Activity - private MethodChannel methodChannel; - private EventChannel eventChannel; - private static Context sContext; - - public static Context getContext(){ +public class PowerImagePlugin implements FlutterPlugin { + + private static Context sContext; + + public static Context getContext() { return sContext; } @@ -36,87 +24,25 @@ public static Context getContext(){ System.loadLibrary("powerimage"); } + private PowerImageEngineContext engineContext; + @Override - public void onAttachedToEngine(FlutterPluginBinding flutterPluginBinding) { - if(sContext == null){ + public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { + if (sContext == null) { sContext = flutterPluginBinding.getApplicationContext(); } - methodChannel = new MethodChannel( - flutterPluginBinding.getBinaryMessenger(), "power_image/method"); - methodChannel.setMethodCallHandler(this); - eventChannel = new EventChannel( - flutterPluginBinding.getBinaryMessenger(), "power_image/event"); - eventChannel.setStreamHandler(PowerImageEventSink.getInstance()); - PowerImageRequestManager.getInstance() - .configWithTextureRegistry(flutterPluginBinding.getTextureRegistry()); + if (engineContext == null) { + engineContext = new PowerImageEngineContext(); + } + engineContext.onAttachedToEngine(flutterPluginBinding); PowerImageDispatcher.getInstance().prepare(); } @Override public void onDetachedFromEngine(FlutterPluginBinding binding) { - methodChannel.setMethodCallHandler(null); - eventChannel.setStreamHandler(null); - } - - @Override - public void onMethodCall(MethodCall call, Result result) { - if ("startImageRequests".equals(call.method)) { - if (call.arguments instanceof List) { - List arguments = (List) call.arguments; - List results = PowerImageRequestManager.getInstance() - .configRequestsWithArguments(arguments); - result.success(results); - PowerImageRequestManager.getInstance().startLoadingWithArguments(arguments); - } else { - throw new IllegalArgumentException("startImageRequests require List arguments"); - } - } else if ("releaseImageRequests".equals(call.method)) { - if (call.arguments instanceof List) { - List arguments = (List) call.arguments; - List results = PowerImageRequestManager.getInstance().releaseRequestsWithArguments(arguments); - result.success(results); - } else { - throw new IllegalArgumentException("stopImageRequests require List arguments"); - } - } else { - result.notImplemented(); - } - } - - public static class PowerImageEventSink implements EventChannel.StreamHandler { - - private EventChannel.EventSink eventSink; - - private PowerImageEventSink() { - } - - private static class Holder { - private final static PowerImageEventSink instance = new PowerImageEventSink(); - } - - public static PowerImageEventSink getInstance() { - return PowerImageEventSink.Holder.instance; - } - - @Override - public void onListen(Object arguments, EventChannel.EventSink events) { - eventSink = events; + if (engineContext != null) { + engineContext.onDetached(); + engineContext = null; } - - @Override - public void onCancel(Object arguments) { - eventSink = null; - } - - public void sendImageStateEvent(Map event, boolean success) { - if (eventSink == null || event == null) { - return; - } - - event.put("eventName", "onReceiveImageEvent"); - event.put("success", success); - eventSink.success(event); - } - } } diff --git a/android/src/main/java/com/taobao/power_image/dispatcher/PowerImageDispatcher.java b/android/src/main/java/com/taobao/power_image/dispatcher/PowerImageDispatcher.java index 50401d4..e7f5fdb 100644 --- a/android/src/main/java/com/taobao/power_image/dispatcher/PowerImageDispatcher.java +++ b/android/src/main/java/com/taobao/power_image/dispatcher/PowerImageDispatcher.java @@ -14,6 +14,7 @@ public class PowerImageDispatcher { private static volatile PowerImageDispatcher sInstance; + private boolean isPrepared = false; private Handler workHandler; private Handler mainHandler; private Looper workLooper; @@ -30,6 +31,10 @@ public static PowerImageDispatcher getInstance() { } public void prepare() { + if (isPrepared) { + return; + } + isPrepared = true; mainHandler = new Handler(Looper.getMainLooper()); Thread workThread = new Thread(new Runnable() { @Override diff --git a/android/src/main/java/com/taobao/power_image/request/PowerImageBaseRequest.java b/android/src/main/java/com/taobao/power_image/request/PowerImageBaseRequest.java index 51018bd..277f4f1 100644 --- a/android/src/main/java/com/taobao/power_image/request/PowerImageBaseRequest.java +++ b/android/src/main/java/com/taobao/power_image/request/PowerImageBaseRequest.java @@ -1,8 +1,6 @@ package com.taobao.power_image.request; -import android.graphics.Bitmap; - -import com.taobao.power_image.PowerImagePlugin; +import com.taobao.power_image.PowerImageEngineContext; import com.taobao.power_image.dispatcher.PowerImageDispatcher; import com.taobao.power_image.loader.FlutterMultiFrameImage; import com.taobao.power_image.loader.PowerImageLoader; @@ -26,12 +24,14 @@ public abstract class PowerImageBaseRequest { public static final String RENDER_TYPE_EXTERNAL = "external"; public static final String RENDER_TYPE_TEXTURE = "texture"; + private final PowerImageEngineContext engineContext; private PowerImageRequestConfig imageRequestConfig; String requestId; protected String imageTaskState; protected PowerImageResult realResult; - public PowerImageBaseRequest(Map arguments) { + public PowerImageBaseRequest(PowerImageEngineContext context, Map arguments) { + engineContext = context; requestId = (String) arguments.get("uniqueKey"); imageRequestConfig = PowerImageRequestConfig.requestConfigWithArguments(arguments); } @@ -68,7 +68,7 @@ public void onResult(PowerImageResult result) { ); } - void onLoadResult(PowerImageResult result){ + void onLoadResult(PowerImageResult result) { this.realResult = result; } @@ -77,8 +77,7 @@ public void onLoadSuccess() { @Override public void run() { PowerImageBaseRequest.this.imageTaskState = REQUEST_STATE_LOAD_SUCCEED; - PowerImagePlugin.PowerImageEventSink.getInstance() - .sendImageStateEvent(PowerImageBaseRequest.this.encode(), true); + engineContext.sendImageStateEvent(PowerImageBaseRequest.this.encode(), true); } }); } @@ -90,8 +89,7 @@ public void run() { PowerImageBaseRequest.this.imageTaskState = REQUEST_STATE_LOAD_FAILED; Map event = PowerImageBaseRequest.this.encode(); event.put("errMsg", errMsg != null ? errMsg : "failed!"); - PowerImagePlugin.PowerImageEventSink.getInstance() - .sendImageStateEvent(event, false); + engineContext.sendImageStateEvent(event, false); } }); } @@ -104,7 +102,7 @@ public Map encode() { Map encodedTask = new HashMap<>(); encodedTask.put("uniqueKey", requestId); encodedTask.put("state", imageTaskState); - if(realResult != null && realResult.success && realResult.image instanceof FlutterMultiFrameImage){ + if (realResult != null && realResult.success && realResult.image instanceof FlutterMultiFrameImage) { encodedTask.put("_multiFrame", true); } return encodedTask; diff --git a/android/src/main/java/com/taobao/power_image/request/PowerImageExternalRequest.java b/android/src/main/java/com/taobao/power_image/request/PowerImageExternalRequest.java index fe712a6..9374fea 100644 --- a/android/src/main/java/com/taobao/power_image/request/PowerImageExternalRequest.java +++ b/android/src/main/java/com/taobao/power_image/request/PowerImageExternalRequest.java @@ -5,6 +5,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; +import com.taobao.power_image.PowerImageEngineContext; import com.taobao.power_image.loader.FlutterMultiFrameImage; import com.taobao.power_image.loader.PowerImageResult; @@ -28,8 +29,8 @@ public class PowerImageExternalRequest extends PowerImageBaseRequest { private long handle; private int length; - public PowerImageExternalRequest(Map arguments) { - super(arguments); + public PowerImageExternalRequest(PowerImageEngineContext context, Map arguments) { + super(context, arguments); } @Override diff --git a/android/src/main/java/com/taobao/power_image/request/PowerImageRequestManager.java b/android/src/main/java/com/taobao/power_image/request/PowerImageRequestManager.java index 2f3607d..ed7c717 100644 --- a/android/src/main/java/com/taobao/power_image/request/PowerImageRequestManager.java +++ b/android/src/main/java/com/taobao/power_image/request/PowerImageRequestManager.java @@ -3,6 +3,8 @@ import static com.taobao.power_image.request.PowerImageBaseRequest.RENDER_TYPE_EXTERNAL; import static com.taobao.power_image.request.PowerImageBaseRequest.RENDER_TYPE_TEXTURE; +import com.taobao.power_image.PowerImageEngineContext; + import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; @@ -16,23 +18,18 @@ */ public class PowerImageRequestManager { + private final PowerImageEngineContext engineContext; + private Map requests; private WeakReference textureRegistryWrf; - private PowerImageRequestManager() { + public PowerImageRequestManager(PowerImageEngineContext context) { + engineContext = context; requests = new HashMap<>(); } - private static class Holder { - private final static PowerImageRequestManager instance = new PowerImageRequestManager(); - } - - public static PowerImageRequestManager getInstance() { - return Holder.instance; - } - public void configWithTextureRegistry(TextureRegistry textureRegistry) { - textureRegistryWrf = new WeakReference<>(textureRegistry); + this.textureRegistryWrf = new WeakReference<>(textureRegistry); } public List> configRequestsWithArguments(List> list) { @@ -45,9 +42,9 @@ public List> configRequestsWithArguments(List arguments, TextureRegistry textureRegistry) { - super(arguments); + public PowerImageTextureRequest(PowerImageEngineContext context, Map arguments, TextureRegistry textureRegistry) { + super(context, arguments); textureRegistryWrf = new WeakReference<>(textureRegistry); stopped = false; }