#c# #android #xamarin.forms
#c# #Android #xamarin.forms
Вопрос:
Я использую Xamarin Forms Entry
для извлечения некоторых данных при OnTextChanged
вызове события.
Иногда он выдает неуловимое Java.Lang.ArrayIndexOutOfBoundsException
значение, что приводит к сбою приложения.
Код, который я использовал:
private void textbox_OnTextChanged(object sender, TextChangedEventArgs e)
{
TextChanged();
}
public async void TextChanged()
{
try
{
if(textbox.Text.Length > 5) //< This sucks and I know it.
{
string text = textbox.Text;
await Task.Run(()=>doSomeMadlyDemandingRandomStuff(text));
}
}
catch(Exception ex)
{
//Bloody exception is never caught.
}
}
Я знаю, что условное значение at TextChanged()
находится на расстоянии нескольких световых лет от производительности, но на данный момент я просто хочу, чтобы оно работало.
Вышеупомянутое исключение выдается, когда пользователь вводит довольно длинное предложение или когда он несколько раз отступает назад.
Все исключение Java.Lang.ArrayIndexOutOfBoundsException: length=20; index=20
.
Примечания
1) Я попытался запустить Environment.StackTrace
, но он зависает, и я просто не знаю, куда он выбрасывается. Любая помощь в этом отношении будет оценена.
2) Раньше он вызывал это самое исключение, когда общая длина превышала 20 символов, и метод await
ed Text
напрямую получал свойство, которое, я подозреваю, искажало значения из запущенного потока. Передача переменной ( text
) решила эту проблему.
3) Я знаю, что Java.Lang.ArrayIndexOutOfBoundsException
это значит. Я просто не знаю, когда он обращается к индексу, который выходит за пределы.
4) У Xamarin Forms Editor
та же проблема.
5) Некоторый контекст, чтобы уточнить, что должно делать это текстовое поле: предполагается, что оно служит в качестве автозаполняемой (способной) записи, где пользователь вводит несколько букв, список заполняется результатами и продолжает обновляться по мере ввода оставшихся букв.
Комментарии:
1. попробуйте поймать (исключение ) { }
2. Забавно, что он улавливает исключение, если переменная не указана, но, к сожалению, я не могу просто игнорировать эту проблему.
3. проверьте реализацию doSomeMadlyDemandingRandomStuff.
4. Он использует предоставленную строку для отправки ее через
DependencyService
компонент на базе Android. Проблема не должна быть.5. Не обращайте на это внимания. Перехват исключения без переменной вообще не перехватил его.
Ответ №1:
Я вижу потенциальные проблемы с. doSomeMadlyDemandingRandomStuff
.. если это займет некоторое время, что может помешать пользователю снова изменить текст и, таким образом, снова вызвать обработчик до того, как вы закончите обработку первого события изменения текста? В качестве теста вы можете временно отключить текстовое поле, пока не будет выполнено «MadlyDemandingRandomStuff», чтобы увидеть, может ли повторный вызов этого обработчика до завершения первого обработчика быть непосредственной причиной проблемы, например:
public async void TextChanged()
{
textbox.IsEnabled = false;
try
{
if(textbox.Text.Length > 5) //< This sucks and I know it.
{
string text = textbox.Text;
await Task.Run(()=>doSomeMadlyDemandingRandomStuff(text));
textbox.IsEnabled = true;
}
}
catch(Exception ex)
{
//Bloody exception is never caught.
}
}
Я знаю, что это не может быть «ответом», но это может помочь найти проблему, поэтому опубликуйте ее как таковую.
Кроме того, если это собственное исключение, иногда собственные исключения приводят к сбою приложения до того, как какое-либо исключение может быть отправлено обратно на управляемую сторону, поэтому ваш блок catch никогда не поймает его.
Комментарии:
1. Спасибо за ваш ответ, @jgoldberger. Я обновил вопрос, чтобы предоставить некоторый контекст для того, что должно делать текстовое поле. Пользователю рекомендуется продолжать печатать, и, если я отключу компонент, клавиатура Android будет «отодвинута».
2. @EricWu Я создал свою собственную страницу автозаполнения, которая заполняет a
ListView
по мере ввода пользователем (она вызывает службу для данных), и я добавил дроссельTimeSpan
, который может работать аналогично отключению текстового поля без того, чтобы пользователь видел эффект. Добавление чего-то вроде следующего в вашTask.Run
:if(DateTime.UtcNow - _lastRequestDateTime <= TimeSpan.FromMilliseconds(500)) { return; } _lastRequestDateTime = DateTime.UtcNow;
3. @hvaughan3 это на самом деле звучит правдоподобно, но кажется немного … некрасиво. Я собираюсь попробовать это, и, если это сработает, я дам вам знать.