mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-16 12:12:20 +08:00
Summary: DynamicFromMap internally uses SimplePool object to recycle dynamic prop objects. But the pool is not multi-thread safe. Currently the most used dynamic props are size props such as left, paddingVertical, marginTop and so on. These props are only accessed from the layout thread so the pool works fine. If a dynamic prop is needed in UI thread, then the two threads can access the same pool object and cause random errors. This PR make the pool object thread local to avoid synchronization. After this change there are two pool objects created in the process. Tested in official Airbnb app after updating accessibilityComponentType to be dynamic. Once this is merged, I'll send another PR to support "disabled" state in `accessibilityComponentType`. [ANDROID] [BUGFIX] [DynamicFromMap] - Fix a crash caused by dynamic props. Pull Request resolved: https://github.com/facebook/react-native/pull/17842 Differential Revision: D10374238 Pulled By: hramos fbshipit-source-id: 7ebf89c5abf06bd5fb43b205348ba4dc7e19517d
112 lines
2.8 KiB
Java
112 lines
2.8 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.bridge;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
import android.support.v4.util.Pools.SimplePool;
|
|
|
|
/**
|
|
* Implementation of Dynamic wrapping a ReadableMap.
|
|
*/
|
|
public class DynamicFromMap implements Dynamic {
|
|
private static final ThreadLocal<SimplePool<DynamicFromMap>> sPool = new ThreadLocal<SimplePool<DynamicFromMap>>() {
|
|
@Override
|
|
protected SimplePool<DynamicFromMap> initialValue() {
|
|
return new SimplePool<>(10);
|
|
}
|
|
};
|
|
|
|
private @Nullable ReadableMap mMap;
|
|
private @Nullable String mName;
|
|
|
|
// This is a pools object. Hide the constructor.
|
|
private DynamicFromMap() {}
|
|
|
|
public static DynamicFromMap create(ReadableMap map, String name) {
|
|
DynamicFromMap dynamic = sPool.get().acquire();
|
|
if (dynamic == null) {
|
|
dynamic = new DynamicFromMap();
|
|
}
|
|
dynamic.mMap = map;
|
|
dynamic.mName = name;
|
|
return dynamic;
|
|
}
|
|
|
|
@Override
|
|
public void recycle() {
|
|
mMap = null;
|
|
mName = null;
|
|
sPool.get().release(this);
|
|
}
|
|
|
|
@Override
|
|
public boolean isNull() {
|
|
if (mMap == null || mName == null) {
|
|
throw new IllegalStateException("This dynamic value has been recycled");
|
|
}
|
|
return mMap.isNull(mName);
|
|
}
|
|
|
|
@Override
|
|
public boolean asBoolean() {
|
|
if (mMap == null || mName == null) {
|
|
throw new IllegalStateException("This dynamic value has been recycled");
|
|
}
|
|
return mMap.getBoolean(mName);
|
|
}
|
|
|
|
@Override
|
|
public double asDouble() {
|
|
if (mMap == null || mName == null) {
|
|
throw new IllegalStateException("This dynamic value has been recycled");
|
|
}
|
|
return mMap.getDouble(mName);
|
|
}
|
|
|
|
@Override
|
|
public int asInt() {
|
|
if (mMap == null || mName == null) {
|
|
throw new IllegalStateException("This dynamic value has been recycled");
|
|
}
|
|
return mMap.getInt(mName);
|
|
}
|
|
|
|
@Override
|
|
public String asString() {
|
|
if (mMap == null || mName == null) {
|
|
throw new IllegalStateException("This dynamic value has been recycled");
|
|
}
|
|
return mMap.getString(mName);
|
|
}
|
|
|
|
@Override
|
|
public ReadableArray asArray() {
|
|
if (mMap == null || mName == null) {
|
|
throw new IllegalStateException("This dynamic value has been recycled");
|
|
}
|
|
return mMap.getArray(mName);
|
|
}
|
|
|
|
@Override
|
|
public ReadableMap asMap() {
|
|
if (mMap == null || mName == null) {
|
|
throw new IllegalStateException("This dynamic value has been recycled");
|
|
}
|
|
return mMap.getMap(mName);
|
|
}
|
|
|
|
@Override
|
|
public ReadableType getType() {
|
|
if (mMap == null || mName == null) {
|
|
throw new IllegalStateException("This dynamic value has been recycled");
|
|
}
|
|
return mMap.getType(mName);
|
|
}
|
|
}
|