Skip to content

Commit

Permalink
Allow horizontal scroll view also retry side-effects when content vie…
Browse files Browse the repository at this point in the history
…w is not mounted

Summary:
This diff fixed a NPE in horizontal scroll view when calling scrollToEnd API in side effect.

The problem here is we may trigger side-effects before the required view got mounted for performance reasons. We've been fixing this with retry logic on those side-effects and we've already done this in vertical scroll view. This is to fix on the horizontal scroll as well.

Changelog:
[Android][Fixed] - Fixed HorizontalScrollView API scrollToEnd causing NPE in side-effects.

Reviewed By: lunaleaps, JoshuaGross

Differential Revision: D37571847

fbshipit-source-id: 0a4dc38381008350fd09908aa3ebb64e3e65a424
  • Loading branch information
ryancat authored and facebook-github-bot committed Jul 6, 2022
1 parent ec3c8f4 commit e5ba6ab
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
package com.facebook.react.views.scroll;

import android.graphics.Color;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.RetryableMountingLayerException;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.PointerEvents;
Expand Down Expand Up @@ -208,8 +210,15 @@ public void scrollTo(
public void scrollToEnd(
ReactHorizontalScrollView scrollView,
ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
// ScrollView always has one child - the scrollable area
int right = scrollView.getChildAt(0).getWidth() + scrollView.getPaddingRight();
// ScrollView always has one child - the scrollable area. However, it's possible today that we
// execute this method as view command before the child view is mounted. Here we will retry the
// view commands as a workaround.
@Nullable View child = scrollView.getChildAt(0);
if (child == null) {
throw new RetryableMountingLayerException(
"scrollToEnd called on HorizontalScrollView without child");
}
int right = child.getWidth() + scrollView.getPaddingRight();
if (data.mAnimated) {
scrollView.reactSmoothScrollTo(right, scrollView.getScrollY());
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ public void setOverflow(ReactScrollView view, @Nullable String overflow) {
@Override
public void scrollToEnd(
ReactScrollView scrollView, ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
// ScrollView always has one child - the scrollable area. However, it's possible today that we
// execute this method as view command before the child view is mounted. Here we will retry the
// view commands as a workaround.
View child = scrollView.getChildAt(0);
if (child == null) {
throw new RetryableMountingLayerException("scrollToEnd called on ScrollView without child");
Expand Down

0 comments on commit e5ba6ab

Please sign in to comment.