onSaveInstanceState и onRestoreInstanceState вызываются, но при ротации данные сбрасываются

Я добавил onRestoreInstanceState и onSaveInstanceState в свой код, чтобы сохранить переменную, которая должна быть сохранена, но эта переменная не сохраняется после поворота

Я попытался погуглить, я видел, как Logcat и Android вызывают обе эти функции, вот важный раздел Logcat.

I/SimpleActivity: PlayTheGame #9469915 onPause()

I/SimpleActivity: PlayTheGame #9469915 onSaveInstanceState()

I/SimpleActivity: PlayTheGame #9469915 onStop()

I/SimpleActivity: PlayTheGame #9469915 onDestroy()

I/SimpleActivity: PlayTheGame #245612069 onStart()

I/SimpleActivity: PlayTheGame #245612069

onRestoreInstanceState(bundle=Bundle[{points=-4, android:viewHierarchyState=Bundle[{android:views={/какие-то странные числа/} I/SimpleActivity: PlayTheGame #245612069 onResume()

Итак, похоже, что функции, которые я сделал, вызываются, но не реализуются

package com.example.rishabhjain.myapplication;

import android.content.Intent;
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import java.util.TreeMap;

import stanford.androidlib.AutoSaveFields;
import stanford.androidlib.SimpleActivity;

//SimpleActivity is standford library I have downloaded,It only makes 
//Syntax easy. Not used uch in this code although

public class PlayTheGame extends SimpleActivity {

private static Map<String, String> dictionary = null;//keeps words and 
//defns
private static ArrayList<String> arr = null;//keeps only words
TextView score = null;
private MediaPlayer mp;//for starting music when playing the game

private int sc;//this variable saves score

//the next two functions read files containing words and their meanings
private void readFileData() {
    Scanner scan = new Scanner(
            getResources().openRawResource(R.raw.text)//scans from raw file
    );
    readIt(scan);//readIt and store it in dictionary
    try {//in try in case user didn't added a word and file was not created
        Scanner scan2 = new Scanner(
                openFileInput("dictionary.txt")//reads the user saved words
        );
        readIt(scan2);
    } catch (Exception e) {
        //do noting
    }
}

private void readIt(Scanner scan) {
    /*splits appart the words of each file from their definitions*/
    while (scan.hasNextLine()) {
        String line = scan.nextLine();
        String[] parts = line.split("\t");//stores the splitted parts
        if (parts.length < 2)
            continue;//in case encountered an emply line
        dictionary.put(parts[0], parts[1]);//words and correspondind defns
        //added to the dictionary
        arr.add(parts[0]);//stores words
    }
}

//to reset word after each click or onCreate
private void resetWord() {
    Random randy = new Random();
    int nextInt = randy.nextInt(arr.size());
    String nextWord = arr.get(nextInt);
    TextView word = (TextView) findViewById(R.id.word);
    for (; nextWord.equals(word.getText()); ) {
        nextInt = randy.nextInt(arr.size());
        nextWord = arr.get(nextInt);
    }

    String realdefn = dictionary.get(nextWord);
    List<String> options = new ArrayList<>(dictionary.values());
    options.remove(realdefn);


    Collections.shuffle(options);
    options = options.subList(0, 3);
    options.add(realdefn);
    Collections.shuffle(options);
    word = (TextView) findViewById(R.id.word);
    word.setText(nextWord);
//the listview, onClick of it is on onCreate
    ListView list = (ListView) findViewById(R.id.list);
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
            this,
            android.R.layout.simple_list_item_1,
            options
    );
    list.setAdapter(adapter);
}

//checks if the user clicked correct answer or not it too works file
private void checkCorrect(String defn) {
    TextView word = (TextView) findViewById(R.id.word);
    score = (TextView) findViewById(R.id.score);


    if (defn.equals(dictionary.get(word.getText()))) {
        sc++;
        score.setText("Score: " + sc);
        toast("Nice One");
    } else {
        sc--;
        score.setText("Score: " + sc);
        toast("booooo!");
    }
    resetWord();
}

//To save the variable sc when performing rotation but not working,sc 
//getting
//set to zero after rotation
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("sc", sc);
}

//this may be the reason of the problem to the world either
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    sc = savedInstanceState.getInt("sc");
}

//onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_play_the_game);

    setTraceLifecycle(true);//library function that generates Log
//nothing to do with app, just displays the activity life cycle
    dictionary = new TreeMap<>();
    arr = new ArrayList<String>(dictionary.keySet());
    sc = 0;
    readFileData();//read file data into the dictionary
    resetWord();//reset word
    //setting the onClick for the List works fine
    ListView list = (ListView) findViewById(R.id.list);
    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) {
            String defn = parent.getItemAtPosition(position).toString();
            checkCorrect(defn);
        }
    });
    //plays the song Makhana, nice song must listen :)
    //works fine
    mp = MediaPlayer.create(this, R.raw.recordings);
    mp.start();
}

//the layout of this activity has a button to other activity called AddWord
//onResume when you return from that activity, works fine
@Override
protected void onResume() {
    super.onResume();
    mp.start();
}

//onPause when goning from this activity to AddWord, this too works fine
@Override
protected void onPause() {
    super.onPause();

    mp.pause();
}

//this directs to AddWord, attached with a button, works fine
public void addAWordClick(View view) {
    Intent intent = new Intent(this, AddWord.class);
    startActivity(intent);
}

}

Игра чем-то похожа на то, что программа считывает из файлов две вещи: слова и их значения, затем отображается слово и 4 варианта, и если вы выбираете правильный, ваш счет увеличивается, иначе уменьшается. Эта оценка сохраняется в переменной sc. Я хотел сохранить эту переменную при повороте экрана. Но этого, кажется, не происходит

Я также пробовал:

Я попытался удалить onRestoreInstanceState и изменил код

arr = new ArrayList<String>(dictionary.keySet());
    sc = savedInstanceState.getInt("sc",0);// previosly sc=0
    readFileData();

но это вызывает ошибку
Причина: java.lang.NullPointerException: попытка вызвать виртуальный метод 'int android.os.Bundle.getInt(java.lang.String, int)' для нулевой ссылки на объект

Затем я обновил код в onCreate до этого

if(savedInstanceState!=null)
    sc = savedInstanceState.getInt("sc",0);
    else
        sc = 0;

это не вернуло никакой ошибки, но все же после вращения sc снова устанавливается на ноль


person rishabh jain    schedule 25.01.2019    source источник
comment
Обычно я использую saveInstanceState в onCreate(), лично я даже не знал, что onRestoreInstanceState вообще существует: P В onCreate проверьте, является ли saveInstanceState !=null, а затем присвойте свои значения, как вы это делаете в onRestoreInstanceState()   -  person Zee    schedule 25.01.2019
comment
Не ставьте sc = 0; в методе onCreate() каждый раз дайте нулевую проверку, является ли Bundle нулевым или нет. вы можете прочитать это, если у вас есть сомнения, какой метод выбрать при восстановлении.   -  person Rohit Singh    schedule 25.01.2019


Ответы (1)


Дело не в том, что он не работает, а в том, что onRestoreInstanceState() вызывается после onStart(), который вызывается после onCreate().

Вы выполняете всю свою обработку в onCreate() и сохраняете только sc в OnRestoreInstanceState(), в то время как onCreate() имеет sc = 0;

Это приведет к тому, что вся обработка, которую вы выполняете в onCreate(), будет использовать значение 0 вместо сохраненного вами значения sc. Потому что он не достиг этапа жизненного цикла активности, на котором он извлекает ваше значение sc.

Используйте sc = savedInstanceState.getInt("sc", 0); вместо sc = 0 в методе onCreate(). Вы можете избавиться от метода onRestoreInstanceState().

Таким образом, если вы ранее сохранили sc через onSaveInstanceState(), вы сможете получить это значение в своем onCreate(). Если вы его не сохранили, будет использоваться значение по умолчанию 0.

Изменить:

Убедитесь, что savedInstanceState имеет значение null, потому что оно будет нулевым, если из onSaveInstanceState() ничего не было передано, что обычно происходит при первом запуске.

arr = new ArrayList<String>(dictionary.keySet());
sc = savedInstanceState==null ? 0 : savedInstanceState.getInt("sc", 0);
readFileData();//read file data into the dictionary
person Jackey    schedule 25.01.2019
comment
я изменил его так: arr = new ArrayList‹String›(dictionary.keySet()); sc = saveInstanceState.getInt (sc, 0); readFileData();//прочитать данные файла в словарь..... но это дало мне ошибку - person rishabh jain; 25.01.2019
comment
Извините, забыл, что этот пакет может быть нулевым. Вам просто нужно проверить, имеет ли значение saveInstanceState значение null. Если он нулевой, это означает, что это начальный запуск, и вы можете просто установить 0 в sc. Если он не нулевой, это означает, что он прошел через onSaveInstanceState(), и вы можете использовать метод savedInstanceState.getInt() для извлечения значения. - person Jackey; 25.01.2019
comment
Я надеялся, что по умолчанию сделано для обработки таких ситуаций, но я попробовал и это, это не дало ошибки, но и не помогло. - person rishabh jain; 25.01.2019
comment
Можете ли вы описать, что происходит? Я дам вам сценарий. После начальной загрузки Score TextView пуст. Вы нажимаете на правильный ответ, и это должно установить текст в Score TextView как Score: 1. Затем поверните устройство. Текстовое представление Score снова должно быть пустым. Нажмите на другой правильный ответ. Что показывает Score TextView? - person Jackey; 25.01.2019
comment
Когда я начинаю, он отображает Score: 0, затем я отвечаю правильно, он отображает Score: 1, когда я поворачиваю, он снова устанавливает Score: 0 @Jackey - person rishabh jain; 25.01.2019