Andorid
I want to show progressdialog while doing renaming task. The dialog should appear after clicking rename button. However, the progress dialog appears after renaming function(loop) is ended. Here's my code
public void onRenameClicked(View v){
ProgressTask task = new ProgressTask();
task.execute();
for(int i = 0; i < num_of_files; i++){
rename(file[i]);
}
}
and Here's innerclass to show dialog
class ProgressTask extends AsyncTask<Integer, Void, Void>{
ProgressDialog pd = new ProgressDialog(MainActivity.this);
#Override
protected Void doInBackground(Integer... i) {
for(int j = 0; j < item.size(); j++) {
pd.setProgress(j);
pd.setMessage((j) + "/" + item.size());
}
return null;
}
#Override
protected void onPreExecute() {
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setTitle("변경중");
pd.setMax(item.size());
pd.show();
}
}
You do realize that you are calling your async task, with no data.. therfore its finishing quickly. You should probably pass in the list of files into the AsyncTask via arguments and then process those calls accordingly for each file INSIDE the AsyncTask and update the progress of the AsyncTask as you finish renaming files.
You have to use
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
pd.setProgress(values[0]);
pd.setMessage((values[0]) + "/" + values[1]);
}
and
publishProgress(j, item.size());
in the doInBackground(). These modifications are required because the setProgress and setMessage must be executed in the UI thread not in the background one.
Related
I need to create several UI controls in an android application at runtime.
In order to not freeze the UI while creating controls (and to show a "Loading..." box), I want to use a worker thread like this:
private class LoadControls extends AsyncTask<TdcItem, Integer, Integer> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(FormActivity.this);
dialog.setMessage(getString(R.string.loading_message));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
protected Integer doInBackground(TdcItem... items) {
ScrollView accordion = (ScrollView) findViewById(R.id.accordion);
int count = items.length;
for (int i = 0; i < count; i++) {
Button header = new Button(FormActivity.this);
header.setText(items[i].getName());
if (isCancelled()) break;
}
return count;
}
protected void onPostExecute(Integer result) {
dialog.dismiss();
}
}
This code in part of the Activity which will response to button clicks.
The problem is that compiler says that I cannot create a button in a worker thread. How can I do it?
it seems to be a UI stuff you want to do so it should be done on UI thread...
otherwise you ll have to create a
new Handler()
create a new Runnable and call the postOnUiThread() method of the handler is not very...usefull i guess
I know this answer has already been answered multiple times but I cannot get it to work properly. It's starts with activity A where a user needs to login via the function authenticate. When the user hits the button login I want the progressdialog to appear until the function authenticate has got a response. While success you go to another activity where you can navigate through the app.. Anyway sometimes when the internet is slow or if you're on mobile internet I still see activity A for a few seconds doing nothing while the auth function is going on. When it's done the system hops to activity B.
I tried using sleep thread thingy but that's not the point.. I want the progressdialog to appear when the user hits login and dissapear when the auth function has been finished.
With the help of AsyncTask I sometimes see the dialog for one flash of a second but not how it should be.. I also want to use asynctask for loading my listviews but the dialog isn't doing what it should.
Here my AsyncTask code
public class HeavyWorker extends AsyncTask<String, Context, Void> {
private ProgressDialog dialog;
public HeavyWorker() {
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(AuthenticationActivity.this);
dialog.setMessage("Gettting data");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected Void doInBackground(String... params) {
authenticate(username, password, autoLogin);
return null;
}
#Override
protected void onPostExecute(Void result) {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
}
And where I call the asynctask
builder.setTitle(R.string.dialog_authenticate)
.setIcon(R.drawable.ic_launcher)
.setView(viewInflater)
.setPositiveButton(R.string.dialog_button_login,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
EditText ETusername = (EditText) viewInflater.findViewById(R.id.username);
EditText ETpassword = (EditText) viewInflater.findViewById(R.id.password);
CheckBox optionAutoLogin = (CheckBox) viewInflater
.findViewById(R.id.autoLogin);
checkAutoLogin = 0;
if (optionAutoLogin.isChecked()) checkAutoLogin = 1;
username = ETusername.getText().toString();
password = ETpassword.getText().toString();
new HeavyWorker().execute();
//authenticate(ETusername.getText().toString(), ETpassword.getText().toString(), checkAutoLogin);
}
})
Any help or advice is appreciated.
Are you finishing the activity A when authentication success? In that case, you could skip onPostExecute
The Documentation gives you quite a good example: You can post the Progress in the onProgressUpdate(...) And can update it from doInBackground via publishProgress(int i)
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
//DO YOUR PROGRESSBAR THINGS HERE
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
I have an Activity with a button that starts a long running task. I perform the task using an AsyncTask and display a determinate ProgressBar that is updated as the task progresses. Everything works fine the first time the task is run, but on subsequent runs the dialog appears, but is already at 100% and 100/100. I'm overriding both onCreateDialog and onPrepareDialog in my Activity. I presumed that using setProgress(0) would reset the dialog, but this isn't working. I use showDialog in the AsyncTask's onPreExecute method and dismissDialog in the AsyncTask's onPostExecute. The only way I've been able to get the dialog to reset is by using removeDialog in onPostExecute, but I would rather not recreate the dialog as I'm going to be reusing several times. The relevant code is below. This is on API level 10.
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case PROGRESS_DIALOG:
progressDialog = new ProgressDialog(ProtoBufSerializationTestActivity.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(true);
progressDialog.setMax(100);
progressDialog.setMessage("Testing...");
return progressDialog;
default:
return null;
}
}
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
switch (id) {
case PROGRESS_DIALOG:
ProgressDialog tmp = (ProgressDialog)dialog;
tmp.setProgress(0);
tmp.setSecondaryProgress(0);
return;
default:
Log.e("test", "Unknown dialog requested");
}
}
private class SerializationTestTask extends AsyncTask<Void, Integer, Long> {
#Override
protected void onPreExecute() {
showDialog(PROGRESS_DIALOG);
}
#Override
protected Long doInBackground(Void... params) {
long accumulator = 0;
int totalSize = 0;
for (int i = 0; i < 10000; i++) {
final long start = System.nanoTime();
//code to be timed
final long end = System.nanoTime();
accumulator += end - start;
if (i % 100 == 0) {
publishProgress(i);
}
}
return accumulator;
}
#Override
protected void onPostExecute(Long aLong) {
dismissDialog(PROGRESS_DIALOG);
results.setText(String.format("Serialized Message 10000 times.\nAverage time to serialize %.3fms", (double) aLong / 1e10));
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.incrementProgressBy(1);
}
Edit After taking #Arhimed's suggestion I ended up with the following code. It is much simpler. I could have used DialogFragment, but I don't think it is necessary in this case.
private class SerializationTestTask extends AsyncTask<Void, Integer, Long> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(ProtoBufSerializationTestActivity.this, "Serialization Test", "Testing...", false);
}
#Override
protected Long doInBackground(Void... params) {
long accumulator = 0;
int totalSize = 0;
for (int i = 0; i < 10000; i++) {
final long start = System.nanoTime();
//code to be timed
final long end = System.nanoTime();
accumulator += end - start;
if (i % 100 == 0) {
publishProgress(i);
}
}
return accumulator;
}
#Override
protected void onPostExecute(Long aLong) {
dialog.dismiss();
results.setText(String.format("Serialized Message 10000 times.\nAverage time to serialize %.3fms", (double) aLong / 1e10));
}
#Override
protected void onProgressUpdate(Integer... values) {
dialog.incrementProgressBy(1);
}
}
Actually Arhimed is right and you can't do it but you can force progress bar to come to its zero state with 'dirty' way.For me the client wanted progress bar to zero its value no matter what,in case if user leave that activity,but in my case the progress was still there,and only was reseting from start.I had custom progress drawable and setProgress did not help me at all.So what i did was to call this method before actually setting the REAL drawable setProgressDrawable(null) this is dirty way clearing,but it do what you want,and afterwards just call same method with your own progressdrawable so it feels like it has been refreshed.Thats it..no other way you can achieve this unfortunately.
It is impossible to use ProgressDialog in that way. Your AsyncTask should create a new instance each time.
Actually setProgress(0) refreshes the display only if the progress is started.
So, you can force the refresh by calling onStart before setProgress, like this :
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
ProgressDialog progress = (ProgressDialog)dialog;
progress.onStart();
progress.setProgress(0);
}
I have an activity that loads an xml file, but when the app is invoked without reply in 1 or 2 seconds, I wonder if I can put some kind of loading not to appear that the app crashed, thanks.
The rule of thumb is, if you do anything, use AsyncTask, otherwise your application will eventually crash on long network delays or large files.
private class doSomethingTask extends AsyncTask<SomeData,Integer,SomeData[]> {
private ProgressDialog dialog;
protected SomeData[] doInBackground(SomeData... values) {
int count = values.length;
for( int i=0; i<count; i++) {
publishProgress(count,i+1);
// do something here
....
//
if( isCancelled() ) return null;
}
return values;
}
protected void onPreExecute()
{
// show progress bar or something
dialog = new ProgressDialog(context);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMessage(context.getString(R.string.downloading));
dialog.show();
}
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
dialog.setMax(values[0]);
dialog.setProgress(values[1]);
}
protected void onPostExecute(SomeData[] result) {
// kill progress bar here
if( this.dialog.isShowing()) {
this.dialog.dismiss();
}
}
}
I'm using "include" on my main layout. Each one of them is a RelativeLayout which needs an OnClick listener to be attached, and update some information related.
So I've tried to do it simply by:
setContentView(R.layout.allobjects);
ObjectListeners objectListeners = new ObjectListeners(objects);
for(int i=0;i<1;i++)
{
RelativeLayout objectBoxRelativeLayout = (RelativeLayout)findViewById(R.id.object1 + i);
objectBoxRelativeLayout.setOnClickListener(objectListeners.GetObjectListener(i));
SomeObject currentObject = this.objects.get(i);
Object viewObject = findViewById(R.id.object1 + i);
this.setObjectView(viewObject, currentObject);
}
The issue is that it takes too long after the "setContentView(R.layout.allobjects);" command, and the application shows black screen until it finish loading.
In addition, I use "setContentView(R.layout.allobjects);" after I perform the above commands. All of these commands have to be written after "setContentView(R.layout.allobjects);".
How can I handle that kind of situation ? Do I have to use onPreExecute and implement AsyncTask ?
Yes, AsyncTask is good solution to show loading dialog while these commands being executed.
UPDATE:
Add this class under your onCreate() function:
private class MyTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog dialog;
private Context context;
public MyTask(Activity activity) {
context = activity;
dialog = new ProgressDialog(context);
}
protected void onPreExecute() {
dialog.setTitle("Loading...");
dialog.setMessage("Loading...");
dialog.show();
}
#Override
protected Void doInBackground(Void... params) {
//do your code here in background
protected void onPostExecute(Void res) {
dialog.dismiss();
}
}
then use the task inside onCreate() like this:
MyTask mt = new MyTask(this);
mt.execute();