Call outer method from run in TimerTask but doesn't refresh data - android

In Activity I have TimerTask which periodically executes and sometimes call function changeData ( changeData is function in Activity and put new text in text fileds ). Problem is that function changeData when is called doesn't refresh text fields, refresh when I scroll.
I tried with invalidate but doesn't help. Can anybody give me any suggestion ?
private void changeData(String text){
// TextView
txtSemi.setText(text);
}

The ui can only be updated by the UIThread. You can use a Handler inside your timer task.
This blog has a pretty comprehensive tutorial. But basically, you just have to instantiate a Handler outside of your timer task and then, in the timer task you can do:
final String mytext = text;
handler.post(new Runnable() {
#Override
public void run() {
txtSemi.setText(mytext);
}
});

Related

Android postDelayed does not delay

I have the Problem that my Android app does not delay a second (or 10 seconds), if I use the postDelayed method..
Basically I would like my program to wait one second after I clicked the button, then update the text on my textview ("READY"), wait another 2 seconds, then update the textview again ("SET") and then it should start another activity (not yet implemented :-) ).
With my code, the programm starts and after I click the button the textview shows the last text ("SET") immediately.. It just does not wait.
What am i doing wrong?
Here is my code:
public class MyCounterActivity extends Activity {
private long mInternval = 100000;
private Handler mHandler;
private Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
//updateInterval(); //change interval
startRepeatingTask();
}
};
void startRepeatingTask(){
mHandler.postDelayed(mStatusChecker, mInternval);
//mStatusChecker.run();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gym_counter);
final TextView tv1 = (TextView) findViewById(R.id.fullscreen_content);
final Button startButton = (Button) findViewById(R.id.startbutton);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final long up;
EditText textUp = (EditText) findViewById(R.id.editTextUp);
up = Integer.parseInt(textUp.getText().toString());
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//
}
},1000);
Log.d("after 1 runnable", "whaaat");
tv1.setText("Ready");
handler.postDelayed(new Runnable() {
#Override
public void run() {
//
}
}, 2000);
Log.d("after 2nd runnable", "whaaat 2");
//startRepeatingTask();
tv1.setText("SET");
}
});
}
I also tried to run it with the runOnUiThread() (within the onClick(View v) but with with the same result). I expected it to wait 1 second (startRepeatingTask()) and then runs the loop and waits several seconds...
runOnUiThread(new Runnable() {
#Override
public void run() {
startRepeatingTask();
for (int u = 0; u < up; u++){
startRepeatingTask();
}
}
}
});
Hope my description makes sense :-).
Thank you for your help!
EDIT:
I was now able to find a solution for my first problem. The answer from #mad in this post helpded me: How to start a different activity with some delay after pressing a button in android?
(Thats probably the same thing that #laalto tried to tell me. Thanks for the hint!)
In the onClick()
tv1.setText("READY");
mHandler.postDelayed(mDelay1, 2000);
And then the Runnable
private Runnable mDelay1 = new Runnable() {
#Override
public void run() {
if (tv1.getText()=="READY")
tv1.setText("SET");
}
};
BUT:
If i want to refresh the text on my Textview after every second, how do i do that? I cant just call mHandler.postDelayed() several times.. Any help is appreciated.
When you call postDelayed(), it just places the Runnable in a queue and returns immediately. It does not wait for the runnable to be executed.
If you need something to happen after a delay, put the code in the run() method of the runnable.
Whenever you call something like Thread.start(), handler.postDelayed, view.postDelayed, AsynchTask, TimerTask .. you enter the world of threading or you might call it parallel computing.
So there can be multiple threads ("codes") running at the same time.
When you are inside your Activity it is running in a Thread that is calld UI-thread or main thread. All graphics is handled in that thread and that thread alone.
Do NEVER wait in the UI-thread!
Example: you have a button that switches color from say gray to yellow on pressing it. Now you enter a Thread.sleep(10000); - waiting 10 seconds at the start of your onClick.
You will then see that the button stays yellow (=pressed) for 10 seconds even if you only pressed very shortly. Also: if you overdo it android os will become angry and post the user if he wants to force-close your app.
So what happens on handler.postDelayed?
Android will very quickly open a thread that runs in the background parallel to your UI thread. So in some nanoseconds it has done that and will execute the next command in UI thread (in the example above it is Log.d). In the background it will wait and count the millis until time is up. Then any code that is inside the runnable.run method will again be executed in the ui-thread after the wait.
Note also: postDelayed will not be super precise with the wait time as usually the ui-thread is quite buisy and when the wait time is up it may have something else to do. Your runnable code will be added to a queue and executed when ui-thread is ready again. All this happens without you having anything to do about it.
Also:
Remember to work with try/catch inside the runnable.run as many things can happen while waiting - for example user could press Home button closing your app - so the ui-element you wanted to change after the wait could already been destroyed.

Create timer(Handler) when view appears and stop it when view disappears

I have been developing iOS apps for quite a time and now i have switched to android. I have a requirement in which I have to start timer(In think in Android, I need to use handler) when view appears(onResume) and invalidate timer(stop handler) when view disappears(onPause). I am able to create runnable Handler but not able to stop it.
My code is:
protected void AutoRefresh() {
try{
handler.postDelayed(new Runnable() {
public void run() {
new LongOperation().execute("");
}
AutoRefresh();
}, 60000);
}
catch(Exception ex){
}
}
Now, how can I stop this this handler thread when view disappears. Please also comment, if its not the right way to do timer implementation in android.
when view appears(onResume) and invalidate timer(stop handler) when
view disappears(onPause). I am able to create runnable Handler but not
able to stop it.
Keep a reference to the Runnable you use:
private Runnable mRefresh = new Runnable() {
public void run() {
new LongOperation().execute("");
}
AutoRefresh();
}
//...
protected void AutoRefresh() {
handler.postDelayed(mRefresh, 60000);
}
and in onPause remove it like this:
handler.removeCallbacks(mRefresh);
Keep in mind that this will not remove the currently Runnable that is being executed(if any) so in the LongOperation's onPostExecute method you might want to check if the Activity is still available before refreshing the UI or doing any other interaction with the Activity.
Please also comment, if its not the right way to do timer
implementation in android.
You seem to need to do an action at a certain interval of time and using a Handler is the way to do it, I don't think a timer is what you need.

Implementing a while loop in android

I can't understand the implementation of a while loop in android.
Whenever I implement a while loop inside the onCreate() bundle, (code shown below)
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView=(TextView)findViewById(R.id.TextView);
while (testByte == 0)
updateAuto();
}
nothing boots up, and the program enters a "hanging" state after a while and I can't understand why. Testbyte is as follows:
byte testByte == 0;
and updateAuto() is supposed to update the code per 1 second and display inside the textView portion. I've been using setText inside updateAuto() as shown below and everything works fine, but once i implement the while loop all i see is a black screen and then an option to force close after a few seconds due to it "not responding".
TextView.setText(updateWords);
I've changed it to a button format (meaning i have to click on the button to update itself for now), but i want it to update itself instead of manually clicking it.
Am i implementing the while loop in a wrong way?
I've also tried calling the while loop in a seperate function but it still gives me the black screen of nothingness.
I've been reading something about a Handler service... what does it do? Can the Handler service update my TextView in a safer or memory efficient way?
Many thanks if anyone would give some pointers on what i should do on this.
Brace yourself. And try to follow closely, this will be invaluable as a dev.
While loops really should only be implemented in a separate Thread. A separate thread is like a second process running in your app. The reason why it force closed is because you ran the loop in the UI thread, making the UI unable to do anything except for going through that loop. You have to place that loop into the second Thread so the UI Thread can be free to run. When threading, you can't update the GUI unless you are in the UI Thread. Here is how it would be done in this case.
First, you create a Runnable, which will contain the code that loops in it's run method. In that Runnable, you will have to make a second Runnable that posts to the UI thread. For example:
TextView myTextView = (TextView) findViewById(R.id.myTextView); //grab your tv
Runnable myRunnable = new Runnable() {
#Override
public void run() {
while (testByte == 0) {
Thread.sleep(1000); // Waits for 1 second (1000 milliseconds)
String updateWords = updateAuto(); // make updateAuto() return a string
myTextView.post(new Runnable() {
#Override
public void run() {
myTextView.setText(updateWords);
});
}
}
};
Next just create your thread using the Runnable and start it.
Thread myThread = new Thread(myRunnable);
myThread.start();
You should now see your app looping with no force closes.
You can create a new Thread for a while loop.
This code will create a new thread to wait for a boolean value to change its state.
private volatile boolean isClickable = false;
new Thread() {
#Override
public void run() {
super.run();
while (!isClickable) {
// boolean is still false, thread is still running
}
// do your stuff here after the loop is finished
}
}.start();

Update textView from thread

In my OnCreate method I have created a thread that listens to incoming message!
In OnCreate() {
//Some code
myThread = new Thread() {
#Override
public void run() {
receiveMyMessages();
}
};
myThread.start();
// Some code related to sending out by pressing button etc.
}
Then, receiveMyMessage() functions…
Public void receiveMyMessage()
{
//Receive the message and put it in String str;
str = receivedAllTheMessage();
// << here I want to be able to update this str to a textView. But, How?
}
I checked this article but it did not work for me, no luck!
Any updates to the UI in an Android application must happen in the UI thread. If you spawn a thread to do work in the background you must marshal the results back to the UI thread before you touch a View. You can use the Handler class to perform the marshaling:
public class TestActivity extends Activity {
// Handler gets created on the UI-thread
private Handler mHandler = new Handler();
// This gets executed in a non-UI thread:
public void receiveMyMessage() {
final String str = receivedAllTheMessage();
mHandler.post(new Runnable() {
#Override
public void run() {
// This gets executed on the UI thread so it can safely modify Views
mTextView.setText(str);
}
});
}
The AsyncTask class simplifies a lot of the details for you and is also something you could look into. For example, I believe it provides you with a thread pool to help mitigate some of the cost associated with spawning a new thread each time you want to do background work.
Android supports message-passing concurrency using handlers and sendMessage(msg). (It is also possible to use handlers for shared-memory concurrency.) One tip is to call thread.setDaemon(true) if you wish the thread to die when the app dies. The other tip is to have only one handler and use message.what and a switch statement in the message handler to route messages.
Code and Code

How can I refresh the activity?

I want to refresh the activity as i want thatwithout firing any event some work gets performed and activity calls by itself. So, i want to know is there any option in android to refresh the activity by itself.
You can do this by yourself through a Handler on which you call postDelayed(..)
http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable, long)
Put this in your class:
private final Handler handler = new Handler();
make a function called: doTheAutoRefresh() that does:
private void doTheAutoRefresh() {
handler.postDelayed(new Runnable() {
#Override
public void run() {
doRefreshingStuff(); // this is where you put your refresh code
doTheAutoRefresh();
}
}, 1000);
}
Call this function in your onCreate.
NOTE: this is the basic approach. consider stopping this after onPause has been called and to resume it after onResume. Look at the handler class to see how to remove.
You can create a thread and and call the refresh() with the task you want to refresh
for other questions I've pulled the most effective ways to do this are:
finish();startActivity(getIntent());
OR
// Refresh main activity upon close of dialog box
Intent refresh =new Intent(this, ActivityWeAreIn.class);
startActivity(refresh);
Note: this also works with Activity objects or from Fragments using getActivity()

Categories

Resources