I have an asynctask that is in its own activity. I pass it a string value and it connects to my web service and downloads Json data based on the name I pass in, returning the Json resultset. Works great.
I'd like to add a progress spinner to the asynctask, but I'm stymied as to how to do it. I've perused this and many other blogs, and come close but have not yet found the solution. It seems I either need to have the asynctask in with an Activity class to get the context or I have to pass in the context as a parameter -- but I need the input parameter to be String. I've read about the possibility of building an Object that could hold the String and a Context parameter, but I'm very new to Java and don't know how to build something like that nor have I found a good explanation of how to do so. So often an explanation gets right up to what I need and then says, "... and then you do X and that's it," when X is what I need to know.
All I want is just a spinner thingie to whirl while the download happens. No text, no dialog, just a spinner.
Add a ProgressBar(this is what it's actually called, Spinners are like drop down menus in Android) to the layout of the Activity where you're initializing your AsyncTask.
Then make two functions startProgress()
and stopProgress()
, which start and stop the progress bar.
Give your AsyncTask a reference to the Activity, either by sending it during initialization or execution, or making a function in your asyncTask setActivity(MyActivity activity)
and call it between your AsyncTask initialization and execution.
Override the onPreExecute()
of your AsyncTask to call activity.startProgress()
and onPostExecute()
to call activity.stopProgress()
.
EDIT: You can also try passing a reference to the ProgressBar in the constructor of your AsyncTask. Get the reference to the ProgressBar in the onCreate()
method of your activity, then add it in the AsyncTask constructor. In the onPreExecute()
and onPostExecute()
methods of the AsyncTask, start and stop the progress bars accordingly.
class MyTask extends AsyncTask<Request, Void, Result> {
protected ProgressDialog progressDialog;
@Override
protected void onPreExecute()
{
super.onPreExecute();
progressDialog = ProgressDialog.show(YourActivity.this, "", "", true, false);
}
@Override protected Boolean doInBackground(Request... params) {
// do some work here
return true;
}
@Override protected void onPostExecute(Result res) {
progressDialog.dismiss();
}
}
You can pass various parameters to an AsyncTask
, not just one!
One way to do this is to make member variables in your AsyncTask and initialize them using a constructor that accepts parameters.
For example:
private class MyAsyncTask extends AsyncTask<null, null, null> {
String mFirstParam = null;
Context mContext = null;
// Constructor which accepts parameters
public MyAsyncTask(String _firstParam, Context _context){
this.mFirstParam = _firstParam;
this.mContext = _context;
}
}
When you create an instance of your AsyncTask
, create it as follows:
MyAsyncTask task = new MyAsyncTask(myFirstStringParam, mySecondContextParam);
task.execute();
Now you can use both these parameters throughout the scope of your AsyncTask
.
Consider passing the ImageView
containing of "loading" image and set its Visibility to View.GONE
once you have finished downloading your data.
i.e. download your data in the doInBackground
method and then change the ImageViews visibility to View.GONE
in the onPostExecute
method
I think you can pass the progress bar instance to AsyncTask when your create it in its constructor. Here is a downloader example by using AsyncTask -
public void downloadFile(String url, String path, ProgressDialog progress) {
DownloadFileAsync downloader = new DownloadFileAsync(progress);
File file = new File(path);
if (file.exists()) {
file.delete();
}
downloader.execute(url, path);
}
class DownloadFileAsync extends AsyncTask<String, String, String> {
private final WeakReference<ProgressDialog> progressbarReference;
public DownloadFileAsync(ProgressDialog progress) {
progressbarReference = new WeakReference<ProgressDialog>(progress);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... aurl) {
int count;
try {
URL url = new URL(aurl[0]);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
/*
* android.util.Log.v("downloadFile", "Lenght of file: " +
* lenghtOfFile + ":" + aurl[1]);
*/
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(aurl[1]);
try {
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""
+ (int) ((total * 100) / lenghtOfFile));
output.write(data, 0, count);
}
} finally {
if (output != null) {
output.flush();
output.close();
}
if (input != null) {
input.close();
}
}
} catch (Exception e) {
ProgressDialog p = null;
if (progressbarReference != null) {
p = progressbarReference.get();
}
if (p != null && p.isShowing()) {
p.dismiss();
}
}
return null;
}
protected void onProgressUpdate(String... progress) {
if (progressbarReference != null) {
ProgressDialog p = progressbarReference.get();
if (p != null) {
p.setProgress(Integer.parseInt(progress[0]));
}
}
}
@Override
protected void onPostExecute(String unused) {
ProgressDialog p = null;
if (progressbarReference != null) {
p = progressbarReference.get();
}
if (p != null && p.isShowing()) {
p.dismiss();
}
}
}
ProgressDialog is a custom Dialog which have a progress bar inside it.
Hope it helps.