Calling FindViewById from Handler thread - NullPointerException - java

So, I am trying to implement a simple timer in my application wherein I increment the MM:SS display every one second.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
handler = new Handler();
Runnable runnable = new GameActivity();
handler.postDelayed(runnable, 5000); //Start Incrementing timer after 5s.
}
#Override
public void run() {
// TODO Auto-generated method stub
TextView timeView = (TextView)findViewById(R.id.textView1);
String time = (String) timeView.getText();
if (TimerUtilities.convertMSToSeconds(time) < R.integer.TimeLimit)
{
time = TimerUtilities.incrementOne(time);
timeView.setText(time);
timeView.postInvalidate();
handler.postDelayed(new GameActivity(), 1000);
}
else
{
time = TimerUtilities.incrementOne(time);
timeView.setText(time);
}
}
When I looked at the logcat output - I am getting a null pointer exception in the findViewById line of the overridden run method.
So could the problem because of reading/updating UI from the handler thread. If so, is there an alternative way for me to do this ?

The run method is being called on the new GameActivity that you created. The setContentView method never gets called on it so it doesn't have any views. You probably wanted to call
handler.postDelayed(this, 5000);
instead of creating a new activity.

Related

Problems in running handlers?

I am trying to call my takepicture() method after every 1 minute. So, I tried using the handler class and then tried calling my method within its run function. However, when I tried doing a step wise debugging, it never enters the run method at all. Can anyone please suggest me what I am doing wrong? I am trying to call it from my fragment.
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mFile = new File(getActivity().getExternalFilesDir(null), "pic.jpg");
final Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
Log.d("HandlerThread","This is from the HandlerThread");
takePicture();
handler.postDelayed(this, 60000);
}
};
}
Try this:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mFile = new File(getActivity().getExternalFilesDir(null), "pic.jpg");
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Log.d("HandlerThread","This is from the HandlerThread");
takePicture();
}
}, 60000);
}
Rather than defining the handler.postDelayed within run method.I have just changed the call within your main thread itself.
Kindly mark it as answer if it solves your problem.
You never call any method that would run the Runnable. You only specified its behavior inside the run() function.
In order to start the Runnable, call something like handler.postDelayed(r, 0);
Just an info: please note that your Handler is still tied to the main Thread. See this answer and this one if you want to run it on a separate thread.
You should make an initial call to start the handler functionality.
ie , handler.post(r);

How to make app wait and then start activity or go back?

I want my activity to show a screen for 3 seconds, then go back to previous screen. But when i use
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.welcome_layout);
TextView tvResult = (TextView)findViewById(R.id.textView1)
Thread.sleep(3000);
Intent i = new Intent(this,myActivity.class);
startActivity(i);
But unfortunately, this does not work. This doesent show the activity waits 3 seconds and goes back. However, i want it to show its contents before going back. How can i do it ?
You should remove this Thread.sleep(3000); which block the ui thread. You should never block the ui thred. You can use a Handler postDelayed with a delay and then startActivtiy.
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
#Override
public void run(){
// do something
}
}, 3000);
To go back to previous Activity you can call finish().
Also if you need to go back to the previous activity for 3 seconds why do you need
Intent i = new Intent(this,myActivity.class);
startActivity(i);
Calling finish() will do the job
This is not the recommended way to do this.
Using Thread.sleep you're blocking the main UI thread for 3000 milliseconds. This means that nothing in the activity will work until 3 seconds are passed.
Instead, you could do this:
edited: now it works well.
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.welcome_layout);
TextView tvResult = (TextView)findViewById(R.id.textView1)
new Thread(new Runnable()
{
#Override
public void run()
{
try
{
Thread.sleep(3000);
Intent i = new Intent(getApplicationContext(), myActivity.class);
startActivity(i);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}

How to display some text in TextView for a specified amount of time?

I have developed an android application which extracts single line text messages from the server. Once a button is clicked, it makes a function call which gets the next message from the server. Some of those messages are time based,
i.e those messages have to be displayed in the TextView for a particular amount of time and after that time is elapsed, it should automatically make the function call to get the next message from the server(i.e without the button being clicked).
Could someone please help me out in achieving this.
I tried using while loop as follows:
while(!presentTime.equals(expiryTime)){
calculatePresentTym(); //This method calculates the presentTime value
display.settext(the received instruction);
}
if(presentTime.equals(expiryTime))
(make the function call)
If I do this, nothing is being displayed till presentTime and expiryTime are equal. Once they are equal, the next instruction is automatically fetched by the function call and is displayed in the TextView.
Use a a handler
Handler m_handler;
Runnable m_handlerTask ;
m_handler = new Handler();
#Override
public void run() {
// do something
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
T0 cancel the run
m_handler.removeCallbacks(m_handlerTask); // to cancel the run
You can also use a timer but you will have to use runOnUiThread to update ui since timer runs on a different thread.
Timer _t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
//do something
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
//update ui
}
});
}
}, 1000, 1000 );
Note:
gets the next message from the server
Getting the message from server should be done on a background thread.
Edit:
While copy pasting the initialization part was missing. You have a counter i that is displayed in the textview. The counter increases by 1 every second. When it reaches 100 you cancel the run. Modify the below according to your requirements.
public class MainActivity extends Activity {
TextView tv;
Handler m_handler;
Runnable m_handlerTask ;
int i=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView1);
m_handler = new Handler();
m_handlerTask = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if(i<=100)
{
tv.setText(""+i);
i++;
}
else
{
m_handler.removeCallbacks(m_handlerTask);
}
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
}
}
Use a timer. Schedule the timer for repeated interval executions, and after each execution you can get the next text from the server and display the same.
Check the Timer reference scheduleAtFixedRate(TimerTask task, long delay, long period)

Make this function repeat using runOnUiThread to update textview location

I trying to make my textView appear in different place of the screen every minute or two (delay is not important). I've seen people are suggesting I use runOnUiThread to make a timer repeat the random function and the update the UI.
I'm really struggling getting my head around these different threads, just wondering if anyone could give me an example? Or should I research using something different?
Public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.digitalClock1);
Random r = new Random();
int x = r.nextInt(350 - 100);
int y = r.nextInt(800 - 100);
textView.setX(x);
textView.setY(y);
}
Try this method
public void doInback()
{
handler.postDelayed(new Runnable() {
#Override
public void run()
{
// TODO Auto-generated method stub
// Try the code that you want to repeat
doInback();
}
}, 1000);
}
just call the method where you want to use.
Create the runnable and the handler below
private Runnable runnable = new Runnable(){
#Override
public void run() {
handler.sendEmptyMessage(0);
}
};
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//change the text position here
this.postDelayed(runnable , TIME_OUT_MS);
}
};
The TIME_OUT_MS is the time out you want in milliseconds.
And put this on the OnCreate() method of the activity
Thread thread =new Thread(runnable );
thread.start();

Why the thread behaves this way in my example?

Can someone explain to me 2 things about the thread code that I finally made almost working the way it should. I want to do a periodic task in the background every x seconds and be able to stop and start it at will. I coded that based on the examples I found, but I'm not sure if I made it in the right way. For the purpose of debugging, the task is displaying a time with custom showTime().
public class LoopExampleActivity extends Activity {
TextView Napis, Napis2;
Button button1,button_start,button_stop;
Handler handler = new Handler();
Boolean tread1_running = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Napis = (TextView) findViewById(R.id.textView1);
Napis2 = (TextView) findViewById(R.id.textView2);
button1 = (Button) findViewById(R.id.button1);
button_stop = (Button) findViewById(R.id.button_stop);
button_start = (Button) findViewById(R.id.button_start);
button_stop.setOnClickListener(new OnClickListener() {
#Override
public void onClick (View v) {
tread1_running = false;
}
});
button_start.setOnClickListener(new OnClickListener() {
#Override
public void onClick (View v) {
tread1_running = true;
}
});
thread.start();
}// endof onCreate
final Runnable r = new Runnable()
{
public void run()
{
handler.postDelayed(this, 1000);
showTime(Napis2);
}
};
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(tread1_running) {
sleep(1000);
handler.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
Now the questions are:
1)Will my thread quit forever if I stop it with the stop button?
2)Why can't I start it again with the start_button? If I add the tread.start() in a button, will it crash?
3) I tried a second version when I let the thread run and put a condition into the handler. The only way I can get it to work is to loop conditionaly in the handler by adding an
if (thread1_running) {
handler.postDelayed(this, 2000);
showTime(Napis2);
}
And changing the condition in a thread start to while (true) but then I have an open thread that is running all the time and I start and stop it in a handler, and it posts more and more handlers.
So, finally I get to the point it looks like that:
final Runnable r = new Runnable()
{
public void run()
{
if (thread1_running) handler.postDelayed(this, 1000);
showTime(Napis2);
}
};
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
if (thread1_running) handler.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Is the proper way to do that is to start and stop a whole thread? Or that is the best way?
The best way to achieve something like that would be, in my humble opinion, to postDelayed(Runnable, long).
You could do something like this. Class definition:
private Handler mMessageHandler = new Handler();
private Runnable mUpdaterRunnable = new Runnable() {
public void run() {
doStuff();
showTime(Napis2);
mMessageHandler.postDelayed(mUpdaterRunnable, 1000);
}
};
And control true run/stop like this:
To start:
mMessageHandler.postDelayed(mUpdaterRunnable, 1000);
And to stop:
mMessageHandler.removeCallbacks(mUpdaterRunnable);
It's much much simpler, in my humble opinion.
Threads a described by a state machine in java.
When a thread get outs of its run method, it enters in the stopped state and can't be restarted.
You should always stop a thread by getting it out of its run method as you do, it s the proper way to do it.
If you want to "restart the thread", start a new instance of your thread class.
You should better encapsulate your thread and its running field. It should be inside your thread class and the class should offer a public method to swich the boolean. No one cares about your datastructure, hide them. :)
You should consider using runOnUIThread for your runnable, its much easier to use than handlers.

Categories

Resources