Comments (6)
I think this is the most interesting issue I've ever discovered in my life π
So basically crash happens in this code:
public void afterTextChanged(Editable s) {
if (!ReactEditText.this.mIsSettingTextFromJS && ReactEditText.this.mListeners != null) {
Iterator var2 = ReactEditText.this.mListeners.iterator();
while(var2.hasNext()) {
TextWatcher listener = (TextWatcher)var2.next();
listener.afterTextChanged(s);
}
}
}
On every afterTextChanged
input-mask-android removes the listener and adds it back.
Now let's consider oversimplified example (you can run this code in https://www.jdoodle.com/online-java-compiler):
import java.util.ArrayList;
import java.util.Iterator;
public class MyClass {
public static void main(String args[]) {
ArrayList<Integer> mListeners = new ArrayList<>();
mListeners.add(0);
mListeners.add(1);
// mListeners.add(2);
Iterator<Integer> iterator = mListeners.iterator();
while (iterator.hasNext()) {
Integer listener = iterator.next();
// Check if the listener is equal to 1
// 1 is OnlyChangeIfRequiredMaskedTextChangedListener and we simulate the behavior of this class
if (listener == 1) {
int i = mListeners.indexOf(listener);
if (i >= 0) {
mListeners.remove(i);
}
// Add the removed element at the end
mListeners.add(listener);
}
}
// Print the modified list
System.out.println(mListeners);
}
}
This code will be executed without any issues, and will produce expected [0, 1]
output.
But if we uncomment mListeners.add(2);
- we'll get our exception:
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1049)
at MyClass.main(MyClass.java:14)
These 3 array elements are real elements in RN app:
- 0 is
EmojiTextWatcher
(seems like it's added by OS); - 1 is
OnlyChangeIfRequiredMaskedTextChangedListener
(added byreact-native-text-input-mask
); - 2 is a listener that I'm attaching in RNKC.
So here we get a situation, where react-native
code works for 2 listeners, but doesn't work for 3. To make this code working again with 3 listeners we just can change the order - if the order is [2, 0, 1]
or [0, 2, 1]
it will work, because removal/insertion operation will be the last one and java will not throw an exception.
Or before iterating we can create a copy of array and iterate over this copy (but we'll have to modify react-native source code). For example Android code iterates over mListeners
as:
if (mListeners != null) {
final ArrayList<TextWatcher> list = mListeners;
final int count = list.size();
for (int i = 0; i < count; i++) {
list.get(i).afterTextChanged(text);
}
}
Oversimplified version with new iteration approach that works may look like this:
import java.util.ArrayList;
import java.util.Iterator;
public class MyClass {
public static void main(String args[]) {
ArrayList<Integer> mListeners = new ArrayList<>();
mListeners.add(0);
mListeners.add(1);
mListeners.add(2);
final ArrayList<Integer> list = mListeners;
final int count = list.size();
for (int i = 0; i < count; i++) {
Integer listener = list.get(i);
if (listener == 1) {
mListeners.remove(i);
// Add the removed element at the end
mListeners.add(listener);
}
}
// Print the modified list
System.out.println(mListeners);
}
}
So now we have two options on how to fix this issue:
- insert RNKC listener before MaskedTextChangedListener;
- change how react-native iterates over array.
Both solutions are not good enough because:
- we don't have an access to
private
variable ofReactEditText
and can not insert to the beginning (actually we can use reflection and I already experimented with it - it fixes the problem, but everyone knows that reflection should be used as a last resort); - that means that only new version of RN (let's say 0.74) will support RNKC 1.10. And such compatibility range is not good enough for general purpose library.
I will think about other solutions too, but if you @devoren have any ideas - please, share them π
from react-native-keyboard-controller.
Just a quick update - the issue is reproducible on my end in 100% cases.
Basically this exception happens when you iterate over and collection gets modified, so this code will trigger this exception:
List<String> myList = new ArrayList<>();
Iterator<String> iterator = myList.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
myList.add("newElement"); // This will throw ConcurrentModificationException
}
There is some issues because in different calls I see different amount of listeners.
3 listeners | 2 listeners |
---|---|
I've tried naive things like adding listener after 100ms or 1s, but it will produce crash when you type a symbol π€·ββοΈ
I'll search for new solutions π
from react-native-keyboard-controller.
I think I will go with reflection approach (it should work pretty reliably) and most likely will submit a PR to react-native repo :)
I think it'll be fixed in 1.10.2 π€
from react-native-keyboard-controller.
Just've tried new version. The issue was fixed for me. Huge thx for your work @kirillzyusko
from react-native-keyboard-controller.
Nice catch @devoren
I'll try to have a look today on it π
from react-native-keyboard-controller.
To be honest, I'm not good at the native side. But I understand the problem, so is it because of react-native limitations? Then I don't want to take up too much of your timeπ . For now i will use version 1.9.5 without any problems
from react-native-keyboard-controller.
Related Issues (20)
- KeyboardAccesoryView Input navigation arrows HOT 10
- useReanimatedKeyboardAnimation doesn't look smooth like the Reanimated UseAnimatedKeyboard hook in IOS when closing the keyboard HOT 7
- Incorrect first frame when using `KeyboardAvoidingView`/`KeyboardStickyView+offset` and keyboard gets resized
- iOS memory leakοΌ1.10.0οΌ HOT 6
- Jest mock doesn't include newly exported KeyboardAwareScrollView HOT 2
- Expose style prop of chidren of KeyboardAwareScrollView HOT 2
- [IOS] Incorrect behavior of hooks and components when focusing on an input with secureTextEntry enabled. HOT 14
- [KASV] white space in the end of ScrollView on keyboard hide
- `useFocusedInputHandler` and `onChangeText` handler ignores an input from `react-native-text-input-mask` on iOS
- Incorrect KeyboardAvoidingView calculations on Android HOT 5
- Slow back scroll on `KeyboardAwareScollView` on some Android devices HOT 1
- Check for `ScrollView` ancestor in `KeyboardAwareScrollView`
- `onScroll` on `KeyboardAwareScrollView` is not fired
- KeyboardAwareScrollView not working on first load of the app after fresh install in production iOS builds HOT 1
- Bottom Sheet component compatibility/custom native wrapper(long-term feature) HOT 2
- KeyboardAwareScrollView scrolling too much when pasting a lot of content in multiline inputibox HOT 8
- KeyboardAwareScrollView has no ref prop HOT 3
- [ios] build error 'react_native_keyboard_controller-Swift.h' file not found HOT 8
- modal looks weird after use TextInput on KeyboardAwareScrollView HOT 13
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-native-keyboard-controller.