Как EditText сохраняет свое значение, но не текстовое представление при изменении ориентации телефона?

Что такого особенного в Edittext, что он может сохранять значение, но не Textview и некоторые другие виджеты, и мы должны использовать для них метод onSavedInstance().

В чем магия EditText, особенно в том, что он может сохранять значения?

Если кто может подскажите как он работает внутренне.

‹----Обновление---->

Как это работает внутри? Пожалуйста, укажите на ту часть кода, которая объясняет этот сценарий.


person Hisham Muneer    schedule 21.03.2013    source источник
comment
Вы устанавливаете значение TextView через код?   -  person Abhishek Nandi    schedule 21.03.2013
comment
Я не спрашиваю, как его сохранить, но как он автоматически обрабатывается Android?   -  person Hisham Muneer    schedule 21.03.2013
comment
на самом деле так и будет... или ты хочешь сказать что-то другое?/   -  person Kiran    schedule 21.03.2013
comment
нет никакого волшебства, весь его код, андроид ничего не делает, опубликуйте свой xml-файл и код метода onCreate   -  person Abhishek Nandi    schedule 21.03.2013
comment
Что такого особенного в Edittext, что он может сохранять значение — он наследуется от TextView. Он наследует метод onSavedInstanceState() от TextView, у которого есть логика для сохранения его текста. но не Textview - сохраняет ли onSaveInstanceState() в TextView свой текст, зависит от того, вызывается ли setFreezesText(true) (или устанавливается android:freezesText). По умолчанию для TextView используется значение false, что означает, что текст не сохраняется. Чего я не вижу, так это того, как EditText устанавливает это значение по умолчанию на true.   -  person CommonsWare    schedule 31.10.2014


Ответы (5)


В чем магия EditText, особенно в том, что он может сохранять значения? Как это работает внутри? Пожалуйста, укажите на ту часть кода, которая объясняет этот сценарий.

Отличие заключается в выбираемом свойстве. Следующее условие if в TextView.onSaveInstanceState позаботится об этом.

@Override
public Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();

    // Save state if we are forced to
    boolean save = mFreezesText;
    int start = 0;
    int end = 0;

    if (mText != null) {
        start = getSelectionStart();
        end = getSelectionEnd();
        if (start >= 0 || end >= 0) {
            // Or save state if there is a selection
            save = true;
        }
    }

    ...
}

По умолчанию TextView нельзя выбрать. Следовательно, getSelectionStart() и getSelectionEnd() возвращают -1, а переменная save содержит ложное значение. Чтобы сохранить содержимое при изменении ориентации, установите атрибут textIsSelectable к истине.

Поскольку EditText выбирается по умолчанию, getSelectionStart() и getSelectionEnd() всегда возвращают значение >=0, а переменная save содержит истинное значение, и содержимое сохраняется.

Примечание. По умолчанию параметр freezesText отключен. Следовательно, значение mFreezesText ложно.

person Manish Mulimani    schedule 01.11.2014
comment
Можете ли вы объяснить, почему getSelectionStart() и getSelectionEnd() всегда возвращают значение ›=0, когда textIsSelectable истинно? Я имею в виду, если текст можно выделить, но ничего не выбрано, разве оба метода не должны возвращать -1? - person curioustechizen; 03.11.2014
comment
@curioustechizen Если текст не выделен, начало и конец выделения будут равны 0, что указывает на то, что текст не выделен. Это то же самое, что поместить курсор в 0-й индекс, как в случае EditText. Это место, где установлено значение 0. - person Manish Mulimani; 03.11.2014
comment
Хм.. это сбивает с толку. Код, на который вы ссылаетесь, кажется, противоречит javadocs. В частности, TextView#getSelectionStart() указывает на android.text.Selection#getSelectionStart(). И javadocs для последнего состояния: Return the offset of the selection anchor or cursor, or -1 if there is no selection or cursor. - person curioustechizen; 03.11.2014
comment
@curioustechizen Я полагаю, что no selection означает, что свойство textIsSelectable вообще не установлено. - person Manish Mulimani; 03.11.2014
comment
@Taranfx Да, моя ошибка. Спасибо, что нашли его, я обновил ответ. - person Manish Mulimani; 06.11.2014

По умолчанию представление EditText сохраняет свое состояние. Это достигается путем установки флагов в коде, сообщающих представлению о сохранении состояния, когда представление не отображается или теряет фокус. Текст автоматически сохраняется и восстанавливается после поворота устройства. Автоматическое сохранение состояния представления EditText можно отключить в файле макета XML, установив для свойства android:saveEnabled значение false:

 android:saveEnabled="false"

Или программно вызовите view.setSaveEnabled(false).

saveEnabled определяет, включено ли сохранение состояния этого представления (то есть будет ли вызываться его метод onSaveInstanceState()). Обратите внимание, что даже если замораживание включено, представление все равно должно иметь назначенный ему идентификатор (через setId()), чтобы его состояние сохранялось. Этот флаг может только отключить сохранение этого вида; любые дочерние представления могут сохранять свое состояние. Атрибут saveEnabled является частью Android View — Просмотреть код. Вот связанные части кода:

public boolean isSaveEnabled() {
        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
    }

...

 public void setSaveEnabled(boolean enabled) {
        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
    }

...

 void setFlags(int flags, int mask) {
        int old = mViewFlags;
        mViewFlags = (mViewFlags & ~mask) | (flags & mask);

        int changed = mViewFlags ^ old;
        if (changed == 0) {
            return;
        }
        int privateFlags = mPrivateFlags;

        /* Check if the FOCUSABLE bit has changed */
        if (((changed & FOCUSABLE_MASK) != 0) &&
                ((privateFlags & HAS_BOUNDS) !=0)) {
            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
                    && ((privateFlags & FOCUSED) != 0)) {
                /* Give up focus if we are no longer focusable */
                clearFocus();
            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
                    && ((privateFlags & FOCUSED) == 0)) {
                /*
                 * Tell the view system that we are now available to take focus
                 * if no one else already has it.
                 */
                if (mParent != null) mParent.focusableViewAvailable(this);
            }
        }

....

person Wildroid    schedule 07.11.2014

Цитата из этой статьи: https://tekeye.uk/android/examples/saving-activity-state

«Переключение устройства с книжной на альбомную приводит к тому, что Android останавливает и перезапускает действие, позволяя действиям перерисовывать экран для разных размеров. При остановке и запуске действия пользователи часто раздражаются, если ввод продолжает теряться. Android У действий есть пара методов, называемых onSaveInstanceState(Bundle) и onRestoreInstanceState(Bundle), которые автоматически используются входными представлениями для сохранения их данных. все элементы экрана), чтобы иметь идентификатор. Преимущество заключается в том, что эта пара методов может быть переопределена в действии, так что переменные состояния, не связанные с полями ввода, также могут быть сохранены и восстановлены».

Удалите идентификатор из текста редактирования и попробуйте :)

person Daniel S. Fowler    schedule 21.03.2013
comment
Textview и edittext изначально имеют значение mFreeze как false. Но Edittext поддерживает состояние. Но Textview не поддерживает состояние. Как это происходит??? - person Mohamed Ibrahim; 11.01.2016

Попробуйте это для своего текстового просмотра, я думаю, это может вам помочь

<TextView 
 ... 
 android:freezesText="true" />
person Akash    schedule 07.11.2014
comment
Ты мой герой ! - person Hilal; 18.02.2019

Класс Android View имеет защищенные методы

protected Parcelable onSaveInstanceState ()
protected void onRestoreInstanceState (Parcelable state)

поэтому любое представление может переопределить эти методы и сохранить с ними информацию о состоянии представления.

TextView расширяет класс View и имеет в нем реализацию protected Parcelable onSaveInstanceState() и protected void onRestoreInstanceState (состояние Parcelable).

давайте посмотрим на реализацию onSaveInstanceState()

@Override
public Parcelable onSaveInstanceState()
{
    Parcelable superState = super.onSaveInstanceState();

    // Save state if we are forced to
    boolean save = mFreezesText;
    int start = 0;
    int end = 0;

    if (mText != null) 
    {
        start = getSelectionStart();
        end = getSelectionEnd();
        if (start >= 0 || end >= 0)
        {
            // Or save state if there is a selection
            save = true;
        }
    }
    ...
}
  1. как вы можете видеть здесь, функция сохранения зависит от одного флага «сохранить», поэтому, если пользователь явно укажет mFreezesText = true, он сохранит текст
  2. другая возможность, если есть курсор выбора, тогда он, по крайней мере, вернет getSelectionStart() = 0, а не -1, что заставит TextView сделать save=true для сохранения состояния TextView, и это то, что происходит с EditText, поскольку EditText имеет курсор выбора, и он делает расширяет TextView.
person Kirtan    schedule 07.11.2014