mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
f379b1e583
Summary: This replaces the internal core implementation of `setState` with the new `updateStateWithAutorepeat` which is now the only option. In short, `updateStateWithAutorepeat` works as `setState` with the following features: * The state update might be performed several times until it succeeds. * The callback is being called on every retry with actual previous data provided (can be different on every call). * In case of a static value is provided (simple case, not lambda, the only case on Android for now), the same *new*/provided value will be used for all state updates. In this case, the state update cannot fail. * If a callback is provided, the update operation can be canceled via returning `nullptr` from the callback. This diff removes all mentions of the previous state update approach from the core; some other leftovers will be removed separatly. Changelog: [Internal] Fabric-specific internal change. Reviewed By: sammy-SC Differential Revision: D25695600 fbshipit-source-id: 14b3d4bad7ee69e024a9b0b9fc018f7d58bf060c
95 lines
3.1 KiB
Java
95 lines
3.1 KiB
Java
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
package com.facebook.react.uimanager;
|
|
|
|
import androidx.annotation.Nullable;
|
|
import com.facebook.common.logging.FLog;
|
|
import com.facebook.react.bridge.ReadableMap;
|
|
import com.facebook.react.bridge.WritableMap;
|
|
|
|
/**
|
|
* This is a helper base class for ViewGroups that use Fabric State.
|
|
*
|
|
* <p>Reason to use this: UpdateState calls from the View layer to the Fabric core can fail, and
|
|
* optionally Fabric will call a "failure callback" if that happens. This class abstracts that and
|
|
* makes it easier ensure that State in Fabric is always up-to-date.
|
|
*
|
|
* <p>1. Whenever ViewManager.updateState is called, call View.setStateWrapper. 2. Instead of
|
|
* calling StateWrapper.updateState directly, call View.setState and it will automatically keep
|
|
* retrying the UpdateState call until it succeeds; or you call setState again; or the View layer is
|
|
* updated with a newer StateWrapper.
|
|
*/
|
|
public class FabricViewStateManager {
|
|
private static final String TAG = "FabricViewStateManager";
|
|
|
|
public interface HasFabricViewStateManager {
|
|
FabricViewStateManager getFabricViewStateManager();
|
|
}
|
|
|
|
public interface StateUpdateCallback {
|
|
WritableMap getStateUpdate();
|
|
}
|
|
|
|
@Nullable private StateWrapper mStateWrapper = null;
|
|
|
|
public void setStateWrapper(StateWrapper stateWrapper) {
|
|
mStateWrapper = stateWrapper;
|
|
}
|
|
|
|
public boolean hasStateWrapper() {
|
|
return mStateWrapper != null;
|
|
}
|
|
|
|
private void setState(
|
|
@Nullable final StateWrapper stateWrapper,
|
|
final StateUpdateCallback stateUpdateCallback,
|
|
final int numTries) {
|
|
// The StateWrapper will change, breaking the async loop, whenever the UpdateState MountItem
|
|
// is executed.
|
|
// The caller is responsible for detecting if data is up-to-date, and doing nothing, or
|
|
// detecting if state is stale and calling setState again.
|
|
if (stateWrapper == null) {
|
|
FLog.e(TAG, "setState called without a StateWrapper");
|
|
return;
|
|
}
|
|
if (stateWrapper != mStateWrapper) {
|
|
return;
|
|
}
|
|
// We bail out after an arbitrary number of tries. In practice this should never go higher
|
|
// than 2 or 3, but there's nothing guaranteeing that.
|
|
if (numTries > 60) {
|
|
return;
|
|
}
|
|
|
|
Runnable failureRunnable =
|
|
new Runnable() {
|
|
@Override
|
|
// Run on the UI thread
|
|
public void run() {
|
|
FLog.e(TAG, "UpdateState failed - retrying! " + numTries);
|
|
setState(stateWrapper, stateUpdateCallback, numTries + 1);
|
|
}
|
|
};
|
|
@Nullable WritableMap stateUpdate = stateUpdateCallback.getStateUpdate();
|
|
if (stateUpdate == null) {
|
|
return;
|
|
}
|
|
|
|
// TODO: State update cannot fail; remove `failureRunnable` and custom retrying logic.
|
|
stateWrapper.updateState(stateUpdate);
|
|
}
|
|
|
|
public void setState(final StateUpdateCallback stateUpdateCallback) {
|
|
setState(mStateWrapper, stateUpdateCallback, 0);
|
|
}
|
|
|
|
public @Nullable ReadableMap getState() {
|
|
return mStateWrapper != null ? mStateWrapper.getState() : null;
|
|
}
|
|
}
|