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)
.