简体   繁体   中英

Why does an object throw nullPointerException on RestoreInstanceState?

I've got a TextView and ImageButton objects in my android app, they appear correctly when the app starts (onCreate), but when saveInstanceState() and restoreInstanceState() are called the compiler throws nullPointerException (even though their states are loaded properly) when I try to setText or anything for that matter. I have some other ImageButtons that show correctly both times (on first onCreate, and when restoreInstanceState is called) so it puzzles me even further.

I had tried to create another instance of TextView, setText to it, and then set that TextView as the original, but it doesn't work.

public class MainActivity extends AppCompatActivity {
    private TextView score;
    private TextView labelPoints;
    private ImageButton finQuest;
    private int langFlag = 0;
    private PowerManager.WakeLock wakeLock;
    private int points = 0;
    private ListenerQuestionChooser lqc;
    //saving and loading the instanceState of the buttons bellow works perfectly
    private ImageButton btn1;
    private ImageButton btn2;
    private ImageButton btn3;
    private ImageButton btn4;
    private ImageButton btn5;
    private ImageButton btn6;

    @SuppressLint("InvalidWakeLockTag")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Lock");
        wakeLock.acquire();

        setContentView(R.layout.activity_main);

        labelPoints = findViewById(R.id.total_score);
        finQuest = findViewById(R.id.btn_finanswer);
        score = findViewById(R.id.text_points); 
        btn1 = findViewById(R.id.btn1);
        btn2 = findViewById(R.id.btn2);
        btn3 = findViewById(R.id.btn3);
        btn4 = findViewById(R.id.btn4);
        btn5 = findViewById(R.id.btn5);
        btn6 = findViewById(R.id.btn6);
        lqc = new ListenerQuestionChooser(this, this);

        if (savedInstanceState != null) {
            this.loadSettings(savedInstanceState);
        }

        btn1.setOnClickListener(lqc);
        btn2.setOnClickListener(lqc);
        btn3.setOnClickListener(lqc);
        btn4.setOnClickListener(lqc);
        btn5.setOnClickListener(lqc);
        btn6.setOnClickListener(lqc);

        if (getLangFlag() == 0){
            labelPoints.setVisibility(View.INVISIBLE);
            TextView s = findViewById(R.id.text_points);
            setScore(s);
            score.setVisibility(View.INVISIBLE);
        }else{
            //I have tried to directly set text to the original TextView, it didn't work
            //Then I tried like this, still doesn't work
            TextView s = findViewById(R.id.text_points);
            s.setText(getPoints()); //throws null pointer here
            setScore(s);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //there are other things saved here that are not relevant to the question, which save and load perfectly
        if (getFinQuest().getVisibility()==View.VISIBLE) {
            outState.putInt(STATE_FINAL_BUTTON, 1);
        } else{
            outState.putInt(STATE_FINAL_BUTTON, 0);
        }
        if (btn1.getVisibility() == View.INVISIBLE) {
            outState.putInt(STATE_BUTTON_01, 1);
        } else{
            outState.putInt(STATE_BUTTON_01, 0);
        }
        if (btn2.getVisibility() == View.INVISIBLE) {
            outState.putInt(STATE_BUTTON_02, 1);
        } else{
            outState.putInt(STATE_BUTTON_02, 0);
        }
        if (btn3.getVisibility() == View.INVISIBLE) {
            outState.putInt(STATE_BUTTON_03, 1);
        }else{
            outState.putInt(STATE_BUTTON_03, 0);
        }
        if (btn4.getVisibility() == View.INVISIBLE) {
            outState.putInt(STATE_BUTTON_04, 1);
        }else{
            outState.putInt(STATE_BUTTON_04, 0);
        }
        if (btn5.getVisibility() == View.INVISIBLE) {
            outState.putInt(STATE_BUTTON_05, 1);
        }else{
            outState.putInt(STATE_BUTTON_05, 0);
        }
        if (btn6.getVisibility() == View.INVISIBLE) {
            outState.putInt(STATE_BUTTON_06, 1);
        }else{
            outState.putInt(STATE_BUTTON_06, 0);
        }
        outState.putCharSequence(STATE_USERNAME_LANG, String.valueOf(langFlag));
          outState.putInt(STATE_POINTS, getPoints());
   }

   private void loadSettings(Bundle savedInstanceState){
        //I printed logs after each of these lines and the values are loaded perfectly
        CharSequence lFlag = savedInstanceState.getCharSequence(STATE_USERNAME_LANG);
        setLangFlag(Integer.parseInt(lFlag.toString()));
        int butFin = savedInstanceState.getInt(STATE_FINAL_BUTTON);
        if (butFin == 1) {
            finQuest.setVisibility(View.VISIBLE);
        }
        int but01 = savedInstanceState.getInt(STATE_BUTTON_01);
        if (but01 == 1) {
            btn1.setVisibility(View.INVISIBLE);
        }
        int but02 = savedInstanceState.getInt(STATE_BUTTON_02);
        if (but02 == 1) {
            btn2.setVisibility(View.INVISIBLE);
        }
        int but03 = savedInstanceState.getInt(STATE_BUTTON_03);
        if (but03 == 1) {
            btn3.setVisibility(View.INVISIBLE);
        }
        int but04 = savedInstanceState.getInt(STATE_BUTTON_04);
        if (but04 == 1) {
            btn4.setVisibility(View.INVISIBLE);
        }
        int but05 = savedInstanceState.getInt(STATE_BUTTON_05);
        if (but05 == 1) {
            btn5.setVisibility(View.INVISIBLE);
        }
        int but06 = savedInstanceState.getInt(STATE_BUTTON_06);
        if (but06 == 1) {
            btn6.setVisibility(View.INVISIBLE);
        }
        int poeni = savedInstanceState.getInt(STATE_POINTS);
        setPoints(poeni);
   }
    public int getPoints() {
        return points;
    }

    public void setPoints(int points) {
        this.points = points;
    }
    public TextView getScore() {
        return score;
    }

    public void setScore(TextView score) {
        this.score = score;
    }
}

FINAL EDIT: After approximately 16 hours of banging my head against the wall, trying various things (both logical and illogical) and printing logs on every step, I had solved the problem. So here's the solution (I still don't understand why other objects work perfectly without this and these objects require it, but hey, as long as it works I down with it).

if (lqc == null) {
        lqc = new ListenerQuestionChooser(this, this);
    }

    if (savedInstanceState != null) {
        this.loadSettings(savedInstanceState);
    }

    if (finQuest == null) {
        try {
            finQuest = findViewById(R.id.btn_finansfer);
            finQuest.setOnClickListener(lqc);
            if (ListenerQuestionChooser.getCorrectAnswer() > 0) {
                finQuest.setVisibility(View.VISIBLE);
            } else {
                finQuest.setVisibility(View.INVISIBLE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    if (labelPoints == null) {
        labelPoints = findViewById(R.id.total_score);
        score = findViewById(R.id.text_points);
        try {
            ss = new StringSetter(this);
            if (getLangFlag() == 0) {
                labelPoints.setVisibility(View.INVISIBLE);
                score.setVisibility(View.INVISIBLE);
            } else {
                score.setText(String.valueOf(getPoints()));
                labelPoints.setText(ss.podesiPromenljivu(brPoena, getLanguage()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 }

This is the log I get:

09-08 17:55:19.317 8848-8848/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.quizme, PID: 8848 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.quizme/com.example.quizme.MainActivity}: java.lang.NullPointerException at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2338) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3930) at android.app.ActivityThread.access$900(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:5292) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824) at com.android.internal.os.ZygoteInit.main(Zygo teInit.java:640) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.NullPointerException at com.example.quizme.MainActivity.onCreate(MainActivity.java:256) at android.app.Activity.performCreate(Activity.java:5264) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2302) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3930) at android.app.ActivityThread.access$900(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:5292) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$M ethodAndArgsCaller.run(ZygoteInit.java:824) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640) at dalvik.system.NativeStart.main(Native Method)

After approximately 16 hours of banging my head against the wall, trying various things (both logical and illogical) and printing logs on every step, I had solved the problem. So here's the solution (I still don't understand why other objects work perfectly without this and these objects require it, but hey, as long as it works I down with it).

if (lqc == null) {
    lqc = new ListenerQuestionChooser(this, this);
}

if (savedInstanceState != null) {
    this.loadSettings(savedInstanceState);
}

if (finQuest == null) {
    try {
        finQuest = findViewById(R.id.btn_finansfer);
        finQuest.setOnClickListener(lqc);
        if (ListenerQuestionChooser.getCorrectAnswer() > 0) {
            finQuest.setVisibility(View.VISIBLE);
        } else {
            finQuest.setVisibility(View.INVISIBLE);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

if (labelPoints == null) {
    labelPoints = findViewById(R.id.total_score);
    score = findViewById(R.id.text_points);
    try {
        ss = new StringSetter(this);
        if (getLangFlag() == 0) {
            labelPoints.setVisibility(View.INVISIBLE);
            score.setVisibility(View.INVISIBLE);
        } else {
            score.setText(String.valueOf(getPoints()));
            labelPoints.setText(ss.podesiPromenljivu(brPoena, getLanguage()));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

This is obviously not the complete source so we can only guess. It looks like the first time you create this activity langFlag is set to 0. After you read it from bundle it must be a different value since you get into the else block. We don't know what is the getPoints - it is mentioned only once in place where you get NPE. So, it looks that getPoints is null but we can't tell why from the code you attached.

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