1

I am making an app that counts up every second based on rate of pay, and as it is written now, it crashes on startup.

Am I doing the thread section wrong?

I am kind of new to android, so I am a bit unclear on the onCreate method in general. Any clarification about that and how it relates to my code would be helpful as well.

The button is supposed to start the count. I think it's crashing due to the t.start() line, but I don't know how to trigger the event.

package com.example.terik.myapplication;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;


public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView text2;
        text2 = (TextView) findViewById(R.id.textView2);

        Thread t = new Thread() {

            @Override
            public void run() {
                try {
                    while (!isInterrupted()) {
                        Thread.sleep(1000);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                updateTextView();
                            }
                        });
                    }
                } catch (InterruptedException e) {
                }
            }
        };

        t.start();
    }

    private void updateTextView() {
        TextView text2;
        double update;
        double rateofPay = 9.00;
        text2 = (TextView)findViewById(R.id.textView2);
       CharSequence newtime = text2.getText();
        int number = Integer.parseInt(newtime.toString());
        update = number+ rateofPay;
        text2.setText((int) update);

    }




    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
Terik Brunson
  • 187
  • 1
  • 13
  • Please post the stack trace of the crash. – BladeCoder Jul 18 '15 at 01:54
  • Sorry, but how do I get this? I have the logcat but there is nothing in it. – Terik Brunson Jul 18 '15 at 01:54
  • please put `e.printStackTrace();` in the catch block, and update your question with that message it prints in the logcat. – Jay Harris Jul 18 '15 at 02:01
  • Jay, I put that into the code, and ran in debug mode, but the logcat is continuously streaming lines. There are a lot of them. – Terik Brunson Jul 18 '15 at 02:07
  • Thats good, it means its repeating itself like you wanted, the bad part is now you have to find the exact error, remove the while statement so you get one stack trace – Jay Harris Jul 18 '15 at 02:15
  • I also suspect that onCreate is not a good spot to continuously loop your program. – Jay Harris Jul 18 '15 at 02:17
  • Please not that you should not use the Timer class and creating a Thread is absolutely not needed for this. On Android you should use `Handler.postDelayed()` http://developer.android.com/reference/android/os/Handler.html – BladeCoder Jul 18 '15 at 02:22

2 Answers2

2

One problem was a NumberFormatException when trying to parse a Double as an Integer.

The other problem was trying to call setText() with an int on this line:

text2.setText((int) update);

This fixed it:

private void updateTextView() {
    TextView text2;
    double update;
    double rateofPay = 9.00;
    text2 = (TextView)findViewById(R.id.textView2);
    CharSequence newtime = text2.getText();
    double number = Double.parseDouble(newtime.toString());
    update = number+ rateofPay;
    text2.setText(String.valueOf(update));
}

Edit:

Here's how you would only start the Thread when you click the Button. First make the Thread t an instance variable, so that it can be accessed in the button click run() method (you might want to re-name that method too!).

I just tested this, it worked for me:

public class MainActivity extends ActionBarActivity {

    Thread t;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView text2;
        text2 = (TextView) findViewById(R.id.textView2);

        t = new Thread() {

            @Override
            public void run() {
                try {
                    while (!isInterrupted()) {
                        Thread.sleep(1000);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                updateTextView();
                            }
                        });
                    }
                } catch (InterruptedException e) {
                }
            }
        };

    }

    public void run(View v) {
        t.start();
    }

    private void updateTextView() {
        TextView text2;
        double update;
        double rateofPay = 9.00;
        text2 = (TextView)findViewById(R.id.textView2);
        CharSequence newtime = text2.getText();
        double number = Double.parseDouble(newtime.toString());
        update = number+ rateofPay;
        text2.setText(String.valueOf(update));
    }

    //.........

Edit 2:

As @BladeCoder mentioned in the comments, a Thread is really over-kill for this. Using a Handler and postDelayed() is really the best route for something like this.

Also, it would be better to make the TextView an instance variable so that you don't create a new reference every time you update it.

I tested this version as well:

public class MainActivity extends ActionBarActivity {

    TextView text2;
    Handler handler;

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

        text2 = (TextView) findViewById(R.id.textView2);

        handler = new Handler();

    }

    Runnable updateText = new Runnable(){
        @Override
        public void run(){
            updateTextView();
            handler.postDelayed(this, 1000);
        }
    };

    public void run(View v) {
        handler.postDelayed(updateText, 1000);
    }

    private void updateTextView() {

        double update;
        double rateofPay = 9.00;
        CharSequence newtime = text2.getText();
        double number = Double.parseDouble(newtime.toString());
        update = number+ rateofPay;
        text2.setText(String.valueOf(update));
    }

    //.............
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
0

Instead of using thread to achieve this, you can achieve the same effect with a "neat way" using the Timer class.

Check this stackoverflow answer Android timer? How-to?

Regarding the onCreate method I suggest you to check the activity life cycle

Called when the activity is first created. This is where you should do all of your normal static set up: create views, bind data to lists, etc. This method also provides you with a Bundle containing the activity's previously frozen state, if there was one. Always followed by onStart().

Check the documentation for further info http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle)

Community
  • 1
  • 1
msamhoury
  • 333
  • 3
  • 12