In the below code, outside is printed before inside. I want the order to be inside first and then outside. So how do I ensure that the Runnable is finished before the second Log is reached?
webView.post(new Runnable() {
#Override
public void run() {
Log.d("check", "inside");
}
});
// some code needed here
Log.d("check", "outside");
Some code must be inserted where to comment is to achieve this.
EDIT: I am doing all the work in a background service.
[P.S.: Those who are curious as to why I am doing this, it is so because unless I add the webview.post, I keep getting the following error: "All WebView methods must be called on the same thread.". Anyway, this shouldn't affect you from answering the question.]
You might try using a CountDownLatch:
final CountDownLatch latch = new CountDownLatch(1);
webView.post(new Runnable() {
#Override
public void run() {
Log.d("check", "inside");
latch.countDown();
}
});
// some code needed here
latch.await();
Log.d("check", "outside");
However, you wouldn't want to use latch.await() on the UI thread, as that's a blocking method. If you wanted to run this on the UI thread it would be best to replace latch.countDown() with a call to a callback method, which would in turn run Log.d("check", "outside").
Related
I want perform a network call in every 30sec to push some metrics to Server. Currently I am doing it using thread.sleep(). I found some articles saying thread.sleep() has some drawbacks. I need to know am I doing it right? or Replacing the thread with Handler will improve my code?
public static void startSending(final Context con) {
if (running) return;
running = true;
threadToSendUXMetrics = new Thread(new Runnable() {
#Override
public void run() {
do {
try {
Thread.sleep(AugmedixConstants.glassLogsPushInterval);
} catch (InterruptedException e) {
mLogger.error(interrupt_exception + e.getMessage());
}
// to do to send each time, should have some sleep code
if (AugmedixConstants.WEBAPP_URL.equals(AugmedixConstants.EMPTY_STRING)||!StatsNetworkChecker.checkIsConnected(con)) {
Utility.populateNetworkStat();
mLogger.error(may_be_provider_not_login_yet);
} else
sendUXMetrics();
} while (running);
if (!uxMetricsQueue.isEmpty()) sendUXMetrics();
}
});
threadToSendUXMetrics.start();
}
If You are using only one thread in the network, then usage of the thread.sleep() is fine. If there are multiple threads in synchronization, then the thread.sleep() command will block all the other threads that are currently running.
As per the details you've provided, there is only one thread present which isn't blocking any other active threads which are running in synchronization, so using thread.sleep() shouldn't be a problem.
Use Handler.postDelayed to schedule tasks if you are working in UI Thread and Thread.sleep if you are working in background thread.
Apparently you are sending some data using network, you must do it in the background thread, hence Thread.sleep is recommended.
Simple is:
Thread.sleep(millisSeconds): With this method, you only can call in background tasks, for example in AsyncTask::doInBackground(), you can call to delay actions after that. RECOMMENDED CALL THIS METHOD IN BACKGROUND THREAD.
Handler().postDelayed({METHOD}, millisSeconds): With this instance, METHOD will trigged after millisSeconds declared.
But, to easy handle life cycle of Handler(), you need to declare a Handler() instance, with a Runnable instance. For example, when your Activity has paused or you just no need call that method again, you can remove callback from Handler(). Below is example:
public class MainActivity extends Activity {
private Handler mHandler = Handler();
public void onStart(...) {
super.onStart(...)
this.mHandler.postDelayed(this.foo, 1000)
}
public void onPaused(...) {
this.mHandler.removeCallback(this.foo)
super.onPaused(...)
}
private Runnable foo = new Runnable() {
#Override
public void run() {
// your code will call after 1 second when activity start
// end remove callback when activity paused
// continue call...
mHandler.postDelayed(foo, 1000)
}
}
}
The code above just for reference, I type by hand because don't have IDE to write then copy paste.
i want to repeat task while the activity is open.
For example repeat foo() every minute while the activity is open.
I tought about Timer, handler and runable.
I tought about this code:
Maybe there is some better way?
public void setRefreshRate()
{
newTimer = true
while(true)
{
if(newTimer)
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if(isNetworkAvailable() && movedToAnotherActivity== false)
new GetWorkouts().execute();
newTimer = true;
}
}, Integer.getInteger(data.getWallRefresh()));
newTimer = false;
}
}
There may be a better way but I like AsyncTask so I would probably use that and call sleep() in doInBackground() then you can call cancel() on your task object and set it to null when the Activity finishes.
public void doInBackground(Void...params)
{
boolean flag = false;
while (!flag)
{
// do some work
Thread.sleep(6000);
}
}
then overide and set flag to true in onBackPressed() and finish(). You can then use any of the other AsyncTask methods to update the UI if necessary.
AsyncTask
Thanks to codeMagic's answer for starting me down the right path, but AsyncTask isn't really designed for this. From the docs:
AsyncTasks should ideally be used for short operations (a few seconds at the most.)
The problem is that AsyncTasks, at least by default, run sequentially on the same worker thread, so if you try to launch another AsyncTask, it won't be able to run, since the timer loop never finishes.
To work around this, I just used a raw Thread and it's working fine.
apiUpdateTimerThread = new Thread(new Runnable() {
#Override
public void run() {
while(true) {
try {
Log.i(TAG, "UPDATE FROM THE API!!!!");
doSomeStuff();
Thread.sleep(5 * 1000);
} catch(InterruptedException e) {
Log.e(TAG, "API Update AsyncTask Interrupted", e);
}
}
}
});
To stop it, just call
apiUpdateTimerThread.interrupt();
I think this is a beginner (me) question, then for you guys is easy to answer.
I have this method:
public void onQuantityTextChange(final int value)
{
new Thread(new Runnable() {
public void run() {
addProductToCart(value);
view.post(new Runnable() {
public void run() {
updateTotals();
}
});
}
}).start();
}
My question is: this peace of code:
view.post(new Runnable() {
public void run() {
updateTotals();
}
is executed only when this addProductToCart(value); method is executed(finished)? or is it more safe to use AsyncTasks with doInBackground() and onPostExecute()?
It is always executed after: addProductToCart(value);
But if that function starts a Thread or AsyncThread or similar then the function will return before that task finishes.
To summarize: nobody can answer without the contents of addProductToCart
That largely depends on whether or not your method addProductToCart(value) starts another thread of its own. If it does, then there's no guarantee as the thread will start and finish as the system sees fit. If not, then you will not call view.post(...) until that thread is complete.
Another thing to watch out for depending on what you're trying to accomplish is the method inside view.post(...) is not guaranteed to run immediately. What this method does is put Runnable objects inside a message queue. This means, this runnable won't execute until the other elements in the message queue execute first. Secondly, the message queue can run at any time meaning even if this is the first Runnable in the queue it will start eventually, but not necessarily immediately.
I am new to android i am trying to create a new thread to invoke another method.
But don't why it is throwing the error.
here is my stub
void test()
{
int i=0;
Toast.makeText(getApplicationContext(), "Testing", Toast.LENGTH_SHORT).show();
}
public void Button2_Click(View v)
{
Thread thread = new Thread()
{
#Override
public void run() {
test();
}
};
thread.start();
}
You can't manipulate the UI from other threads than the main thread, and launching a Toast involves the user interface.
change your test function
void test()
{
int i=0;
Log.d("Test","Testing");
}
now if the thread works you will se a log inside LogCat. If you want to display a Toast from another thread, you must use Handler or runOnUiThread.
Do this is Handler
like this http://www.tutorialforandroid.com/2009/01/using-handler-in-android.html
you can not put Toast inside a Thread. Remove your Toast message from your code. It will work fine.
This is how you can do it.
`new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
}).start();
'
Its a bracket mismatch.
If you absolutely must Toast, you should use the runOnUIThread() method and pass it a new Runnable() anonymous class that Toasts in the run() method.
Irrelevantly, this doesn't seem to make a whole lot of sense. Perhaps you want to make test() static. Maybe post a better idea of what you'd like to do and exactly what error you're getting?
In My application I want to check data after every second, using service.
I have tried to use Timer but it doesn't allow me to use 'runOnUiThread' in service.
In Activity Timer works fine.
or
Is there any other way to trace database at every seconds?
Implement a Runnable, that way you can use the runOnUiThread(runnable) functionality.
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
//do ui update
}
};
Edit: try this: More efficient way of updating UI from Service than intents?
Edit2: http://developer.android.com/resources/articles/timed-ui-updates.html
Use thread u can trace the data base every time
try{
thread=new Thread()
{
#Override
public void run() {
while(set) {
thread_Run();
}
}
};
}
catch(Exception e)
{
Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
}