-
-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The library conflicts with the react-native-text-input-mask since version 1.10.0. #324
Comments
Nice catch @devoren I'll try to have a look today on it 👀 |
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 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 But if we uncomment 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:
So here we get a situation, where 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 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:
Both solutions are not good enough because:
I will think about other solutions too, but if you @devoren have any ideas - please, share them 😊 |
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 |
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 🤞 |
## 📜 Description Fixed `ConcurrentModificationException` when user touches TextInput from `react-native-text-input-mask`. ## 💡 Motivation and Context I described problem in #324 (comment) Here I'd like to focus on a solution. The most obvious one is to match old behavior and attach `TextWatcher` from `react-native-text-input-mask` as a last one. Unfortunately we don't have an API to control a position of watcher, so I had to use reflection. I think I wrote reflection quite carefully. I'm checking, that `mListeners` field is present, I'm checking that it's `ArrayList`, I'm verifying that all elements belongs to `TextWatcher` and only after that I'm adding RNKC listener as first element in an array. Closes #324 ## 📢 Changelog ### JS - added example with `react-native-text-input-mask`; ### Android - use reflection to set RNKC `TextWatcher` into first position of array; ## 🤔 How Has This Been Tested? Tested manually on Pixel 3a (emulator, Android 13). ## 📸 Screenshots (if appropriate): <img width="245" alt="Screenshot 2024-01-12 at 22 37 41" src="https://github.com/kirillzyusko/react-native-keyboard-controller/assets/22820318/5783a44b-82f6-428a-82a6-99a4c4f8816e"> ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
Just've tried new version. The issue was fixed for me. Huge thx for your work @kirillzyusko |
Describe the bug
Hello! I know that this problem is not serious and in many cases does not occur. Sorry for the increase in issues, but I hope someone can help 🙏 . The library conflicts with the react-native-text-input-mask since version 1.10.0, so the keyboard does not open the first time. I think this is related to the FocusedInputTextChangedEvent. The latest version that works without errors is 1.9.5 without FocusedInputTextChangedEvent.
Code snippet
Repo for reproducing
You can change the RNKC version and see the difference.
https://github.com/devoren/TestRNKC732
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Keyboard opens without any problem in first press
Screenshots
In the video i press input 2 times
mask.mp4
Smartphone (please complete the following information):
Additional context
The problem only occurs if I add a mask prop to TextInputMask.
The text was updated successfully, but these errors were encountered: