TextView медленно заполняется текстом, поступающим из фонового сервиса. Я переопределил методы onSaveInstanceState() и onRestoreInstanceState() в MainActivity и добавил атрибут android:freezesText = "true" к TextView в макете. В большинстве случаев содержимое TextView сохраняется при повороте устройства или сворачивании приложения, нажатии кнопки «Домой» и запуске другого приложения. Однако время от времени содержимое теряется. Поскольку она медленно собирается фоновой службой, ее нелегко восстановить, и ценная информация теряется.
Я тестирую приложение на устройстве с Android 7.0, но я также распространил его на другие устройства с другими версиями Android, и оно работает нормально, за исключением этих случайных потерь информации.
public class MainActivity extends AppCompatActivity {
private TextView textView;
static private boolean firstRun = true;
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
String newPost = bundle.getString(MyService.POST);
textView.append((new Date()).toString().substring(11, 19) + " " + newPost + "\n");
// Delete 250 leading chars if too many
Editable ed = textView.getEditableText();
int len = ed.length();
if ( len > 5000 ) ed.delete(0, 250);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.idTextView);
if ( firstRun ) {
firstRun = false;
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putCharSequence("TEXTVIEW", textView.getText());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
CharSequence viewContents = savedInstanceState.getCharSequence("TEXTVIEW");
textView.setText(viewContents);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter(MyService.NOTIFICATION));
}
}
Я прочитал много сообщений о подобных проблемах и сделал все, что знал, чтобы избежать этого.
РЕДАКТИРОВАТЬ: Я добавил атрибут android:configChanges в Activity в манифесте. onCreate () теперь вызывается только один раз. Тем не менее, содержимое TextView иногда теряется из-за приложения начать сначала. Это происходит только при перерисовке приложения, при реконфигурации или при переводе его на передний план. Почему перезапускается? Logcat в Android Studio сообщает об отсутствии проблем.
Спасибо Грациано за это предложение. Не могли бы вы объяснить, как это влияет на содержимое TextView, когда устройство поворачивается или приложение скрыто другим? Как указано в другом комментарии, проверить решение довольно сложно.
В вашем коде есть 3 элемента, которые могут изменить ваш EditText во время вращения: BroadcastReceiver, атрибут android:freezesText = "true" и методы onSave/RestoreInstanceState. Мое предложение состоит в том, чтобы остановить первое (здесь мое предыдущее предложение), но я предлагаю также удалить второе (атрибут freezesText), чтобы оставить bunden и честь задачи onSave/RestoreInstanceState.
@Graziano Хорошо, легко удалить freezesText и добавить unregisterReceiver. Я могу попробовать. Но, честно говоря, получатель только добавляет больше текста, и я думаю, что freezesText ничего не делает, потому что я никогда не вызываю onSaveInstanceState и onRestoreInstanceState в TextView. Но опять же, я понятия не имею, почему/когда это происходит, поэтому это очень сложно проверить. Я никогда не буду уверен, что это решено.
@Graziano Добавление unregisterReceiver() оказалось совершенно необходимым, чтобы избежать утечки памяти, но оно не решило исчезающий текст. Я считаю, что onRestoreInstanceState() не вызывается в некоторых случаях, но я не знаю, когда и почему. Потеря текста в TextView происходит редко, но бывает. Я также добавил onRestoreInstanceState() к onCreate(), но это не помогло.




вы используете общие настройки
Для градиента
implementation 'com.google.code.gson:gson:2.8.8'
Инициализировать общие настройки
SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);
Сохранить данные или любой объект и класс
MyObject myObject = new MyObject;
Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject);
prefsEditor.putString("MyObject", json);
prefsEditor.commit();
Получить данные
Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);
Вы можете сохранять данные разными способами, например. используя файл, с которым я более знаком. Но использование Bundle savedInstanceState является рекомендуемым решением и должно работать. Я не думаю, что savedInstanceState потерян, должно быть другое объяснение.
проверьте также Bundle, переданный в качестве аргумента методу onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
... your code
checkInstanceState(savedInstanceState); // at the end after GUI init
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
checkInstanceState(savedInstanceState);
}
private void checkInstanceState(Bundle savedInstanceState) {
if (savedInstanceState==null) return;
CharSequence viewContents = savedInstanceState.getCharSequence("TEXTVIEW");
textView.setText(viewContents);
}
Обратите внимание, что savedInstanceState не может быть нулевым в onRestoreInstanceState, см. документы. Я мог бы добавить восстановление TextView в onCreate, но onRestoreInstanceState приходит позже и переопределяет его. Проверить решение очень сложно, так как проблема возникает редко и я не знаю, как ее спровоцировать.
Потеря содержимого TextView происходит, когда Android время от времени уничтожает активность в фоновом режиме и воссоздает ее, когда приложение выводится на передний план. В этом случае в вызове onCreate()Bundle savedInstanceState есть null, и его нельзя использовать для восстановления TextView. Однако статические переменные в Activity сохраняются.
РЕШЕНИЕ: чтобы сохранить содержимое TextView в этом переходе уничтожения-создания, сохраните содержимое в статической переменной в onSaveInstanceState() и восстановите в onCreate(). В этом сценарии onRestoreInstanceState() никогда не вызывается и не может использоваться.
Я проверил это решение на устройстве с Android 7.0. Другие версии Android могут вести себя иначе. Жаль, что Android так плохо документирован.
Попробуйте добавить
onPause()и вставить вызовunregisterReceiver(receiver).