diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/NativeRenderer.java b/renderer/native/android/src/main/java/com/tencent/renderer/NativeRenderer.java index 3bd489681f0..ea487a53522 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/NativeRenderer.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/NativeRenderer.java @@ -395,8 +395,9 @@ public void dispatchEvent(int rootId, int nodeId, @NonNull String eventName, if (lowerCaseEventName.startsWith(EVENT_PREFIX)) { lowerCaseEventName = lowerCaseEventName.substring(EVENT_PREFIX.length()); } - if (eventType != EventType.EVENT_TYPE_GESTURE && !mRenderManager.checkRegisteredEvent( - rootId, nodeId, lowerCaseEventName)) { + if (eventType != EventType.EVENT_TYPE_GESTURE + && !mRenderManager.checkRegisteredEvent(rootId, nodeId, lowerCaseEventName) + && !mVirtualNodeManager.checkRegisteredEvent(rootId, nodeId, lowerCaseEventName)) { return; } LogUtils.d(TAG, "dispatchEvent: id " + nodeId + ", eventName " + eventName diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponent.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponent.java index 11926bf7dfa..bce4e74f39c 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponent.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/image/ImageComponent.java @@ -186,9 +186,10 @@ public void setTintColorBlendMode(int tintColorBlendMode) { } protected void onFetchImageStart() { - if (mHostRef.get() != null) { + final RenderNode host = mHostRef.get(); + if (host != null) { // send onLoadStart event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_START, null); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_START, null); } } @@ -217,17 +218,28 @@ private void onFetchImageSuccess(@NonNull String uri, ImageSourceType sourceType mImageHolder = imageHolder; mImageFetchState = ImageFetchState.LOADED; setImageData(imageHolder); - if (mHostRef.get() != null && !loadFromCache) { + final RenderNode host = mHostRef.get(); + if (host != null) { + final int width = imageHolder.getImageWidth(); + final int height = imageHolder.getImageHeight(); // send onLoad event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_ON_LOAD, null); - HashMap params = new HashMap<>(); - params.put("success", 1); - HashMap imageSize = new HashMap<>(); - imageSize.put("width", imageHolder.getImageWidth()); - imageSize.put("height", imageHolder.getImageHeight()); - params.put("image", imageSize); + HashMap onLoad = new HashMap<>(); + onLoad.put("width", width); + onLoad.put("height", height); + onLoad.put("url", uri); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_ON_LOAD, onLoad); // send onLoadEnd event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_END, params); + HashMap onLoadEnd = new HashMap<>(); + onLoadEnd.put("success", 1); + onLoadEnd.put("width", width); + onLoadEnd.put("height", height); + onLoadEnd.put("url", uri); + @Deprecated + HashMap imageSize = new HashMap<>(); + imageSize.put("width", width); + imageSize.put("height", height); + onLoadEnd.put("image", imageSize); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_END, onLoadEnd); } } else if (sourceType == ImageSourceType.DEFAULT) { if (!uri.equals(mDefaultUri)) { @@ -247,35 +259,45 @@ private void onFetchImageSuccess(@NonNull String uri, ImageSourceType sourceType postInvalidateDelayed(0); } - private void onFetchImageFail() { + private void onFetchImageFail(String url, Throwable throwable) { mImageFetchState = ImageFetchState.UNLOAD; - if (mHostRef.get() == null) { + final RenderNode host = mHostRef.get(); + if (host == null) { return; } // send onError event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_ERROR, null); - HashMap params = new HashMap<>(); - params.put("success", 0); + HashMap onError = new HashMap<>(); + onError.put("error", String.valueOf(throwable)); + onError.put("errorCode", -1); + onError.put("errorURL", url); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_ERROR, onError); // send onLoadEnd event - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_END, params); + HashMap onLoadEnd = new HashMap<>(); + onLoadEnd.put("success", 0); + onLoadEnd.put("error", String.valueOf(throwable)); + onLoadEnd.put("errorCode", -1); + onLoadEnd.put("url", url); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_END, onLoadEnd); } protected void onFetchImageProgress(float total, float loaded) { - if (mHostRef.get() == null) { + final RenderNode host = mHostRef.get(); + if (host == null) { return; } HashMap params = new HashMap<>(); params.put("loaded", loaded); params.put("total", total); - EventUtils.sendComponentEvent(mHostRef.get(), EVENT_IMAGE_LOAD_PROGRESS, params); + EventUtils.sendComponentEvent(host, EVENT_IMAGE_LOAD_PROGRESS, params); } private void doFetchImage(final String uri, final ImageSourceType sourceType) { - int width = (mHostRef.get() != null) ? mHostRef.get().getWidth() : 0; - int height = (mHostRef.get() != null) ? mHostRef.get().getHeight() : 0; + final RenderNode host = mHostRef.get(); + int width = (host != null) ? host.getWidth() : 0; + int height = (host != null) ? host.getHeight() : 0; Map params = new HashMap<>(); - if (mHostRef.get() != null) { - params.put("props", mHostRef.get().getProps()); + if (host != null) { + params.put("props", host.getProps()); } assert mImageLoader != null; mImageLoader.fetchImageAsync(uri, new ImageRequestListener() { @@ -298,7 +320,7 @@ public void onRequestSuccess(ImageDataSupplier imageData) { @Override public void onRequestFail(Throwable throwable) { if (sourceType == ImageSourceType.SRC) { - onFetchImageFail(); + onFetchImageFail(uri, throwable); } else { mDefaultImageFetchState = ImageFetchState.UNLOAD; } @@ -311,17 +333,17 @@ private void fetchImageWithUrl(String uri, ImageSourceType sourceType) { return; } LogUtils.d(TAG, "fetchImageWithUrl: host id " + getHostId() + ", uri " + uri); - ImageDataSupplier imageData = mImageLoader.getImageFromCache(uri); - if (imageData != null && imageData.checkImageData()) { - onFetchImageSuccess(uri, sourceType, imageData, true); - return; - } if (sourceType == ImageSourceType.SRC) { mImageFetchState = ImageFetchState.LOADING; onFetchImageStart(); } else { mDefaultImageFetchState = ImageFetchState.LOADING; } + ImageDataSupplier imageData = mImageLoader.getImageFromCache(uri); + if (imageData != null && imageData.checkImageData()) { + onFetchImageSuccess(uri, sourceType, imageData, true); + return; + } if (UrlUtils.isWebUrl(uri)) { uri = uri.trim().replaceAll(" ", "%20"); } diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TextImageSpan.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TextImageSpan.java index eece831774e..680ad01550c 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TextImageSpan.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TextImageSpan.java @@ -16,7 +16,10 @@ package com.tencent.renderer.component.text; +import static com.tencent.renderer.utils.EventUtils.EVENT_IMAGE_LOAD_END; import static com.tencent.renderer.utils.EventUtils.EVENT_IMAGE_LOAD_ERROR; +import static com.tencent.renderer.utils.EventUtils.EVENT_IMAGE_LOAD_PROGRESS; +import static com.tencent.renderer.utils.EventUtils.EVENT_IMAGE_LOAD_START; import static com.tencent.renderer.utils.EventUtils.EVENT_IMAGE_ON_LOAD; import android.annotation.SuppressLint; @@ -50,9 +53,9 @@ import com.tencent.renderer.node.ImageVirtualNode; import com.tencent.renderer.node.TextVirtualNode; import com.tencent.renderer.utils.EventUtils.EventType; -import com.tencent.vfs.UrlUtils; import java.lang.ref.WeakReference; import java.lang.reflect.Field; +import java.util.HashMap; public class TextImageSpan extends ImageSpan { @@ -88,7 +91,7 @@ public class TextImageSpan extends ImageSpan { private Movie mGifMovie; @Deprecated @Nullable - private LegacyIAlignConfig mAlignConfig; + private final LegacyIAlignConfig mAlignConfig; @Nullable private Paint mGifPaint; private float mHeightRate = 0; @@ -161,11 +164,12 @@ private int legacyGetSize(@NonNull Paint paint, CharSequence text, int start, in return super.getSize(paint, text, start, end, fm); } Drawable drawable = getDrawable(); + assert mAlignConfig != null; return mAlignConfig.getSize(paint, text, start, end, fm, drawable); } - public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, - int bottom, Paint paint) { + public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, + int bottom, @NonNull Paint paint) { if (mUseLegacy) { legacyDraw(canvas, text, start, end, x, top, y, bottom, paint); return; @@ -225,6 +229,7 @@ private void legacyDraw(Canvas canvas, CharSequence text, int start, int end, fl legacyDrawGIF(canvas, x + mLeft, transY + mTop, width, height); } else { Drawable drawable = getDrawable(); + assert mAlignConfig != null; mAlignConfig.draw(canvas, text, start, end, x, top, y, bottom, paint, drawable, mBackgroundPaint); } } @@ -233,6 +238,7 @@ private void legacyDraw(Canvas canvas, CharSequence text, int start, int end, fl @SuppressWarnings("unused") public void setDesiredSize(int width, int height) { if (mUseLegacy) { + assert mAlignConfig != null; mAlignConfig.setDesiredSize(width, height); } } @@ -241,6 +247,7 @@ public void setDesiredSize(int width, int height) { public void setActiveSizeWithRate(float heightRate) { mHeightRate = heightRate; if (mUseLegacy) { + assert mAlignConfig != null; mAlignConfig.setActiveSizeWithRate(heightRate); } } @@ -249,39 +256,40 @@ public void setActiveSizeWithRate(float heightRate) { @SuppressWarnings("unused") public void setMargin(int marginLeft, int marginRight) { if (mUseLegacy) { + assert mAlignConfig != null; mAlignConfig.setMargin(marginLeft, marginRight); } } - protected boolean shouldUseFetchImageMode(String url) { - return UrlUtils.isWebUrl(url) || UrlUtils.isFileUrl(url); - } - @MainThread private void loadImageWithUrl(@NonNull final String url) { - NativeRender nativeRender = mNativeRendererRef.get(); - ImageLoaderAdapter imageLoader = nativeRender != null ? nativeRender.getImageLoader() : null; + final NativeRender nativeRenderer = mNativeRendererRef.get(); + final ImageLoaderAdapter imageLoader = nativeRenderer != null ? nativeRenderer.getImageLoader() : null; if (mImageLoadState == STATE_LOADING || imageLoader == null) { return; } + nativeRenderer.dispatchEvent(mRootId, mId, EVENT_IMAGE_LOAD_START, null, false, false, + EventType.EVENT_TYPE_COMPONENT); mImageLoadState = STATE_LOADING; imageLoader.fetchImageAsync(url, new ImageRequestListener() { @Override public void onRequestStart(ImageDataSupplier imageData) { + handleFetchImageStart(); } @Override public void onRequestProgress(long total, long loaded) { + handleFetchImageProgress(total, loaded); } @Override public void onRequestSuccess(final ImageDataSupplier imageData) { - handleFetchImageResult(imageData); + handleFetchImageResult(url, imageData, null); } @Override public void onRequestFail(Throwable throwable) { - handleFetchImageResult(null); + handleFetchImageResult(url, null, throwable); } }, null, mWidth, mHeight); } @@ -405,23 +413,74 @@ private void legacyShouldReplaceDrawable(@NonNull ImageDataHolder imageHolder) { postInvalidateDelayed(0); } - private void handleFetchImageResult(@Nullable final ImageDataSupplier imageHolder) { - String eventName; + private void handleFetchImageStart() { + NativeRender nativeRenderer = mNativeRendererRef.get(); + if (nativeRenderer != null) { + // send onLoadStart event + nativeRenderer.dispatchEvent(mRootId, mId, EVENT_IMAGE_LOAD_START, null, false, false, + EventType.EVENT_TYPE_COMPONENT); + } + } + + private void handleFetchImageProgress(float total, float loaded) { + NativeRender nativeRenderer = mNativeRendererRef.get(); + if (nativeRenderer != null) { + // send onProgress event + HashMap onProgress = new HashMap<>(); + onProgress.put("loaded", loaded); + onProgress.put("total", total); + nativeRenderer.dispatchEvent(mRootId, mId, EVENT_IMAGE_LOAD_PROGRESS, onProgress, false, false, + EventType.EVENT_TYPE_COMPONENT); + } + } + + private void handleFetchImageResult(@NonNull final String url, @Nullable final ImageDataSupplier imageHolder, + final @Nullable Throwable throwable) { + NativeRender nativeRenderer = mNativeRendererRef.get(); if (imageHolder == null || !imageHolder.checkImageData()) { mImageLoadState = STATE_UNLOAD; - eventName = EVENT_IMAGE_LOAD_ERROR; + if (nativeRenderer != null) { + // send onError event + HashMap onError = new HashMap<>(); + onError.put("error", String.valueOf(throwable)); + onError.put("errorCode", -1); + onError.put("errorURL", url); + nativeRenderer.dispatchEvent(mRootId, mId, EVENT_IMAGE_LOAD_ERROR, onError, false, false, + EventType.EVENT_TYPE_COMPONENT); + // send onLoadEnd event + HashMap onLoadEnd = new HashMap<>(); + onLoadEnd.put("url", url); + onLoadEnd.put("success", 0); + onLoadEnd.put("error", String.valueOf(throwable)); + onLoadEnd.put("errorCode", -1); + nativeRenderer.dispatchEvent(mRootId, mId, EVENT_IMAGE_LOAD_END, onLoadEnd, false, false, + EventType.EVENT_TYPE_COMPONENT); + } } else { if (imageHolder instanceof ImageDataHolder) { shouldReplaceDrawable((ImageDataHolder) imageHolder); } mImageLoadState = STATE_LOADED; - eventName = EVENT_IMAGE_ON_LOAD; - } - NativeRender nativeRender = mNativeRendererRef.get(); - if (nativeRender != null) { - nativeRender.dispatchEvent(mRootId, mId, eventName, null, false, false, - EventType.EVENT_TYPE_COMPONENT); - } + if (nativeRenderer != null) { + int width = imageHolder.getImageWidth(); + int height = imageHolder.getImageHeight(); + // send onLoad event + HashMap onLoad = new HashMap<>(); + onLoad.put("width", width); + onLoad.put("height", height); + onLoad.put("url", url); + nativeRenderer.dispatchEvent(mRootId, mId, EVENT_IMAGE_ON_LOAD, onLoad, false, false, + EventType.EVENT_TYPE_COMPONENT); + // send onLoadEnd event + HashMap onLoadEnd = new HashMap<>(); + onLoadEnd.put("success", 1); + onLoadEnd.put("width", width); + onLoadEnd.put("height", height); + onLoadEnd.put("url", url); + nativeRenderer.dispatchEvent(mRootId, mId, EVENT_IMAGE_LOAD_END, onLoadEnd, false, false, + EventType.EVENT_TYPE_COMPONENT); + } + } } public void setTintColor(final int tintColor) { diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/node/ImageVirtualNode.java b/renderer/native/android/src/main/java/com/tencent/renderer/node/ImageVirtualNode.java index 5933f16500e..7ab62c59c21 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/node/ImageVirtualNode.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/node/ImageVirtualNode.java @@ -175,9 +175,9 @@ protected void createSpanOperation(List ops, builder.append(IMAGE_SPAN_TEXT); int end = start + IMAGE_SPAN_TEXT.length(); ops.add(new SpanOperation(start, end, mImageSpan)); - if (mGestureTypes != null && mGestureTypes.size() > 0) { + if (mEventTypes != null && mEventTypes.size() > 0) { TextGestureSpan span = new TextGestureSpan(mId); - span.addGestureTypes(mGestureTypes); + span.addGestureTypes(mEventTypes); ops.add(new SpanOperation(start, end, span)); } } diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/node/TextVirtualNode.java b/renderer/native/android/src/main/java/com/tencent/renderer/node/TextVirtualNode.java index 92952b7b0fb..eeaea5e552f 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/node/TextVirtualNode.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/node/TextVirtualNode.java @@ -438,9 +438,9 @@ protected void createSpanOperationImpl(@NonNull List ops, new TextShadowSpan(mShadowOffsetDx, mShadowOffsetDy, mShadowRadius, mShadowColor))); } - if (mGestureTypes != null && mGestureTypes.size() > 0) { + if (mEventTypes != null && mEventTypes.size() > 0) { TextGestureSpan span = new TextGestureSpan(mId); - span.addGestureTypes(mGestureTypes); + span.addGestureTypes(mEventTypes); ops.add(new SpanOperation(start, end, span)); } if (useChild) { diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/node/VirtualNode.java b/renderer/native/android/src/main/java/com/tencent/renderer/node/VirtualNode.java index b8234212653..644b0e0c2eb 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/node/VirtualNode.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/node/VirtualNode.java @@ -38,7 +38,7 @@ public abstract class VirtualNode { @Nullable protected VirtualNode mParent; @Nullable - protected List mGestureTypes; + protected List mEventTypes; public VirtualNode(int rootId, int id, int pid, int index) { mRootId = rootId; @@ -68,19 +68,23 @@ public int getAncestorId() { protected abstract void createSpanOperation(List ops, SpannableStringBuilder builder, boolean useChild); - public void addGesture(String event) { - if (mGestureTypes == null) { - mGestureTypes = new ArrayList<>(); + public void addEventType(String event) { + if (mEventTypes == null) { + mEventTypes = new ArrayList<>(); } - mGestureTypes.add(event); + mEventTypes.add(event); } - public void removeGesture(String event) { - if (mGestureTypes != null) { - mGestureTypes.remove(event); + public void removeEventType(String event) { + if (mEventTypes != null) { + mEventTypes.remove(event); } } + public boolean hasEventType(String event) { + return mEventTypes != null && mEventTypes.contains(event); + } + public boolean isDirty() { return mDirty; } diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/node/VirtualNodeManager.java b/renderer/native/android/src/main/java/com/tencent/renderer/node/VirtualNodeManager.java index 34d1a784ecb..cf754246b1f 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/node/VirtualNodeManager.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/node/VirtualNodeManager.java @@ -113,9 +113,9 @@ public boolean updateEventListener(int rootId, int nodeId, @NonNull Map endBatch(int rootId) { updateNodes.clear(); return layoutToUpdate; } + + public boolean checkRegisteredEvent(int rootId, int nodeId, String eventName) { + VirtualNode node = getVirtualNode(rootId, nodeId); + return node != null && node.hasEventType(eventName); + } }