简体   繁体   中英

AsyncTask progressdialog not showing, doInBackground blocks UI

I've been trying to get a progressdialog working while the data is being retrieved.

I used this link Implement android splash screen while loading data to get me started but it seems I cannot get it to work properly.

So far it does not show any progressbar because I think the funcion fillMyTickets blocks the UI thread and therefor the dialog is not shown. I do not understand how to resolve this problem. By reading through Stackoverflow I found solutions such as use onProgressUpdate function in AsyncTask but that's not what I want. All I need is a waiting dialog that says downloading and dissapears when the HTTP call is over.

Asynctask function in exampleFragment.java

private ProgressDialog dialog;
private class PrefetchData extends AsyncTask<Void, Void, Void> {

@Override
protected void onPreExecute() {
    super.onPreExecute();
    dialog = new ProgressDialog(getActivity());
    dialog.setMessage("Downloading..");
    dialog.setIndeterminate(true);
    dialog.setCancelable(true);
    dialog.show();
}

@Override
protected Void doInBackground(Void... arg0) {
    fillMyTickets();
    return null;
}

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    dialog.dismiss();
}

fillMyTickets function in exampleFragment.java

private void fillMyTickets() {
        HttpReader httpReader = new HttpReader();
        httpReader
                .setOnResultReadyListener(new HttpReader.OnResultReadyListener() {
                    @Override
                    public void resultReady(String result) {

                        JsonHelper jsonHelper = new JsonHelper();
                        tickets = jsonHelper.getTickets(result);
                    }
                });
        httpReader
                .execute(url);
    }

onAttach(Activity activity) function where AsyncTask is executed

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
     new PrefetchData().execute();
}

Also when commenting dialog.dismiss() in onPostExecute of AsyncTask the dialog does show but then ofcourse never closes.

You are calling a method that register a listener and download some data, but before the downloading the data, you are returning from the doInBackground and dismissing the dialog, so your dialog is being shown and the hidden. Try to modify your code and dismiss the dialog just when it completes the download:

private ProgressDialog dialog;
private class PrefetchData extends AsyncTask<Void, Void, Void> {

@Override
protected void onPreExecute() {
    super.onPreExecute();
    dialog = new ProgressDialog(getActivity());
    dialog.setMessage("Downloading..");
    dialog.setIndeterminate(true);
    dialog.setCancelable(true);
    dialog.show();
}

@Override
protected Void doInBackground(Void... arg0) {
    HttpReader httpReader = new HttpReader();
    httpReader.setOnResultReadyListener(new HttpReader.OnResultReadyListener() {
                @Override
                public void resultReady(String result) {
                    JsonHelper jsonHelper = new JsonHelper();
                    tickets = jsonHelper.getTickets(result);
                    //finished the download and we dismiss the dialog
                    dialog.dismiss();
                }
            });
    httpReader.execute(url);
    return null;
}

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
}

Hope it helps!

While I would recommend that you use the Volley library for doing async network requests(has retry policy, thread pool executor stuff baked in, and some other tasty stuff that you can extend and modify), in past projects I've used an async task with a progress dialog and have run into this exact issue before. The way I've handled it was to write a callback interface into your class that is extending AsyncTask that will be called on postExecute().

public class MyDataGrabber extends AsyncTask<Void,Void,Void> {

    public interface Callback {
        public void onComplete(String data);
    }
    public Callback callBack;
    public MyDataGrabber(Callback callback) { // Initialize the callback
        this.callBack = callback;
    }
   // on preExecute
   // on doInBackground
   public void onPostExecute(String data){
        this.callBack.onComplete(data);
   }
}

// So when you call your async task it will look like this

Dialog dialog;
//.... set up and show dialog etc.

new MyDataGrabber(new MyDataGrabber.Callback(){
    @Override
    public void onComplete(String data){
        // Handle data
        doDataHandling();
        // Dismiss dialog
        if(dialog.isShowing){
            dialog.dismiss();
        }
    }
}).execute(String url...other data etc);

Salauyou is correct though about the drawbacks of AsyncTask, there are some negative side effects with it executing in parallel or serial depending on android api level as well as concurrency issue and async tasks being still running in the background even after you close the app. Often times it requires that you write all sorts of canceling methods and weak references to handle correctly. Using a thread and handler is definitely a worthwhile solution to this as well.

ok so i misread this question.... but doinbackground shouldnt block anything thats why its in the background.

no that is the answer.... dialog isnt acutally on the ui. just run it from your regular activty instead of async task. i jused used ur coed like this, and its beautiful

public class MainActivity extends Activity {
    private ProgressDialog dialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         dialog = new ProgressDialog(this);
            dialog.setMessage("Downloading..");
            dialog.setIndeterminate(true);
            dialog.setCancelable(true);
            dialog.show();
        }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

so basicly move the dialog itself out of asynctask, and use 'this' as context. youll have no problem starting or killing it from anywhere in your app if you change the access from private to public

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM