0

I was making an Android app (min SDK : 8, target SDK : 19)

now I want to set a loading icon to appear at the start until the application checks internet cennectivity

until now I have no problem

I had this method do it for me :

void setLoader(boolean T, String msg){
    View LAY = findViewById(R.id.loaderLayout);
    TextView MTV = (TextView) findViewById(R.id.loader_msg);
    if(T && !loaderStarted){
        loader.start();
        LAY.setVisibility(View.VISIBLE);
        MTV.setText(msg);
        loaderStarted = true;
    }
    else if (!T && loaderStarted) {
        loader.interrupt();
        LAY.setVisibility(View.GONE);
        loaderStarted = false;
    }
}

Then I needed to get user&pass then lock the UI with that thread again to check user&pass The problem is : I have problem pausing a thread :| my primary programming language isn't java

so please help me with this I have the Thread like this :

//first make loading icon visible then call :

    final private Thread loader = new Thread(new Runnable(){

    @Override
    public void run() {
        int i = 0;
        while (true){
            if(loader.isInterrupted()){
                return;
                }
            try {Thread.sleep(25);} catch (InterruptedException e) {}
            final int j = i;
            runOnUiThread(new Runnable(){
                public void run() {
                    ImageView imageView = (ImageView) findViewById(R.id.loaderImage);
                    Matrix matrix = new Matrix();
                    imageView.setScaleType(ScaleType.MATRIX);
                    int newWIDTH = imageView.getWidth();
                    int newHIEGHT = imageView.getHeight();
                    matrix.postScale(((float)(newWIDTH))/imageView.getDrawable().getBounds().width(), ((float)(newHIEGHT))/imageView.getDrawable().getBounds().height());
                    matrix.postRotate((float) j, newWIDTH/2, newHIEGHT/2);
                    imageView.setImageMatrix(matrix);
                }   
            });
            i = (i + 15) % 360;
        }
    }
});

then I need a method like this :

void setLoader(boolean T, String msg){
    View LAY = findViewById(R.id.loaderLayout);
    TextView MTV = (TextView) findViewById(R.id.loader_msg);
    if(T && !loaderStarted){
        loader.start();
        LAY.setVisibility(View.VISIBLE);
        MTV.setText(msg);
        loaderStarted = true;
    }
    else if(T && loaderSuspended && loaderStarted){
        loader.resume();
        LAY.setVisibility(View.VISIBLE);
        MTV.setText(msg);
        loaderSuspended = false;
    }
    else if (loaderStarted && !loaderSuspended) {
        loader.suspend();
        LAY.setVisibility(View.GONE);
        loaderStarted = false;
        loaderSuspended = true;
    }
}

to suspend the thread then resume it (.suspend() and .resume() are deprecated)

Thanks in advance :) And sorry for the awful English ( :D )

  • The reasons the answers are suggesting different implementation is because a java thread cannot _directly_ call sleep on another thread. This way, you know the thread making itself sleep is not in the middle of doing something that would be dangerous to sleep during. (Holding locks during synchronization and such) – DoubleDouble Dec 24 '13 at 16:25
  • You have horrible variable naming standards... You should consider following the standards so your code is more readable. – JoxTraex Dec 24 '13 at 21:38

2 Answers2

1

You could try adding fields:

// defines the paused state
private volatile boolean isPaused = false;

// a monitor object for wait/notify pattern
private final Object suspender = new Object();

Then in your logic:

void pause(){
     synchronized(suspender){
         isPaused = true;        
     }
}

void resume(){
     synchronized(suspender){
         isPaused = false;
         suspender.notify();
     }
}

while (true){
    if(loader.isInterrupted()){
        return;
    }

    // this outside loop is needed to deal with spurious wakeup
    synchronized (suspender){
        while(isPaused){            
            suspender.wait();
        }
    }

    ...
}

More about wait and notify: A simple scenario using wait() and notify() in java

Community
  • 1
  • 1
Andrey Chaschev
  • 16,160
  • 5
  • 51
  • 68
  • if you resume and notify suspender, and then context is switched to your worker thread (`isPaused` is still `true`), you get inside loop and wait one more time - resume failed – hoaz Dec 25 '13 at 13:10
  • I must admit that I haven't tested it, I've fixed what I think could be an error. Did you try running this, or do you think it is conceptually wrong? – Andrey Chaschev Dec 25 '13 at 13:23
  • I think changing order does not help either. There is a small chance to lock job thread in both cases. With the new code if you call `pause()` / `resume()` quickly one by one you can stuck in `wait()` call too. – hoaz Dec 25 '13 at 14:11
  • Ok, I see. I've added `synchronized` blocks for atomic state transitions, they should fix the issue. Thanks for pointing out! – Andrey Chaschev Dec 25 '13 at 17:12
0

It is preferred to introduce boolean flag in your Thread implementation:

final private volatile boolean isSuspended = false;

Then you can set this flag to true/false and rewrite your suspend logic in run method like this:

while (true) {
    while (isSuspended) {
        try {Thread.sleep(25);} catch (InterruptedException e) {}
    }
    ...
}
hoaz
  • 9,883
  • 4
  • 42
  • 53
  • min SDK is : 8 is it OK ? I mean the device's cpu is low that it isn't upgraded to 2.3.6 then doesn't this code reduce the program's running speed ? – Ebrahim Tahernejad Dec 24 '13 at 18:35