0

Can someone please explain why scoreTextSwitcher is getting a null error even though I'm checking with if statement? The error is thrown only after starting activity - changing screen orientation - changing screen orientation again - then error occurs...

if(scoreTextSwitcher != null) {
       scoreTextSwitcher.setText(String.valueOf(a));
}

I tried looking for the answer on the links below but couldn't figure out how it relates to my code. If so, can someone please clarify? Many Thanks.


Here is the whole method (not sure if being in a thread mattered)

 private void setScoreTextSwitcher(final int a){
    Thread setScore = new Thread() {
        public void run() {
            if(scoreTextSwitcher == null) {
                scoreTextSwitcher = (TextSwitcher) findViewById(R.id.score_text_switcher);

            }
            GameActivity.this.runOnUiThread(new Runnable() {
                public void run() {
                    if(scoreTextSwitcher != null) {
                        scoreTextSwitcher.setText(String.valueOf(a));
                    }
                }
            });
        }
    };
    setScore.start();
}

Here are the error messages:

08-27 11:02:10.226    2780-2780/com.major.color D/AndroidRuntime﹕ Shutting down VM
08-27 11:02:10.226    2780-2780/com.major.color W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x409961f8)
08-27 11:02:10.247    2780-2780/com.major.color E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NullPointerException
            at android.widget.TextSwitcher.setText(TextSwitcher.java:78)
            at com.major.color.GameActivity$6$1.run(GameActivity.java:600)
            at android.os.Handler.handleCallback(Handler.java:605)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4340)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)

Here is another section of my program that is also getting a null pointer error. I believe it's the same issue because it only occurs when starting and changing the screen orientation back and forth.. Hopefully this second example can help narrow things down a bit.

 private void startCountDownTimer(){
    isTimerOn = true;
    timerTextSwitcher = (TextSwitcher) findViewById(R.id.timer_text_switcher);
    timer = new CountDownTimer(timerCount, 1000) {
        public void onTick(long millisUntilFinished) {
            isTimerOn = true;
            timerCount = millisUntilFinished;

            if ( millisUntilFinished < 10001) {
                TextView TextSwTextView = (TextView) timerTextSwitcher.getChildAt(0);
                TextSwTextView.setTextColor(Color.RED);
                TextSwTextView.setText(String.valueOf(millisUntilFinished / 1000));
            }else
                if(timerTextSwitcher != null){
                    timerTextSwitcher.setText(String.valueOf(millisUntilFinished / 1000));}else {
                    timerTextSwitcher = (TextSwitcher) findViewById(R.id.timer_text_switcher);
                    timerTextSwitcher.setFactory(new ViewSwitcher.ViewFactory() {

                        public View makeView() {
                            // Create a new TextView and set properties
                            TextView textView = new TextView(getApplicationContext());
                            textView.setLayoutParams(new TextSwitcher.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                            textView.setTextSize(17);
                            textView.setTextColor(Color.BLUE);

                            return textView;
                        }
                    });
                    timerTextSwitcher.setText(String.valueOf(millisUntilFinished / 1000));
                }
        }
   public void onFinish() {
            timerTextSwitcher.post(new Runnable() {
                @Override
                public void run() {
                    createToast("GAME OVER!");
                }
            });
            isTimerOn = false;

            saveScore();
            DialogFragment endDialog = new EndGameFragment();
            Dialog = endDialog;
            endgameVisible = true;
            endDialog.show(getSupportFragmentManager(), "EndGameDialogFragment");
        }
    };
    timer.start();
}

Portion of onCreate method displaying how I setup the TextSwitcher for score and Time of activity.

 @Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.activity_game)
//more code...

 timerTextSwitcher = (TextSwitcher) findViewById(R.id.timer_text_switcher);
    timerTextSwitcher.setFactory(new ViewSwitcher.ViewFactory() {

        public View makeView() {
            // Create a new TextView and set properties
            TextView textView = new TextView(getApplicationContext());
            textView.setLayoutParams(new TextSwitcher.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            textView.setTextSize(17);
            textView.setTextColor(Color.BLUE);

            return textView;
        }
    });
    scoreTextSwitcher = (TextSwitcher) findViewById(R.id.score_text_switcher);
    scoreTextSwitcher.setFactory(new ViewSwitcher.ViewFactory() {

        public View makeView() {
            // Create a new TextView and set properties
            TextView textView = new TextView(getApplicationContext());
            textView.setLayoutParams(new TextSwitcher.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            textView.setTextSize(17);
            textView.setTextColor(Color.BLUE);
            textView.setText("0");
            return textView;
        }
    });

    // Declare the animations and initialize them
    Animation in = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
    Animation out = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);

    // set the animation type to textSwitcher
    timerTextSwitcher.setInAnimation(in);
    timerTextSwitcher.setInAnimation(out);
    scoreTextSwitcher.setInAnimation(in);
    scoreTextSwitcher.setInAnimation(out);
}
Community
  • 1
  • 1
cjayem13
  • 903
  • 10
  • 24
  • 2
    Are you sure `a` is not null? and error is not on `String.valueOf(a)`? – MysticMagicϡ Aug 27 '14 at 12:06
  • 1
    Have you checked with some log statements whether your assumpion is correct? – stealthjong Aug 27 '14 at 12:07
  • @Dhruti that's what I thought at first. I changed to 100 for testing and still failed. – cjayem13 Aug 27 '14 at 12:39
  • 1
    A TextSwitcher is a ViewSwitcher used to animate text in and out. Do you want this, or a regular TextView? If you want the Switcher, you need to set it up appropriately. The problem isn't that `scoreTextSwitcher` is null. – Mike M. Aug 27 '14 at 13:06
  • YEs, I would like to animate the text in and out. I setup the view Factory and used setAnimation(in) within my onCreate() method to assign animation changes. I edited my code to show what I did. – cjayem13 Aug 27 '14 at 13:20
  • 1
    Then get rid of the calls to `findViewById()` in `setScoreTextSwitcher()` and `startCountDownTimer()`. They're wiping out all the setup you're doing. – Mike M. Aug 27 '14 at 13:41
  • I believe that's what I had initially but I'll try once more. one sec – cjayem13 Aug 27 '14 at 14:52
  • @ Mike M. That worked. Thank you very much for your assistance. I understand that findviewbyID was wiping the viewfactory data, however, a bit confused on if scoreTextSwitcher is null when activity is recreated. I thought that when screen orinetation changes that activity is completely destroyed and starts over from oncreate-onstart-onresume. I think my confusion lies with static variables and methods and when to release them by setting = to null. I thought it was during onStop or destroy but i'm doing something wrong... anywho, please post your answer so i can accept! :-) Thanks again. – cjayem13 Aug 27 '14 at 17:56
  • 1
    I'm not sure if I'm following you, but you're right in thinking the Activity will be recreated, and `onCreate()` will be called again. You don't need to declare any of your Views as `static`; they will be re-instantiated and re-initialized upon a configuration change. I'll post an answer a little later when I get to a desktop. Thanks! (Btw, when you use @name in a comment, take out all the spaces.) – Mike M. Aug 27 '14 at 18:20

2 Answers2

1

try this

private void setScoreTextSwitcher(final int a){
scoreTextSwitcher = (TextSwitcher) findViewById(R.id.score_text_switcher);
Thread setScore = new Thread() {
    public void run() {
        if(scoreTextSwitcher.isEmpty()) {
            Log.e("","Empty");

        }
        GameActivity.this.runOnUiThread(new Runnable() {
            public void run() {
                if(scoreTextSwitcher != null) {
                    scoreTextSwitcher.setText(String.valueOf(a));
                }
            }
        });
    }
};
setScore.start();

}

raj
  • 2,088
  • 14
  • 23
  • I'm going to be calling the method a lot; is it ok to keep using the findViewById() method? I thought this was time consuming to do. I was hoping to avoid calling it each time I need to change the score and only when null?? – cjayem13 Aug 27 '14 at 12:42
  • I'm still getting the same error. I'm getting a similar one in another section. I edited my post. Also, isEmpty() is a method for TextView, not Text Switcher. – cjayem13 Aug 27 '14 at 13:14
1

The following lines are causing the undesired behavior:

private void startCountDownTimer(){
    ...
    timerTextSwitcher = (TextSwitcher) findViewById(R.id.timer_text_switcher);

and:

private void setScoreTextSwitcher(final int a){
    ...
    scoreTextSwitcher = (TextSwitcher) findViewById(R.id.score_text_switcher);

These calls to findViewById() are re-initializing the Switchers, causing them to lose the Factory and Animation setups you've got in onCreate(), and causing an internal NullPointerException in the setText() method. Since, it appears, the Switchers are declared in the Activity's scope, you just need to remove those lines.

Mike M.
  • 38,532
  • 8
  • 99
  • 95