简体   繁体   中英

onSaveInstanceState and onRestoreInstanceState being called but yet on rotation data is getting reset

I added an onRestoreInstanceState and onSaveInstanceState in my code to save a variable that is to be saved, but yet that variable is not getting preserved after rotation

I tried googling it, I have seen the Logcat and android do call both of these functions here is the important section of the 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={/ some weird numbers /} I/SimpleActivity: PlayTheGame #245612069 onResume()

So it seems like the functions I have made are getting called but not getting implemented

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);
}

}

The game is something like the program reads from the files two things: words and their meanings, the word and 4 options are then displayed and if you choose correct one your score increases, else decreases. This score is saved in the variable sc. I wished to preserve this variable when did screen rotation. But this does not seem to happen

I also tried:

I tried removing onRestoreInstanceState and changed the code

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

but that generate an error
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.os.Bundle.getInt(java.lang.String, int)' on a null object reference

I then updated the code in onCreate to this

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

this didn't returned any error but still after rotation sc is getting set to zero again

It's not that it's not working, but that onRestoreInstanceState() is called after onStart() which is called after onCreate() .

You do all your processing in onCreate() and you only store sc in OnRestoreInstanceState() while onCreate() has sc = 0;

This will cause all that processing you're doing in onCreate() to use the 0 value instead of the sc value you saved. Because it hasn't reached the step in the Activity Lifecycle where it fetches your sc value.

Use sc = savedInstanceState.getInt("sc", 0); instead of sc = 0 in your onCreate() method. You can get rid of the onRestoreInstanceState() method.

This way, if you previously saved sc through onSaveInstanceState() , you will be able to get that value in your onCreate() . If you didn't save it, it'll use the default value of 0.

Edit:

Check to see if savedInstanceState is null, because it will be null if nothing was passed in from onSaveInstanceState() which normally happens on the first run.

arr = new ArrayList<String>(dictionary.keySet());
sc = savedInstanceState==null ? 0 : savedInstanceState.getInt("sc", 0);
readFileData();//read file data into the dictionary

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM