I have a question.
Recently I develop simple "Logging system" for Android.
There is one singleton class which name is "Logger".
protected Logger(){
....
_logHandler = new LogHandler(_logQueue);
_logHandler.start();
....
}
public static Logger getInstance(){
...
}
In "Logger", one thread is running just like below.
#Override
public void run() {
try{
while (isAlive){
execute();
synchronized (lock) {
try {
while (isPaused) {
lock.wait();
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
shutDown();
}
}
}
}catch(InterruptedException e){
e.printStackTrace();
}finally {
shutDown();
}
}
public void requestShutDown(){
isAlive = false;
interrupt();
}
What i want is when application is terminated, I would like to call "requestShutDown()" method to stop thread above.
But i can't find proper moment.
So, Do I have to
When onPause() method executed in Activity, call requestShutDown(). And onResume() method executed in Activity, call thread.start() again?
Is there another way?
Or When Application is terminated, all the resources in application(include thread, Logger class in above) are garbage collected properly?
thanks in advance.
you can create thread like :
Thread th;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
th = new Thread(new Runnable() {
#Override
public void run() {
//do your stuff
}
});
th.run() //to start thread
}
public void requestShutDown(){
if(th.isAlive())
{
th.yield(); //to close thread
}
}
#dwnz Thank you!!
Finally, I call "onDestory()" method in MainActivity. In onDestory(), if isFinishing() of Activity is true, it will be terminated(Of course, this is not "necessary and sufficient condition".)
Related
i'm trying to restart the interrupted thread in onResume (i'm interpreting the thread in onPause). For this i saw lot of examples in online but nothing was helpful (May it's my fault). So,please tell me how to restart interrupted thread in onResume
My code:
private void runThread(){
threadService = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e("Thread", "thread");
if (freshMSgId != null) {
getPrevChatVolleyInThread();
}
}
});
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
threadService.start();
}
#Override
protected void onPause() {
super.onPause();
if (threadService != null) {
threadService.interrupt();
}
}
#npace Thank you, i got the idea from your comment. I restarted the interrupted thread in onResume like
#Override
protected void onResume() {
super.onResume();
runThread();
}
I'm trying to implement a callback method to be called whenever a Thread is is done It's work.
I'm using the interface approach and not the Handler approach.
I have a main UI Thread which is the onCreate(Bundle) method and a Thread i call from within the onCreate(Bundle) method.
(Only relevant code posted).
MainActivity.java:
public class MainActivity extends AppCompatActivity implements GetDataFromTheWebThreadCallback
{
public static GetDataFromTheWebThread getDataFromTheWebThread;
private GetDataFromTheWebEventNotifier eventNotifier;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.eventNotifier = new GetDataFromTheWebEventNotifier(MainActivity.this);
// The thread that will search the web for data
this.getDataFromTheWebThread = new GetDataFromTheWebThread();
getDataFromTheWebThread.start();
}
#Override
public void finishParsing() // The callback method that never called
{
Toast.makeText(MainActivity.this,"Callback Method Called",Toast.LENGTH_LONG).show();
Log.d("Callback:", "Callback Method Called");
}
}
GetDataFromTheWebEventNotifier.java:
public class GetDataFromTheWebEventNotifier
{
private GetDataFromTheWebThreadCallback callbackInterface;
public GetDataFromTheWebEventNotifier(GetDataFromTheWebThreadCallback callbackInterface)
{
this.callbackInterface = callbackInterface;
}
public void onEvent()
{
this.callbackInterface.finishParsing();
}
}
GetDataFromTheWebThreadCallback.java:
public interface GetDataFromTheWebThreadCallback
{
void finishParsing(); // The method i wish to invoke when certain event will happen
}
GetDataFromTheWebThread.java:
public class GetDataFromTheWebThread extends Thread
{
public static boolean isFinished = false; // False - the thread is still running. True - the thread is dead
#Override
public void run()
{
GetDataFromTheWebThread.isFinished = false;
try
{
// Some internet computations...
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
GetDataFromTheWebThread.isFinished = true;
}
}
So what's wrong with my callback?
As for your ThreadClass, have a constructor with the callback :
public class GetDataFromTheWebThread extends Thread {
public static boolean isFinished = false; // False - the thread is still running. True - the thread is dead
private GetDataFromTheWebThreadCallback mCallback;
public GetDataFromTheWebThread(GetDataFromTheWebThreadCallback c) {
mCallback = c;
}
#Override
public void run() {
GetDataFromTheWebThread.isFinished = false;
try {
// Some internet computations...
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
GetDataFromTheWebThread.isFinished = true;
if (mCallback !- null) {
mCallback.finishParsing();
}
}
}
As for your Activity, simply pass the callback when creating your Thread :
this.getDataFromTheWebThread = new GetDataFromTheWebThread(this);
As well as :
#Override
public void finishParsing() {
// You know that this function is called from a background Thread.
// Therefore from here, run what you have to do on the UI Thread
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this,"Callback Method Called",Toast.LENGTH_LONG).show();
Log.d("Callback:", "Callback Method Called");
}});
}
You never call onEvent(). Is your notifier supposed to be watching the isFinished variable or something?
Actually you didn't call onEvent(). And check AsyncTask.
I need a timer which will send a message for its' handler. I've made a class that implements Runnable and I feed its' object to the thread runnable constructor. When I start the thread it hangs application and it obviously isn't working asyncroniously. I could've used AsyncTask but I've also heard that they're designed for short-term operations while my background timer must work throughout activity onResumed state. Would you mind pointing out my mistake and maybe giving useful links on the subject of threads in android. Thanks.
Here's the code I've written:
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
_myTimerInstance = new MyTimer(new Handler() {
#Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
// ...
}
});
_myThread = new Thread(_myTimerInstance);
_myThread.run();
}
private static class MyTimer implements Runnable {
private Handler _myHandler;
private boolean _activityHasBeenLeft;
public MyTimer(Handler myHandler) {
_myHandler = myHandler;
}
public void setActivityHasBeenLeft(boolean b) {
_activityHasBeenLeft = b;
}
#Override
public void run() {
while (!_activityHasBeenLeft) {
try {
Thread.sleep(2000);
_myHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You should always use Thread.start() not Thread.run()
Thread.run() is like a normal method call and is run on the same thread.
use
_myThread.start();
I used some thread objects in my Android activity. But these threads do not stop itself when Activity on destroy. My code for thread-stopping as following:
#Override
public void onDestroy() {
super.onDestroy();
thread.interrupt();
}
Above code is not only working for thread object stopping but also throws an InterruptedException. What's the correct way to stop a running thread without exceptions?
is it not an error when thread object throws InterruptedException?
try this way:
volatile boolean stop = false;
public void run() {
while ( !stop ) {
log.v("Thread", "Thread running..." );
try {
Thread.sleep( 1000 );
} catch ( InterruptedException e ) {
log.v("Thread","Thread interrupted..." );
}
}
}
#Override
public void onDestroy() {
stop = true;
super.onDestroy();
}
and
#Override
public void onDestroy() {
thread.interrupt();
super.onDestroy();
}
trying to stop the thread from outside is not reliable.
I suggest to use global param using SharePreferences or Application Context, ( e.g. IS_APP_ACTIVE ) across your app
and let thread kill itself.
let me try to explain a bit...
in your Activity
protected void onResume() {
super.onResume();
// isAppActive
CommonUtils.setAppActive(mContext, true);
}
protected void onPause() {
super.onPause();
// isAppActive
CommonUtils.setAppActive(mContext, true);
}
in your thread
if ( !CommonUtils.isAppActive(mContext) )
just get out of the thread loop.
I perform this way.
In your activity
#Override
public void onDestroy() {
super.onDestroy();
thread.interrupt();
}
in your Thread
#Override
public void run() {
// stop your thread
if (interrupted()) {
return;
}
// do your work
}
Adding finish(); should end the Activity when onDestroy() or anything else (eg. a button is pressed) is called. When you use onDestroy(), make sure super.onDestroy(); is put after everything else is called.
My service spawns a new thread, and stops it according to the typically recommended java method of interrupt()'ing. When I stop the service, I stop the thread in onDestroy(). The service is stopped, and the interrupt code is reached. However, soon enough the thread restarts from the beginning of the Runnable.
public class DoScan extends Service {
public volatile Thread runner;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
startThread();
}
#Override
public void onDestroy() {
super.onDestroy();
android.util.Log.v("####################", "DoScan.onDestroy");
stopThread();
}
public synchronized void startThread(){
if(runner == null){
android.util.Log.v("####################", "DoScan.startthread");
runner = new Thread(new ScanningThread());
runner.start();
}
}
/* use a handler in a loop cycling through most of oncreate.
* the scanningthread does the work, then notifies the svc's uithread
*/
public synchronized void stopThread(){
if(runner != null){
android.util.Log.v("####################", "DoScan.stopthread");
Thread moribund = runner;
runner = null;
moribund.interrupt();
android.util.Log.v("####################", "interrupted?" + moribund.isInterrupted());
}
}
}
I think the safest way is to have a flag so the thread checks for it inside its main loop.
class ScanningThread extends Thread {
// Must be volatile:
private volatile boolean stop = false;
public void run() {
while (!stop) {
System.out.println("alive");
}
if (stop)
System.out.println("Detected stop");
}
public synchronized void requestStop() {
stop = true;
}
}
public synchronized void startThread(){
if(runner == null){
android.util.Log.v("####################", "DoScan.startthread");
runner = new ScanningThread();
runner.start();
}
}
public synchronized void stopThread(){
if(runner != null){
android.util.Log.v("####################", "DoScan.stopthread");
runner.requestStop();
runner = null;
}
}
The problem is that your thread needs to cooperate by periodically checking for interruption and exiting if the thread has been interrupted. Unless you place something along the lines of the following in your thread...
// Processing...
if ( Thread.interrupted() ){
return;
}
// More processing...
try{
Thread.sleep(sleeptime);
}catch(InterruptedException interrupt){
return;
}
// Rinse and repeat...
...your thread will just ignore the fact that it has been interrupted. The method proposed by Lucas S. is essentially identical, except that using interruption will generate an exception if the thread is blocked, whereas under Lucas S.'s method, you might have to wait indefinitely for the thread to quit.
Interrupting a thread throws an exception in the thread, it does not necessarily stop it. You should catch that exception and then do the clean up in thread before exiting (provided, you need to exit!).