From 3bdffe7ce9cedb88053e093ccbf3ca82a939b3fc Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Sat, 28 Oct 2023 22:38:43 +0200 Subject: [PATCH] View: prevent redundant measuring for performance reasons No need to remeasure or relayout when nothing has changed --- src/api-impl-jni/util.c | 1 + src/api-impl-jni/util.h | 1 + .../views/android_view_ViewGroup.c | 14 +--------- src/api-impl/android/view/View.java | 26 ++++++++++++++++++- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/api-impl-jni/util.c b/src/api-impl-jni/util.c index 4f23d1dd..c674e716 100644 --- a/src/api-impl-jni/util.c +++ b/src/api-impl-jni/util.c @@ -117,6 +117,7 @@ void set_up_handle_cache(JNIEnv *env) handle_cache.view.getScrollY = _METHOD(handle_cache.view.class, "getScrollY", "()I"); handle_cache.view.performClick = _METHOD(handle_cache.view.class, "performClick", "()Z"); handle_cache.view.onTouchEvent = _METHOD(handle_cache.view.class, "onTouchEvent", "(Landroid/view/MotionEvent;)Z"); + handle_cache.view.layoutInternal = _METHOD(handle_cache.view.class, "layoutInternal", "(II)V"); handle_cache.asset_manager.class = _REF((*env)->FindClass(env, "android/content/res/AssetManager")); handle_cache.asset_manager.extractFromAPK = _STATIC_METHOD(handle_cache.asset_manager.class, "extractFromAPK", "(Ljava/lang/String;Ljava/lang/String;)V"); diff --git a/src/api-impl-jni/util.h b/src/api-impl-jni/util.h index 180b9e24..8d7b83ea 100644 --- a/src/api-impl-jni/util.h +++ b/src/api-impl-jni/util.h @@ -71,6 +71,7 @@ struct handle_cache { jmethodID getScrollY; jmethodID performClick; jmethodID onTouchEvent; + jmethodID layoutInternal; } view; struct { jclass class; diff --git a/src/api-impl-jni/views/android_view_ViewGroup.c b/src/api-impl-jni/views/android_view_ViewGroup.c index 10117bfe..29f0929a 100644 --- a/src/api-impl-jni/views/android_view_ViewGroup.c +++ b/src/api-impl-jni/views/android_view_ViewGroup.c @@ -8,8 +8,6 @@ #include "../generated_headers/android_view_ViewGroup.h" #include "../generated_headers/android_view_View.h" -#define MEASURE_SPEC_EXACTLY (1 << 30) - #define SOURCE_CLASS_POINTER 0x2 struct _AndroidLayout { @@ -41,17 +39,7 @@ static void android_layout_allocate(GtkLayoutManager *layout_manager, GtkWidget AndroidLayout *layout = ATL_ANDROID_LAYOUT(layout_manager); JNIEnv *env = get_jni_env(); - (*env)->CallVoidMethod(env, layout->view, handle_cache.view.onMeasure, MEASURE_SPEC_EXACTLY | width, MEASURE_SPEC_EXACTLY | height); - if((*env)->ExceptionCheck(env)) - (*env)->ExceptionDescribe(env); - - (*env)->CallVoidMethod(env, layout->view, handle_cache.view.computeScroll); - if((*env)->ExceptionCheck(env)) - (*env)->ExceptionDescribe(env); - int scroll_x = (*env)->CallIntMethod(env, layout->view, handle_cache.view.getScrollX); - int scroll_y = (*env)->CallIntMethod(env, layout->view, handle_cache.view.getScrollY); - - (*env)->CallVoidMethod(env, layout->view, handle_cache.view.onLayout, TRUE, scroll_x, scroll_y, width, height); + (*env)->CallVoidMethod(env, layout->view, handle_cache.view.layoutInternal, width, height); if((*env)->ExceptionCheck(env)) (*env)->ExceptionDescribe(env); } diff --git a/src/api-impl/android/view/View.java b/src/api-impl/android/view/View.java index 98847064..c8eea335 100644 --- a/src/api-impl/android/view/View.java +++ b/src/api-impl/android/view/View.java @@ -806,6 +806,12 @@ public class View extends Object { public static HashMap view_by_id = new HashMap(); + private int oldWidthMeasureSpec; + private int oldHeightMeasureSpec; + private boolean layoutRequested; + private int oldWidth; + private int oldHeight; + public View() { this(Context.this_application); } // FIXME @@ -1081,7 +1087,12 @@ public class View extends Object { public void setOnHoverListener(OnHoverListener listener) {} public final void measure(int widthMeasureSpec, int heightMeasureSpec) { - onMeasure(widthMeasureSpec, heightMeasureSpec); + if (layoutRequested || widthMeasureSpec != oldWidthMeasureSpec || heightMeasureSpec != oldHeightMeasureSpec) { + oldWidthMeasureSpec = widthMeasureSpec; + oldHeightMeasureSpec = heightMeasureSpec; + onMeasure(widthMeasureSpec, heightMeasureSpec); + layoutRequested = false; + } } public final int getMeasuredState() { @@ -1156,6 +1167,18 @@ public class View extends Object { native_layout(widget, l, t, r, b); } + /** Helper function to be called from GTKs LayoutManager via JNI */ + private void layoutInternal(int width, int height) { + // if the layout is triggered from a native widget, we might not have measured yet + if (width != getMeasuredWidth() || height != getMeasuredHeight()) { + measure(width | MeasureSpec.EXACTLY, height | MeasureSpec.EXACTLY); + } + boolean changed = oldWidth != width || oldHeight != height; + onLayout(changed, 0, 0, width, height); + oldWidth = width; + oldHeight = height; + } + public int getLeft() { return left; } @@ -1190,6 +1213,7 @@ public class View extends Object { public boolean removeCallbacks(Runnable action) {return false;} public void requestLayout() { + layoutRequested = true; native_requestLayout(widget); };