How can I restart a thread in java/Android from a button? - java

I have a thread in java/Android like this:
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
update_i();
}
};
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Thread myThread = new Thread(new Runnable() {
public void run() {
while (true) {
try {
handler.sendMessage(handler.obtainMessage());
Thread.sleep(timer);
} catch (Throwable t) {
}
}
}
});
myThread.start();
}
The thread works fine when I run my application. But I want to start/restart the thread with a button.
Button.OnClickListener StartButtonOnClickListener = new Button.OnClickListener() {
#Override
public void onClick(View v) {
//start/restart the thread
}
};
If I copy the thread into the button I just make a new thread every time the user clicks on the button. I want to run the thread when the user first time click on the button, "kill it" and start from the beginning if the user click on the button a second time (I don’t want to start a second thread).

I think that Colin is wright you can´t just restart you need to make a new instance, and the interrupt function will stop the running thread if it is still running.
I recommend you make an inner class, instand of an inline implementation, it will make it easier to understand.
if(myThread.isAlive()){
myThread.interrupt();
}
myThread = new MyThread();
myThread.start();
hope this helps

You can't restart a Thread.
From the documentation :
Throws IllegalThreadStateException
if the Thread has been started before
You can kill the previous thread, but in the end you will have to create a second instance of your thread.
Resources :
Javadoc Android - Thread.start()

Related

CountDownTimer not working at all

I am trying to run a CountDownTimer inside a Thread, but it just won't work..
So in the MainActivitys onCreate I start it on Button click like that:
public void onClick(final View v) {
Log.d("Main", "onClick");
runOnUiThread(runner);
}
runner is an Instance of a class which implements Runnable:
private CountDownLatch doneSignal = new CountDownLatch(1);
#Override
public void run() {
Log.d("WR", "run");
this.countDown(20);
Log.d("WR", "waiting");
try {
doneSignal.await();
} catch (final InterruptedException ex) {
Log.e("WR", ex.getMessage(), ex);
}
Log.d("WR", "waited");
}
private void countDown(int time) {
final CountDownTimer timer = new CountDownTimer(time * 1000, 1000) {
#Override
public void onTick(final long millisUntilFinished) {
Log.d("WR", "onTick");
}
#Override
public void onFinish() {
Log.d("WR", "onFinish");
doneSignal.countDown();
}
};
Log.d("WR", "starting");
timer.start();
Log.d("WR", "started");
}
With this code, the application just freezes after Logging onClick, run and starting.
Changing runOnUiThread(runner) to new Thread(runner).start(); makes the application crash immediately after Logging onClick with no more output.
Some research said that the CountDownTimer needs to be run on UI-Thread due to the use of a Handler. But it just freezes.
When I remove the entire Thread stuff and just call runner.run(); in the Buttons onClick (also removing the implements Runnable in the runner Instance) I get following Log entries: onCLick, run, starting, started, waiting. But then nothing happens, as if the timer does not run, no call of the onTick method.
How can I fix my CountDownTimer?
CountDownTimer runs on The Ui Thread, and it has to run on the UI Thread, because internally it uses an Handler, which in turns neead a Looper. runOnUiThread(runner); whatever runner does, runs on the UI Thread.
private CountDownLatch doneSignal = new CountDownLatch(1);
calling await() on the UI Thread will block it, and since the countDown() runs on the same thread you practically dead-locked your app

Run task after 10 seconds, unless user presses button

In my Android app, I want to schedule a task to run in 10 seconds, unless the user presses a specific button.
What is the best way to do this? Should I use a java.util.Timer, java.util.concurrent.ScheduledThreadPoolExecutor or something else?
Thank you in advance.
A handler is fit for this if you are accessing the UI from your task :
Runnable runnable = new Runnable() {
public void run () {
// Do your stuff here
}
}
Handler handler = new Handler();
handler.postDelayed(runnable, 10000);
in your button action :
handler.removeCallbacks(runnable);
Otherwise, a Timer is fine.
and Handler and its postDelayed method
private Runnable requester = new Runnable() {
#Override
public void run() {
// cpde to execute here
}
};
public void onClick(View v) {
new Handler().postDelayed(requester, 10000);
}
You able to use TimerTask and Handler.

Start an Activity from Splash Screen, should I use run() or runOnUiThread()?

I have a Splash Screen (Logo Activity) to show the company name for 3 seconds before app starts. I start Main Activity from a thread, here is the code:
public class Logo extends Activity {
Thread t;
public boolean dead = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.logo);
t = new Thread() {
public void run() {
try {
Intent i = new Intent(Logo.this, Main.class);
Thread.sleep(3000);
if (!dead) {
startActivity(i);
}
finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
}
The Main Activity is called from a worked thread, is this correct? What are the differents with this code (using runOnUiThread)?
...
if (!dead) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent i = new Intent(Logo.this, Main.class);
startActivity(i);
}
});
}
...
I see no difference with this code in debug mode (The same threads, the same operation, etc.). Which is correct?
Starting an intent I think is not an UI operation. runOnUI thread runs UI operation on UI thread. So you can use either of thread (runOnUI or normal). May be normal thread will be good in this situation. But I would like to suggest you use timer instead.
To be honest, I don't like the Thread.sleep. PLease take a look at my solution:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// Do your work here like... startActivity...
}
}, SPLASH_DURATION); // SPLASH_DURATION IS IN MILLISECONDS LIKE 3000
Also you can block the user to prevent the back key like this:
#Override
public void onBackPressed() {
// do nothing! disable user interaction!
}
You should use AsyncTask in "doInBackground" background thread and than sleep your thread(this thread not UIThread) "PostExecute" run on UI Thread than start your new activity
private class mSplashViewer extends AsyncTask<Void,Void,Void>{
protected void doInBackground(Void params){
Thread.currentThread().sleep(3000);
return null;
}
protected void onPostExecute(){
startActivity(...);
}
}

Android - Setting a Timeout for an AsyncTask?

I have an AsyncTask class that I execute that downloads a big list of data from a website.
In the case that the end user has a very slow or spotty data connection at the time of use, I'd like to make the AsyncTask timeout after a period of time. My first approach to this is like so:
MyDownloader downloader = new MyDownloader();
downloader.execute();
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run() {
if ( downloader.getStatus() == AsyncTask.Status.RUNNING )
downloader.cancel(true);
}
}, 30000 );
After starting the AsyncTask, a new handler is started that will cancel the AsyncTask after 30 seconds if it's still running.
Is this a good approach? Or is there something built into AsyncTask that is better suited for this purpose?
Yes, there is AsyncTask.get()
myDownloader.get(30000, TimeUnit.MILLISECONDS);
Note that by calling this in main thread (AKA. UI thread) will block execution, You probably need call it in a separate thread.
Use CountDownTimer Class in side the extended class for AsyncTask in the onPreExecute() method:
Main advantage, the Async monitoring done internally in the class.
public class YouExtendedClass extends AsyncTask<String,Integer,String> {
...
public YouExtendedClass asyncObject; // as CountDownTimer has similar method -> to prevent shadowing
...
#Override
protected void onPreExecute() {
asyncObject = this;
new CountDownTimer(7000, 7000) {
public void onTick(long millisUntilFinished) {
// You can monitor the progress here as well by changing the onTick() time
}
public void onFinish() {
// stop async task if not in progress
if (asyncObject.getStatus() == AsyncTask.Status.RUNNING) {
asyncObject.cancel(false);
// Add any specific task you wish to do as your extended class variable works here as well.
}
}
}.start();
...
change CountDownTimer(7000, 7000) -> CountDownTimer(7000, 1000) for example and it will call onTick() 6 times before calling onFinish(). This is good if you want to add some monitoring.
Thanks for all the good advice I got in this page :-)
In the case, your downloader is based upon an for an URL connection, you have a number of parameters that could help you to define a timeout without complex code:
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setConnectTimeout(15000);
urlc.setReadTimeout(15000);
If you just bring this code into your async task, it is ok.
'Read Timeout' is to test a bad network all along the transfer.
'Connection Timeout' is only called at the beginning to test if the server is up or not.
I don't think there's anything like that built into AsyncTask. Your approach seems to be a good one. Just be sure to periodically check the value of isCancelled() in your AsyncTask's doInBackground method to end this method once the UI thread cancels it.
If you want to avoid using the handler for some reason, you could check System.currentTimeMillis periodically within your AsyncTask and exit on timeout, although I like your solution better since it can actually interrupt the thread.
Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
//async task
final RunTask tsk = new RunTask ();
tsk.execute();
//setting timeout thread for async task
Thread thread1 = new Thread(){
public void run(){
try {
tsk.get(30000, TimeUnit.MILLISECONDS); //set time in milisecond(in this timeout is 30 seconds
} catch (Exception e) {
tsk.cancel(true);
((Activity) mContext).runOnUiThread(new Runnable()
{
#SuppressLint("ShowToast")
public void run()
{
Toast.makeText(mContext, "Time Out.", Toast.LENGTH_LONG).show();
finish(); //will close the current activity comment if you don't want to close current activity.
}
});
}
}
};
thread1.start();
}
You can put one more condition to make cancellation more robust. e.g.,
if (downloader.getStatus() == AsyncTask.Status.RUNNING || downloader.getStatus() == AsyncTask.Status.PENDING)
downloader.cancel(true);
Inspiring from question I have written a method which do some background task via AsyncTask and if processing takes more then LOADING_TIMEOUT then an alert dialogue to retry will appear.
public void loadData()
{
final Load loadUserList=new Load();
loadUserList.execute();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (loadUserList.getStatus() == AsyncTask.Status.RUNNING) {
loadUserList.cancel(true);
pDialog.cancel();
new AlertDialog.Builder(UserList.this)
.setTitle("Error..!")
.setMessage("Sorry you dont have proper net connectivity..!\nCheck your internet settings or retry.")
.setCancelable(false)
.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
loadData();
}
})
.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
System.exit(0);
}
})
.show();
}
}
}, LOADING_TIMEOUT);
return;
}

Queue of runnables for run in other thread Android

that code will help me explain my problem:
public class TestHandlerActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(){
public void run(){
for (int i=0;i<20;i++){
handler.post(run);
}
}
}.start();
}
Handler handler=new Handler(){
};
Runnable run = new Runnable(){
public void run(){
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("TAG", "Message processed");
}
};
}
That way the new thread makes the petitions which are served by the handler in the main thread.
What i need to do is exactly the opposite. The UI thread launches petitions wich are served sequentially by another thread (the order is important), and the UI thread don't need to be notified when each petition end.
Some points are important for this: The petitions have 3 parameters (int, int, boolean), they make changes in the database and are generated by the interaction of the user with the UI, so they aren't launched simultaneously
Thanks in advance
One option is to use this for making your thread: http://developer.android.com/reference/android/os/HandlerThread.html
This will create a thread with its own message queue and loop. You can create a Handler to run work on the thread like so:
HandlerThread handlerThread = new HandlerThread("My Handler");
handlerThread.start();
Handle myHandler = new Handler(handlerThread.getLooper());
This does require that all work done by thread be done so by sending messages and scheduling Runnables on it through Handlers.

Categories