-1

I have created a timer in a different class to Main activity. When I run the code I get the following error:

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.os.Handler.postDelayed(java.lang.Runnable, long)' on a null object reference

Researching it is suggests that the handler is not initialised however in my code it is (if I use that code in the mainactivity thread it works fine)

Can anyone provide any pointers as to where Im going wrong?

Main Activity:

public class MainActivity extends AppCompatActivity {

private ListView listView;
TextView timertxt; //this
public static TextView hourtext;//this2
int time; //this




@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    timertxt = (TextView) findViewById(R.id.timertxt);//this
    hourtext = (TextView) findViewById(R.id.SessionTimerTxt);//this 2
    final Timer timer;



    final Button generate = (Button) findViewById(R.id.Generate);
    generate.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            DatabaseAccess myDatabaseHelper = new    DatabaseAccess(MainActivity.this);
            myDatabaseHelper.open();
            Cursor d = myDatabaseHelper.getRProgram();
            if (d.moveToFirst()) ;
            DisplayProgram(d);

            myDatabaseHelper.close();

            Timer timer = new Timer();
            timer.count();
            //the abpove two lines r causing it to crash prob cos timer class is trying to change text on UI


        }

        public void DisplayProgram(Cursor d) {
            TextView result2 = (TextView) findViewById(R.id.result2);
            result2.setText("\n" + d.getString(1)+ " " + (d.getLong(2)*1000));
            time = (d.getInt(2)*1000);


            TextView dbtime = (TextView) findViewById(R.id.dbtimeproof);
            dbtime.setText (String.valueOf (time));

            final MyCount counter = new MyCount(time,1000);//this
            counter.start();

            Button TButton = (Button) findViewById(R.id.tbutton);
            TButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    //counter.start();

                }
            });

        }

    });

}


// count down timer is an abstract class, so extend it and fill in methods
public class MyCount extends CountDownTimer {  //all below here

    public MyCount(long millisInFuture, long countDownInterval) {
        super(millisInFuture, countDownInterval);
    }

    @Override
    public void onFinish() {
        // it's done
        timertxt.setText("Done!");


    }

    @Override
    public void onTick(long millisUntilFinished) {
        timertxt.setText("Left: " + millisUntilFinished / 1000);

        final String ifvaluest = timertxt.getText().toString();

        //if hour timer is greater than 1 sec then process below else skip below

        if (ifvaluest.equals("Left: 1")){


            DatabaseAccess myDatabaseHelper = new    DatabaseAccess(MainActivity.this);
            myDatabaseHelper.open();
            Cursor d = myDatabaseHelper.getRProgram();
            if (d.moveToFirst()) ;
            DisplayProgram(d);

            myDatabaseHelper.close();}}

        public void DisplayProgram(Cursor d) {
            TextView result2 = (TextView) findViewById(R.id.result2);
            result2.setText("\n" + d.getString(1)+ " " + (d.getLong(2)*1000));
            time = (d.getInt(2)*1000);


            TextView dbtime = (TextView) findViewById(R.id.dbtimeproof);
            dbtime.setText (String.valueOf (time));

            final MyCount counter = new MyCount(time,1000);//this
            counter.start();



        }
    }


}

Heres the Timer Class:

public class Timer extends AppCompatActivity {

//TextView hourtext;
private int elapsedTime;// used to hold elapsed time
public Handler handler;
private int interval = 60000;//millisecs count





@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //hourtext = (TextView) findViewById(R.id.SessionTimerTxt);
    elapsedTime = 0;
    handler = new Handler();//initialise the handler
    count();



}//starts the count


    public void count () {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {


        elapsedTime++; //increase the counter
        MainActivity.hourtext.setText(String.valueOf(elapsedTime));
        handler.postDelayed(runnable, interval); // call the runnable
            }
        });


}//ends of the count section

// Runnable - calls the count() function to continue the sequence
private Runnable runnable = new Runnable() {
    @Override
    public void run() {
        count();
    }
}; //end runnable section



} //end of class
Matmajot
  • 19
  • 1
  • 8

2 Answers2

1

Just had a brainwave! Its because I didnt instantiate the handler within the runonui. So to get it working I just added the following code ABOVE elapsedtime++

handler = new Handler();

Matmajot
  • 19
  • 1
  • 8
0

You dont need to extend AppCompatActivity

 public class Timer {
 //TextView hourtext;
 private int elapsedTime; // used to hold elapsed time
 public Handler handler;
 private int interval = 60000; //millisecs count
 private Context ctx;
 Timer(context contxt) {
  ctx = contxt;
 }

 public void count() {
   elapsedTime = 0;
   handler = new Handler(); //initialise the handler
   count();

   ((Activity) ctx).runOnUiThread(new Runnable() {
    @Override
    public void run() {


     elapsedTime++; //increase the counter
     MainActivity.hourtext.setText(String.valueOf(elapsedTime));
     handler.postDelayed(runnable, interval); // call the runnable
    }
   });


  } //ends of the count section

 // Runnable - calls the count() function to continue the sequence
 private Runnable runnable = new Runnable() {
  @Override
  public void run() {
   count();
  }
 }; //end runnable section



} //end of class

your MainActivity.java as

public class MainActivity extends AppCompatActivity {

 private ListView listView;
 TextView timertxt; //this
 public static TextView hourtext; //this2
 int time; //this




 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  timertxt = (TextView) findViewById(R.id.timertxt); //this
  hourtext = (TextView) findViewById(R.id.SessionTimerTxt); //this 2
  final Timer timer;



  final Button generate = (Button) findViewById(R.id.Generate);
  generate.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    DatabaseAccess myDatabaseHelper = new DatabaseAccess(MainActivity.this);
    myDatabaseHelper.open();
    Cursor d = myDatabaseHelper.getRProgram();
    if (d.moveToFirst());
    DisplayProgram(d);

    myDatabaseHelper.close();

    Timer timer = new Timer(MainActivity.this);
    timer.count();
    //the above two lines r causing it to crash prob cos timer class is trying to change text on UI


   }

   public void DisplayProgram(Cursor d) {
    TextView result2 = (TextView) findViewById(R.id.result2);
    result2.setText("\n" + d.getString(1) + " " + (d.getLong(2) * 1000));
    time = (d.getInt(2) * 1000);


    TextView dbtime = (TextView) findViewById(R.id.dbtimeproof);
    dbtime.setText(String.valueOf(time));

    final MyCount counter = new MyCount(time, 1000); //this
    counter.start();

    Button TButton = (Button) findViewById(R.id.tbutton);
    TButton.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {

      //counter.start();

     }
    });

   }

  });

 }


 // count down timer is an abstract class, so extend it and fill in methods
 public class MyCount extends CountDownTimer { //all below here

  public MyCount(long millisInFuture, long countDownInterval) {
   super(millisInFuture, countDownInterval);
  }

  @Override
  public void onFinish() {
   // it's done
   timertxt.setText("Done!");


  }

  @Override
  public void onTick(long millisUntilFinished) {
   timertxt.setText("Left: " + millisUntilFinished / 1000);

   final String ifvaluest = timertxt.getText().toString();

   //if hour timer is greater than 1 sec then process below else skip below

   if (ifvaluest.equals("Left: 1")) {


    DatabaseAccess myDatabaseHelper = new DatabaseAccess(MainActivity.this);
    myDatabaseHelper.open();
    Cursor d = myDatabaseHelper.getRProgram();
    if (d.moveToFirst());
    DisplayProgram(d);

    myDatabaseHelper.close();
   }
  }

  public void DisplayProgram(Cursor d) {
   TextView result2 = (TextView) findViewById(R.id.result2);
   result2.setText("\n" + d.getString(1) + " " + (d.getLong(2) * 1000));
   time = (d.getInt(2) * 1000);


   TextView dbtime = (TextView) findViewById(R.id.dbtimeproof);
   dbtime.setText(String.valueOf(time));

   final MyCount counter = new MyCount(time, 1000); //this
   counter.start();



  }
 }


}
and-lab
  • 41
  • 2
  • thanks for the reply. I tried your code and it compiled fine (although there was a typo with context, I changed it to a Context and it took it. When running it in the emulator it crashed with the following error "Process: com.example.mat.shaolinwarriordbimport10, PID: 2561 java.lang.StackOverflowError: stack size 8MB" – Matmajot Mar 02 '17 at 20:02
  • http://stackoverflow.com/questions/214741/what-is-a-stackoverflowerror Read there – and-lab Mar 03 '17 at 05:32