to cancel a ongoing operation - android

i have two threads one for downloading and other for displaying data there is a cancel button in layout i want when i click cancel button the downloading thread stops how can i do this
final Thread parseThread=new Thread(new Runnable() {
public void run()
{
count=1;
searchResult.clear();
Log.v("url","++"+"http://wap.vinmonopolet.no/vareutvalg/sok?query="+v.getText());
Log.v("searchText","searchText "+ v.getText());
downloader("http://wap.vinmonopolet.no/vareutvalg/sok?query="+v.getText());
//if(msearchCancel)
}
});
parseThread.start();
Thread displayThread = new Thread(new Runnable() {
public void run() {
try {
if(msearchCancel)
parseThread.interrupt();
else
parseThread.join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
mHandler.post(new Runnable() {
public void run()
{
list_ed=new EfficientAdapter(getApplicationContext());
searchList.setAdapter(list_ed);
progress_waiting1.setVisibility(ProgressBar.GONE);
}
});
}
});
displayThread.start();

First, use AsyncTask for tasks in own threads, it's much easier and handles some low level stuff for you.
Then, in your thread (or background task in AsyncTask), you need periodically to check that main thread requests cancel. In AsyncTask it is isCancelled method.
If you detect cancel request, you exit thread's function ASAP, so that thread may be closed. Otherwise, in case of AsyncTask.cancel, canceling is blocked until background task (thread) gracefully ends.

Related

When i post a long running Runnable to the main thread why isn't it blocked for that time?

If i post a Runnable with Thread.sleep(10000) command, why is the system behaving normally if the UI Thread can only execute one message at a time?
I made this thread in the main activity. Button clicks are processed by the main thread from the MessageQueue, then if the runnable in h.post() is currently active on the main thread then how are the button clicks being processed? shouldn't they wait in the MessageQueue?
new Thread(new Runnable() {
public void run() {
for(int ii=0;ii<9;ii++){
i++;
try
{
Thread.sleep(1000);
h.post(new Runnable(){
#Override
public void run()
{
t();
// TODO: Implement this method
}
});
}
catch (InterruptedException e)
{}
}
}
}).start();
final Runnable r = new Runnable() {
public void run() {
Thread.sleep(10000);
//the thread stoped/sleeped is the thread of Runnable belongs to,
//but not the Main UI thread
}
};
Not block Main UI thred is exactly what Runnable want to achieve.
Aw that was a very trivial question. The inner Runnable is on the main thread while the outer one is time consuming. So the inner Runnable won't block the UI Thread. Thanks!

How to stop background thread, `interupt` not working

Consider this example:
Thread thread = new Thread(new Runnable() {
public void run() {
// Sleep for 5000ms
// Show toast message
}
});
Now I will start this thread on button click in MainActivity and right after that I would exit the activity on back button press, but in overided method onBackPressed following code is implemented:
If(thread != null)
thread.interupt();
finish();
After few seconds toast message is shown, why is that?
interrupt, clears the interrupt status of your thread and will cause the InterruptedException to be thrown. So if your thread is sleepin, and while it is asleep, you call interrupt, it will be woken up, and the execution flow will continue from the instruction that follows the catch block. Assuming you have something really simple like:
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackThreace();
}
runOnUiThread(TOAST);
}
or
public void run() {
while(true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackThreace();
}
runOnUiThread(TOAST);
}
}
both will shown the Toast even though you called interrupt()
While blackbelt has already explained the reason why this happens, here is how you can get around the problem.
The best way to interupt a thread is to use a if-boolean-break method.
So if i were to re-write you code it would be along the following lines
onBackPressed:
isBackPressed = true;
inside the thread's run method:
Thread thread = new Thread(new Runnable() {
public void run() {
// Sleep for 5000ms
if(!isBackPressed){
// Show toast message
}
}
});

Correct way to run a continuously called method in own thread?

I'm calling methode doSomething() continuously with a thread.sleep(100). This happens in on the UIThread, so the UIthread gets unresponsive. What is the correct way in Android to run the method doSomething() or the entire someobject in a seperate thread?
public void loop(){
while(true){
someObject.doSomething();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Right now i'm using
new Thread(new Runnable() {
#Override
public void run() {
someObject.doSomething();
}
}).start();
This obviously creates a different thread for each iteration. I don't think this is the correct way. What is the correct way in Android?
new Thread(new Runnable() {
#Override
public void run() {
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
someObject.doSomething();
}
}
}).start();
Since run never returns, the thread will never end and will loop forever. It will call doSomething roughly every 100 ms (as close as sleep will get, which isn't exact).
You can make your own Thread class, with Looper and Handler, posting your doSomething every 100ms:
public class MyThread extends Thread{
private Handler myHandler;
#Override
public void run(){
Looper.prepare();
myHandler = new Handler();
myHandler.post(doSomethingRunnable);
}
Runnable doSomethingRunnable = new Runnnable{
doSomething(); //or myHandler.postDelayed() first for greater accuracy, but only if doSomething doesnt take too long
myHandler.postDelayed(doSomethingRunnable, 100);
};
doSomething(){
thisStuff(thatStuff());
}
}
You can use AsyncTask. doInBackground() is called on a background thread and will not block UI. This is the preferred way for doing stuff on background threads.
For a long running task. You can use an IntentService and put your background code in onHandleIntent
You can use a basic thread but it may be hard to manage. You can read more about threads in android here

Repeat task while activity is open

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();

How do you loop a thread?

I have a thread containing a runnable.
I need this to loop infinitely unless cancelled by the user.
I have no idea how to go about this. All help is greatly appreciated.
Cheers.
I need this to loop infinitely unless cancelled by the user.
Obviously you can easily add a loop inside of your run() method:
new Thread(new Runnable() {
public void run() {
while (true) {
// do something in the loop
}
}
}).start();
It's always a good idea to check for thread interruption:
new Thread(new Runnable() {
public void run() {
// loop until the thread is interrupted
while (!Thread.currentThread().isInterrupted()) {
// do something in the loop
}
}
}).start();
If you are asking about how you can cancel a thread operation from another thread (such as a UI thread) then you can do something like this:
private final volatile running = true;
...
new Thread(new Runnable() {
public void run() {
while (running) {
// do something in the loop
}
}
}).start();
...
// later, in another thread, you can shut it down by setting running to false
running = false;
We need to use a volatile boolean so that changes to the field in one thread are seen in the other thread.

Categories

Resources