Как использовать пример onSavedInstanceState, пожалуйста

110

Я сбит с толку, когда дело доходит до сохранения состояния. Итак, я знаю, что это onSaveInstanceState(Bundle)вызывается, когда активность вот-вот будет уничтожена. Но как сохранить в нем информацию и вернуть ее в исходное состояние onCreate(Bundle savedInstanceState)? Я не понимаю, как эта связка восстановит информацию. Было бы полезно, если бы кто-нибудь мог привести пример. Руководство разработчика не очень хорошо объясняет это.

public class Conversation extends Activity {
    private ProgressDialog progDialog;
    int typeBar;
    TextView text1;
    EditText edit;
    Button respond;
    private String name;
    private String textAtView;
    private String savedName;

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        setContentView(R.layout.dorothydialog);
        text1 = (TextView)findViewById(R.id.dialog);
        edit = (EditText)findViewById(R.id.repsond);
        respond = (Button)findViewById(R.id.button01);

        if(savedInstanceState != null){
            savedInstanceState.get(savedName);
            text1.setText(savedName);
        }
        else{
            text1.setText("Hello! What is your name?");
            respond.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    name = edit.getText().toString();
                    text1.setText("Nice to meet you "+ name);
                }   
            });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        outState.putString(savedName, name);
    }
}
Ти Джей Уокер
источник
text1.setText (savedInstanceState.getString (savedName));
Spidy
@Spidy А как насчет onBackpressed? Как бы я на это отреагировал со связкой?
TJ ходунки
Ты бы не стал. Когда пользователь нажимает кнопку "Назад". Активность убита. Используйте базу данных для постоянного хранения данных. Используйте Bundle для возврата перезапущенного приложения в предыдущее состояние.
Spidy

Ответы:

198

Это Bundleконтейнер для всей информации, которую вы хотите сохранить. Вы используете функции put * для вставки в него данных. Вот краткий список (их больше) функций put, которые вы можете использовать для хранения данных в Bundle.

putString
putBoolean
putByte
putChar
putFloat
putLong
putShort
putParcelable (used for objects but they must implement Parcelable)

В вашей onCreateфункции это Bundleпередается программе. Лучший способ проверить, перезагружается ли приложение или запускается впервые:

if (savedInstanceState != null) {
    // Then the application is being reloaded
}

Чтобы вернуть данные, используйте функции get * точно так же, как функции put *. Данные хранятся в виде пары имя-значение. Это похоже на хэш-карту. Вы предоставляете ключ и значение, затем, когда вы хотите вернуть значение, вы даете ключ, и функция получает значение. Вот небольшой пример.

@Override
public void onSaveInstanceState(Bundle outState) {
   outState.putString("message", "This is my message to be reloaded");
   super.onSaveInstanceState(outState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        String message = savedInstanceState.getString("message");
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }
}

Ваше сохраненное сообщение будет отображаться на экране. Надеюсь это поможет.

Spidy
источник
14
onSaveInstanceState () вызывается до того, как ваша деятельность будет приостановлена. Таким образом, любая информация, которая ему понадобится после того, как она потенциально может быть уничтожена, может быть извлечена из сохраненного пакета
Дидерик
@Spidy Отлично! Вы просто заставили меня понять все о связке! так я предполагаю, что outState передается обратно в пакет savedInstanceState? Верный?
tj walker
Ага. Пакет outState передается обратно как пакет SavedInstanceState
Spidy
1
@tj walker - Еще один отличный ресурс - технические справочники. Pro Android 3 - дешевый, но обширный ресурс, который вы можете получить на Amazon
Spidy
@Spidy Я разместил свой код активности выше, чтобы вы могли его увидеть. Может быть, вы дадите мне знать, правильно ли я сохраняю свое состояние, как вы предлагали.
tj walker
34

Одно важное замечание, которое должны знать все новые разработчики Android, - это то, что любая информация в виджетах (TextView, Buttons и т. Д.) Будет автоматически сохраняться Android до тех пор, пока вы назначите им идентификатор. Это означает, что о большей части состояния пользовательского интерфейса заботятся без проблем. Только когда вам нужно сохранить другие данные, это становится проблемой.

Из Android Docs :

Единственное, что от вас требуется, - это предоставить уникальный идентификатор (с атрибутом android: id) для каждого виджета, состояние которого вы хотите сохранить. Если виджет не имеет идентификатора, он не может сохранить свое состояние.

Кейт Адлер
источник
1
Это правда? Потому что у меня есть действие с текстовым просмотром кнопки и редактированием текста. Если приложение уничтожено или убито, все возвращается в исходное состояние. В моем приложении тексты textView меняются каждый раз, когда пользователь нажимает кнопку.
tj walker
Документация неточна? У меня никогда не было просмотра, сохраняющего собственную информацию. На мой взгляд, лучше всего сохранить всю информацию самостоятельно.
Spidy
2
Если ваша цель состоит в том, чтобы сохранить информацию, onSaveInstanceState НЕ подходит для этого. Это потому, что нет гарантии, что он будет вызван (см. Документацию). Вместо этого вы должны писать в базу данных, SharedPreferences и т. Д. Да, эта информация точна. Лучший способ проверить, сохраняется ли ваш пользовательский интерфейс таким образом, - это повернуть дисплей при изменении ориентации, перезапустить onCreate и использовать пакет для восстановления состояния.
Кейт Адлер,
@Nissan Fan, можете ли вы привести пример, как это сделал spidy выше? С sharedprefs и всем остальным? Спасибо
tj walker
Честно говоря, лучшие примеры взяты из документации. developer.android.com/guide/topics/data/data-storage.html#pref
Кейт Адлер,
6

Хорошая информация: вам не нужно проверять, является ли объект Bundle нулевым в методе onCreate (). Используйте метод onRestoreInstanceState (), который система вызывает после метода onStart (). Система вызывает onRestoreInstanceState () только при наличии сохраненного состояния для восстановления, поэтому вам не нужно проверять, является ли Bundle нулевым.

Диего Соуза
источник
5

Информация о магазине:

static final String PLAYER_SCORE = "playerScore";
static final String PLAYER_LEVEL = "playerLevel";

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(PLAYER_SCORE, mCurrentScore);
    savedInstanceState.putInt(PLAYER_LEVEL, mCurrentLevel);

// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}

Если вы не хотите восстанавливать информацию в своем onCreate-Method:

Вот примеры: воссоздание действия

Вместо восстановления состояния во время onCreate () вы можете выбрать реализацию onRestoreInstanceState (), которую система вызывает после метода onStart (). Система вызывает onRestoreInstanceState () только при наличии сохраненного состояния для восстановления, поэтому вам не нужно проверять, является ли Bundle нулевым.

public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);

// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(PLAYER_SCORE);
mCurrentLevel = savedInstanceState.getInt(PLAYER_LEVEL);
}
Klatschen
источник
0

В основном onSaveInstanceState (Bundle outBundle) предоставит вам пакет. Когда вы посмотрите на класс Bundle, вы увидите, что в него можно поместить много разных вещей. При следующем вызове onCreate () вы просто получаете этот Bundle в качестве аргумента. Затем вы можете снова прочитать свои значения и восстановить свою активность.

Допустим, у вас есть действие с EditText. Пользователь написал внутри него какой-то текст. После этого система вызывает ваш onSaveInstanceState (). Вы читаете текст из EditText и записываете его в Bundle через Bundle.putString ("edit_text_value", theValue).

Теперь вызывается onCreate. Вы проверяете, не является ли поставляемый комплект нулевым. Если это так, вы можете восстановить свое значение через Bundle.getString ("edit_text_value") и вернуть его в свой EditText.


источник
0

Это для дополнительной информации.

Представьте себе этот сценарий

  1. ActivityA запуск ActivityB.
  2. ActivityB запускает новый ActivityAPrime от

    Intent intent = new Intent(getApplicationContext(), ActivityA.class);
    startActivity(intent);
  3. ActivityAPrime не имеет отношения к ActivityA.
    В этом случае Bundle в ActivityAPrime.onCreate () будет нулевым.

Если ActivityA и ActivityAPrime должны быть одним и тем же действием, а не разными, ActivityB должен вызывать finish (), а не startActivity ().

Кен
источник
просто для пояснения, в вашем примере это ActivityA == ActivityA instance 1 и ActivityAPrime == ActivityA instance 2? также, когда вы говорите: «ActivityB должен вызывать finish (), чем использовать startActivity ()». Вы имеете в виду: (1) AcitivityB должен вызвать finish (), а затем использовать startActivity () (2) или ActivityB должен вызвать finish (), а не использовать startActivity () вообще? если вы имели в виду вариант 2, как бы вы посоветовали кому-то перезапустить то же действиеA instance1, чтобы вы могли загрузить данные, содержащиеся в действии до его уничтожения / завершения? Спасибо
cjayem13
ActivityA и ActivityAPrime относятся к одному классу, но к разным экземплярам. В этом сценарии ActivityA еще не завершает свой бизнес, в середине он создал и запустил ActivityB, поэтому после завершения ActivityB ActivityA должен продолжить свою оставшуюся работу. В этом случае неправильно вызывать startActivity и ожидать, что ActivityA и ActiviyAPrime будут одним и тем же экземпляром. поэтому нам не следует перезапускать ActivityA, просто завершите ActivityB и позвольте ActivityA возобновить свою работу ...
Кен
0

Если данные не загружены из, savedInstanceStateиспользуйте следующий код.
Проблема в том, что вызов URL-адреса не завершен полностью, поэтому проверьте, загружены ли данные, а затем отобразите значение instanceState.

//suppose data is not Loaded to savedInstanceState at 1st swipe
if (savedInstanceState == null && !mAlreadyLoaded){
    mAlreadyLoaded = true;
    GetStoryData();//Url Call
} else {
    if (listArray != null) {  //Data Array From JsonArray(ListArray)
        System.out.println("LocalData  " + listArray);
        view.findViewById(R.id.progressBar).setVisibility(View.GONE);
    }else{
        GetStoryData();//Url Call
    }
}
Матан Чинна
источник