Progressbar in Android Studio is not showing while delay - java

I have a method in which I want a delay of a second, and while the delay is running there should be a loading animation (ProgressBar).
Right now, when the method is now running the loading animation is not appearing. If I do not call the Timeout it does appear, and when I do not make it invisible after, it shows up after the timeout.
How do I show the loading animation while the timeout is running? I have a similar problem trying to do with with Thread.sleep(1000).
public void firstMethod(){
ProgressBar pgLoading = (ProgressBar) findViewById(R.id.pgLoading);
pgLoading.setVisibility(VISIBLE);
try {
TimeUnit.SECONDS.sleep(1);
}catch(InterruptionException ex){
ex.printStackTrace();
}
pgLoading.setVisibility(INVISIBLE);
}

By calling the sleep method you are making the UI thread sleep for 1 second during that time nothing will happen on UI Thread hence you do not see the ProgressBar. You should instead use a TimerTask to wait for this one second and then close the ProgressBar.
Checkout this link on how to use TimerTask.

Main thread can't be blocked. That will cause the entire rendering to stop. That's why you only see the result after that timeout.
These kind of operations shoud be handled in other threads. If you are using Java you can use Runnables but you should consider moving to Kotlin to use coroutines.
E.G:
pgLoading.setVisibility(VISIBLE);
new Thread() {
public void run() {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
pgLoading.setVisibility(INVISIBLE);
}
});
}
}
}.start();

This is happening because the current thread is being paused.To avoid this put your delay/long process in a different thread.For example:
public void firstMethod(){
ProgressBar pgLoading = (ProgressBar) findViewById(R.id.pgLoading);
pgLoading.setVisibility(View.VISIBLE);
new Thread(()->{
// Do all your long process here
try {
TimeUnit.SECONDS.sleep(1);
}catch( InterruptedException ex){
ex.printStackTrace();
}
runOnUiThread(() -> pgLoading.setVisibility(View.INVISIBLE));
}).start();
}

Related

Android - pause and continue thread

In my Activity I create a Thread for multiply objects and "save" them to a hashmap. Is it possible to pause just a single thread of the hasmap and continue it?
public void onCreate(Bundle savedInstanceState) {
Thread oThread = new Thread(new Runnable() {
public void run() {
while (true) {
// doing some work
}
}
}
oThread.start();
aThreads.put(name, oThread);
}
public void anyMethod(){
// here I want to start and continue a thread
aThreads.get(name).stop();
aThreads.get(name).resume();
}
But .stop() and .resume() aren't working :/ any suggestions?
Use a boolean variable to control the thread exection.
ie.
while(!isThreadRunning){
...your statements
}
Once you are moving out of the screen in OnPause method make the variable false/true based on your usage to stop the thread execution.And you have to take care of the persisting hashmap.

Android pause/resume AsynTask

I have a UI thread(MainActivity) calling an AsynTask object(DownloadManager), which, in turn calls 3 threads (DownloaderThread).
How do I pause/resume the 3 DownloaderThreads without pausing the AsynTask or the UI thread?
Following is the code I have currently implemented for the pause functionality, but when the Pause button is clicked, the app crashes with the dialog: "app has stopped". Code:
DownloadManager (AsynTask):
public void onPause() {
try{
t0.wait();
t1.wait();
t2.wait();
this.wait();
}catch (InterruptedException ex){
}
}
DownloaderThread (implements Runnable and is passed to a Thread instance in DownloadManager:
public class DownloaderThread implements Runnable {
private Object mPauseLock;
private Boolean mPaused;
private Boolean mFinished;
public void run(){
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
try{
while(!mFinished){
//do something
synchronized (mPauseLock){
while (mPaused){
try{
mPauseLock.wait();
}catch (InterruptedException e){
}
}
}
}
}
}
public void onPause(){
synchronized (mPauseLock){
mPaused = true;
}
}
You can't really pause an AsyncTask once it started. You can, however, store the progress when activity is paused/destroyed and start from the progress once you are back to the original Activity. But I recommend the best way to complete task for your scenario is to use Service.

Activity doesn't load layout

I setted up simple application with 2 activities. I had problem in first activity. It is used just for displaing logo for 3 seconds and then launching second activity. Problem is that it doesn't load the layout, it waits 3 seconds and then load second activity. The code is here:
public class StartActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_screen);
final Intent myAct = new Intent(this, MyActivity.class);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
startActivity(myAct);
finish();
}
}
I was able to fix this problem by creating another thread and executing waiting there. Fixed code is here:
new Thread(){
public void run(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
startActivity(myAct);
finish();
}
}.start();
So i actually fixed the problem. I just want to know why it works the second way but it doesnt work by first way becouse i don't understand it.
In the first case, you are telling the UI Thread to sleep, preventing it to draw the layout. When it finishes the sleep process, it immediately starts the next Activity. That is why you do not see the first Activity layout being shown. This approach is not recommended at all as during the sleep time, your application is not responsive to any user actions. You are recommended to use an AsyncTask or a new Thread or a Handler, using postDelayed() method but never cause the UIThread to stop doing its job (drawing and handling UI events).
In the second case, you are making the sleep() in a new Thread, not the UIThread. So, what happens is that the UI Thread is never interrupted and is allowed to draw the entire layout. At the same time, the sleep time is respected as well. Once the sleep() ends, your new Activity starts.
First method makes the UI thread sleep .This result in stopping of all the functioning and UI interaction of the activity.
The second method uses another thread .Since it's the other thread which sleeps all the UI parts of the main UI thread works fine and the code works as intended.
Actually your approach is also wrong / bad practice.
Starting new activity and finishing current should be done on main thread.
Also try to avoid final objects initialization, they may stack in memory.
Here is one of correct approaches (postDelayed() will be perform on MainThread):
public class StartActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_screen);
View view = findViewById(R.id.any_view_from_start_screen_layout);
view.postDelayed(new Runnable(){
public void run(){
startNewActivityAndCloseCurrent();
},3000);
}
private void startNewActivityAndCloseCurrent(){
Intent myAct = new Intent(this, MyActivity.class);
startActivity(myAct);
finish();
}
}

Java Timer equivalent in Android

I recently began working with Java and am exploring Android development. I was trying to port over one of the Java programs I made, but I am having some difficulty with getting the java Timer to function the same way in Android. I read through a number of posts and they, for the most part, indicated that it would be better to use the Handler class in android as opposed to Timer.
This was my timer in Java:
playTimer = new Timer(1000/model.getFPS(), new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// do something
...
if( finished everything ) playTimer.stop();
}
});
And once a certain button was clicked, I would simply run "playTimer.start()" to start it.
As you can see, I had it set up so that the user could set the FPS they wanted (by simply setting the first parameter of the Timer class to 1000/model.getFPS()).
Now I've tried to do something similar in Android using handlers, but I am having some difficulty. It appears that the Handler ticks are not firing at the proper intervals. It seems that they are quite slow compared to what I need it to be. This is what I did in android so far:
public void startTimer() {
playHandler = new Handler();
startTime = System.currentTimeMillis();
playHandler.removeCallbacks(updateTimeTask);
playHandler.postDelayed(updateTimeTask, 0);
}
private Runnable updateTimeTask = new Runnable() {
public void run() {
// do something
...
if( finished everything ) playHander.cancel();
else {
playHandler.postDelayed(updateTimeTask, 1000/model.getFPS());
}
}
};
Excuse the semi-pseudocode. Can anyone shed any light? Thanks guys.
You can use a timer as below. The timer runs every second incrementing the counter. Displs the counter value in textview.
Timer runs on a different thread. SO you should set the text on the UI Thread.
The counter runs from 0 to 99. After 99 the timer is cancelled. Also cancel the timer when not required like in onPause().
public class MainActivity extends Activity {
TextView _tv,tv2;
Timer _t;
int _count=0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_tv = (TextView) findViewById( R.id.textView1 );
_t = new Timer();
_tv.setText(R.string.app_name);
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
_count++;
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
_tv.setText(""+_count);
if(_count==99)
{
_t.cancel();
}
}
});
}
}, 1000, 1000 ); //change this value of 1000 to whatever you need.
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
_t.cancel();
}
}
If you decide not to use Timer (for whatever reason) you can just write a separate Thread that sleeps for x milliseconds and then wakes up and calls whatever Runnable you want it to call. That's going to be pretty precise. I have it working at the 10 millisecond level and it works quite nicely.
Just remember that it HAS to call a Runnable because a separate Thread can't have direct effect on anything on the main display thread.
public boolean keepPlayingAnimation = true
Handler h = new Handler()
Runnable updateDisplay = new Runnable(){
public void run(){
//do something in my display;
}
}
new Thread(){
public void run(){
while(keepPlayingAnimation){
try{
sleep(10);
}catch(Exception e){
}
h.post(updateDisplay);
}
}
}.start();
Just don't forget to set keepPlayingAnimation to false when you're done with this cause otherwise it will sit there running in the background for ever (or just about).
Take a look at Android Timer
It already has everything you need i guess. From ticking every 1 second to finish handly and so on.
Here is an example how to setup an TimerTask: setup
Not sure if you need such but i just remembered that i made this.

Android: runOnUiThread does not always choose the right thread?

I've got an activity that keeps reading words to the user, and using onUtteranceCompleted with textTospeech to display something when the code is completed.
Inside onUtteranceCompleted I have this code to delay a function with a second:
Runnable task = new Runnable() {
public void run() {
//runs on ui
runOnUiThread(new Runnable() {
public void run() {
readWord();
}
});
}
};
worker.schedule(task, 1, TimeUnit.SECONDS);
This seems like it works well, but I think it is causing a problem.
When I rotate the screen of my phone (I guess this starts a new activity).
I hear some words being read in the background. I guess this is because of runOnUiThread() which makes the activity continue in the background.
How could I avoid 2 activities running ? I would prefer if I don't have to stop the screen from rotating on doing some weird patch!
Thank you
EDIT:
public void readWord() {
if (this.readingOnPause) {
return;
}
txtCurrentWord.setText(currentItem[1]);
this.hashAudio.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"word");
this.tts.setLanguage(Locale.US);
this.tts.speak(this.currentItem[1], TextToSpeech.QUEUE_FLUSH,this.hashAudio);
}
EDIT2:
instantiation of worker:
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
I would use a Handler instead of runOnUiThread().
For one thing, you're using a Thread that starts another Thread - why?
Secondly, if you create a simple Handler, it should kill itself on the rotate config change. IE:
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// do your background or UI stuff
}
};
Then later use a Thread to call the handler, which will kick off whatever process you want to run on the UI thread:
new Thread() {
#Override
public void run() {
long timestamp = System.currentTimeMillis();
// thread blocks for your 1 second delay
while (System.currentTimeMillis() - timestamp <= 1000) {
// loop
}
handler.sendEmptyMessage(0);
}
}.start();
Ok so this is a fix I've come up with, if someone has a better solution, I'm listening.
I've added android:configChanges="keyboardHidden|orientation" inside the activity in the androidmanifest
2.
and then a function that is called when the screen is rotate:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
setContentView(R.layout.streaming);
initializeUI(); //contains all the findViewByID etc...
}

Categories

Resources