I have a trouble with the circular progressBar, I have it in background in a layout as invisible. When I want to start the new activity I show it setting visible the layout, it is shown good but the animation of the progressBar works bad it sometimes rotate a little then stop after rotate a little more... It isn't fluently. I try to solve with this but seems that didnt work:
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
progressBar.setIndeterminate(true);
progressLayout.setVisibility(View.VISIBLE);
final CustomOverlayItem i = item;
Runnable intentRunnable = new Runnable()
{
public void run()
{
Intent intent = new Intent(context,Next.class);
startActivityForResult(intent, RETURN_FROM_MONUMENTO);
}
};
intentRunnable.run();
}
});
Thanks for your answers.
The part where you receive the data back from the other activity would be interesting. Sending the intent in a Runnable shouldn't be necessary since that is a pretty inexpensive operation (I think). But receiving the result back can result in some heavy operations.
Stuttering animations are normally a sign that you are doing something on the UIThread you shouldn't be doing (or that the device simply is too slow to handle the load of all threads).
If you are doing the network related stuff in the next activity you launch. use AsyncTask in that so that will not block the UI thread and it will make the ProgressBar Animation Smooth.
Related
There are other similar SO questions but none really helped.
I just want to implement a progress bar, that on button click, starts from 0, moves gradually and stops at a point (which is read from sharedPreferences).
However things are working but that progress bar is not gradually updating , instead it appears straight at the end point.
A simplified code I'm pasting here:
public class MainActivity extends ActionBarActivity {
int primaryProgress = 0;
int finalPrimaryProgress = 60;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
progressBar.setMax(100);
progressBar.setProgress(0);
}
public void click(View view) {
while (primaryProgress < finalPrimaryProgress)
{
progressBar.setProgress(primaryProgress+=1);
Thread.sleep(100); //This is inside Try-catch in actual code.
}
}
}
I know the problem is with Threads, but I am not too friendly with threads so unable to understand the problem.
I'm assuming your "click" method is happening on the UI thread (otherwise, you'd probably get an exception when you try to alter the view on a background thread).
Think about what you're doing here - the moment you click a button, you begin a loop. On each iteration of the loop, you change the value of the progress bar, and then make the (main) thread sleep for 100ms, then repeat.
Problem is, you're never letting the runtime react to what change you made. Once you change a value of a view (for instance, change the text of a TextView), the Android runtime needs to have time to react to your change, adjusting the view's size, position and then redraw. Your code basically blocks anything from happening before you change the value again, because you're telling the main thread to sleep, and then you immediately change the value again.
The expected result here would be seeing the progress bar drawn in its final state once you stopped changing its value without letting the runtime actually do anything with it.
As an alternative to your current click method, try doing something with postDelayed. This will allow the runtime to perform a full measure-layout-draw cycle between every iteration:
private void increaseProgressBar()
{
if (progressBar.getProgress() < progressBar.getMax())
progressBar.postDelayed(new Runnable() {
#Override
public void run() {
progressBar.setProgress(progressBar.getProgress() + 1); // increase the value of the progress bar.
increaseProgressBar(); // call the function again, but after a delay.
}
}, 100);
}
public void click(View v)
{
increaseProgressBar();
}
Note: Keep in mind that currently, clicking the button multiple times will cause erratic behaviour, since your basically adding additional runnables to this sequence, causing the progress bar to grow faster. You could defend against such a case fairly easily with a simple flag.
Could someone provide a sample implementation for rotating a button on a thread ? As of now I am rotating my button on the UI thread using the following code:
Animation ranim = (Animation) AnimationUtils.loadAnimation(getBaseContext(),
R.anim.rotation);
buttonRotate.setAnimation(ranim);
following should work for you.
Thread thread = new Thread()
{
#Override
public void run() {
try {
Animation ranim = (Animation) AnimationUtils.loadAnimation(getBaseContext(),
R.anim.rotation);
buttonRotate.setAnimation(ranim);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
you might eventually have to create an AsyncTask which can run independently without disturbing UI Thread.
in your UI thread define
Handler mainHandler = new Handler();
then inside your thread, use this:
mainHandler.post(new Runnable()
{
public void run()
{
//your piece of code
}
});
This has served me well so far in several cases, hope it does for you too! :D
EDIT:
mainHandler.post(new Runnable()
{
public void run()
{
while(someBoolean==true)
{
//your piece of code
}
}
});
if you'd define 'someBoolean' inside your class, just like you did with the handler, the thread is supposed to get it, I believe.
this way, after processing your data, simply set someBoolean to false, and the rotating stops.
Unfortunately I don't have access to my IDE at the moment, so I am going to list the steps for you rather that put buggy code up here.
1) Implement "AnimationListener" in the same class that extends Activity.
2) Set a click listener on your button.
3) Create an AsyncTask class.
4) Override doInBackground (of AsyncTask) and place your resource intensive logic there.
5) In onAnimationStart (of AnimationListener), implement the logic to call your AsyncTask, i.e. new MyTask().execute();
6) Define the animation and set it to your button.
This is how it should go: You click the button, onAnimationStart is called, your AsyncTask logic and animation both start. This way you can have your button rotate at the same that that your background thread is performing resource intensive operations - i.e. concurrently.
And just for fun, you may want to disable your button from being clicked again before the background task has finished.
Sorry for the lack of code, but this should be pretty straight forward from here.
I already have idea on how to use a Progress Dialog when background action is being performed. But my question is how do I show a progress Dialog when I am dynamically inflating a huge layout.
Since I can't inflate a view in another Thread, I am using the main UI thread. Due to this my progress dialog is not getting priority and it doesn't show up. My UI hangs for several seconds until it gets loaded fully. I tried several approcahes but none seems to work.
progress.show(context,"","inflating UI...");
setNewContent(R.layout.my_profile,R.id.my_profile_menu_button,R.id.my_profile_all_elements_layout);
populateProfileList(); //Dynamic nested layouts being inflated.
I am basically looking for dynamic layout changes based on user actions. So I dont have any other way other than creating dynamic views. Can anyone suggest me a helpful idea.
I had an similar problem with ui-thread. I wanted to add much views to my layout at runtime, I wanted to show a ProgressDialog to inform the user, that it could take a while. I had tried it with AsyncTask, but the only chance to do this, was to implement my ui-methods into the onPostExecute-Method of AsyncTask. But this just freezes the ProgressDialog, because ProgressDialog even works on ui-thread. I found a solution, maybe not the best, but it works. Before starting ui-action, I show a Toast. Then, I created a Thread with a handler and delayed the execution. After ui-action was done, I showed a new Toast. Delay the thread, gives the Toast enough time to get showed:
Toast.makeText(ActivityContext.this,
R.string.start_message,
Toast.LENGTH_SHORT).show();
final Handler uiHandler = new Handler();
final Thread uiThread = new Thread(new Runnable() {
#Override
public void run() {
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
yourUIAction();
Toast.makeText(
ActivityContext.this,
R.string.finish_message,
Toast.LENGTH_SHORT).show();
}
}, 100);
}
});
uiThread.start();
You need to use a handler to be able to talk to the UI thread
//in some thread
uiHandler.sendEmptyMessage(1);
...
Handler uiHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == 1) {
//do somestuff
}
}
};
Using Async Task is much better idea to me, when you have to do something in background, while progress dialog shows up on screen and then when background task completes, update UI... for reference please follow the link...
http://labs.makemachine.net/2010/05/android-asynctask-example/
hope this helps...:-)
I can't understand the implementation of a while loop in android.
Whenever I implement a while loop inside the onCreate() bundle, (code shown below)
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView=(TextView)findViewById(R.id.TextView);
while (testByte == 0)
updateAuto();
}
nothing boots up, and the program enters a "hanging" state after a while and I can't understand why. Testbyte is as follows:
byte testByte == 0;
and updateAuto() is supposed to update the code per 1 second and display inside the textView portion. I've been using setText inside updateAuto() as shown below and everything works fine, but once i implement the while loop all i see is a black screen and then an option to force close after a few seconds due to it "not responding".
TextView.setText(updateWords);
I've changed it to a button format (meaning i have to click on the button to update itself for now), but i want it to update itself instead of manually clicking it.
Am i implementing the while loop in a wrong way?
I've also tried calling the while loop in a seperate function but it still gives me the black screen of nothingness.
I've been reading something about a Handler service... what does it do? Can the Handler service update my TextView in a safer or memory efficient way?
Many thanks if anyone would give some pointers on what i should do on this.
Brace yourself. And try to follow closely, this will be invaluable as a dev.
While loops really should only be implemented in a separate Thread. A separate thread is like a second process running in your app. The reason why it force closed is because you ran the loop in the UI thread, making the UI unable to do anything except for going through that loop. You have to place that loop into the second Thread so the UI Thread can be free to run. When threading, you can't update the GUI unless you are in the UI Thread. Here is how it would be done in this case.
First, you create a Runnable, which will contain the code that loops in it's run method. In that Runnable, you will have to make a second Runnable that posts to the UI thread. For example:
TextView myTextView = (TextView) findViewById(R.id.myTextView); //grab your tv
Runnable myRunnable = new Runnable() {
#Override
public void run() {
while (testByte == 0) {
Thread.sleep(1000); // Waits for 1 second (1000 milliseconds)
String updateWords = updateAuto(); // make updateAuto() return a string
myTextView.post(new Runnable() {
#Override
public void run() {
myTextView.setText(updateWords);
});
}
}
};
Next just create your thread using the Runnable and start it.
Thread myThread = new Thread(myRunnable);
myThread.start();
You should now see your app looping with no force closes.
You can create a new Thread for a while loop.
This code will create a new thread to wait for a boolean value to change its state.
private volatile boolean isClickable = false;
new Thread() {
#Override
public void run() {
super.run();
while (!isClickable) {
// boolean is still false, thread is still running
}
// do your stuff here after the loop is finished
}
}.start();
I am now working on an android app in which I need to display a text after some processing is done.
I'm using a Thread to run a process in the back while my progress dialog is being displayed to the user. The Thread works properly and I've followed it step by step and, apparently, it also ends fine; however, the method in which I call it does not seem to come to an end (at least, during a normal cycle) because the text I am setting afterward does display immediately, I have to wait and do some other action (like in order for it to display
Below is the piece of code I'm having trouble with:
private OnClickListener saldoDisp = new OnClickListener(){
public void onClick(View v){
int x = s2.getSelectedItemPosition();
branchSel = arrSucsId[x];
mainProc();
saldoAdminTex.setText(strSaldo); //The late one
}
};
public void mainProc(){
chekP = new Thread (null,doProc,"Background");
chekP.start();
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true, false);
}
private Runnable doProc = new Runnable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
};
So I do get the "Task completed properly" but seems like it still waits for something else, any clues guys?
Thanks for taking a bit of your time to check it out =).
saldoAdminTex.setText(strSaldo); //The late one
is going to get called immediately. It doesn't wait until after the Thread started in mainProc ends. You also cannot dismiss the Progress Dialog in your runnable. You can only do UI related things on the main UI thread.
It would help you to read the article on Painless Threading on the Android Dev site.
About your ProgressDialog, please see this answer about how to use a AsyncTask with a ProgressDialog.
Looking at your code, this:
saldoAdminTex.setText(strSaldo);
would potentially be executed before your thread finishes as the thread will be running in parallel to that line.
An alternative way would be to do this:
public void mainProc(){
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true,false);
handler.post(new Runable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
saldoAdminTex.setText(strSaldo);
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
});
}