ASynchTask sleep in doinbackground locking the UI thread

我的未来我决定 提交于 2019-12-25 01:45:56

问题


EDIT: SOLVED. Sorry guys, it occurred to me that while my loading of my data was occurring in a background thread, the callback that parsed the data was not. The parsing of the data took a very long time, and that was what was locking my thread.

EDIT: It has come to my attention that my overarching problem (the ProgressDialog no longer spinning) may be caused by a problem with my use of a ProgressDialog rather than the UI thread being blocked. If that is the case, how do I fix that?

EDIT: to clarify, this does not lock the entire program up forever. Once everything is loaded, the progress dialog IS dismissed, and the new activity is brought up. My problem is that while it is loading, the entire UI locks up (i.e. the progressdialog stops spinning)

TL;DR: Thread.sleep() in doInBackground() is locking the UI thread

I have an app that, when a specific activity opens, begins to load a lot of data in the background from my back-end, for example, a large amount of data related to a schedule. This information will not be used right away, but may be used if the user attempts to access it (i.e. by clicking the schedule button, and launching the schedule activity).

If the user waits a bit before clicking the schedule button, all of the data loads, the schedule activity opens, and displays everything great. My problem is if they click the button before the data loads.

My solution here was to create an ASyncTask that shows a ProgressDialog while periodically checking if the data has finished loading, and sleeping otherwise. It knows that the data is finished loading via some application-wide boolean variables. My problem is that, even though the Thread.sleep() is run within doinbackground(), it is still locking the UI Thread.

I am using a custom ASyncTask, defined below:

public class LoadWithProgressDialog extends AsyncTask<Void, Void, Boolean>{
    private ProgressDialog pd; //the progress dialog
    private String title; //the title of the progress dialog
    private String  message; //the body of the progress dialog
    private Runnable task; //contains the code we want to run in the background
    private Runnable postTask; //execute when the task ends
    private Context c;


    public LoadWithProgressDialog(Context context,String t, String m,Runnable r, Runnable postR){
        super();
        c = context;
        task = r;
        postTask = postR;
        title = t;
        message = m;
    }

    @Override
    protected void onPreExecute(){
        pd = ProgressDialog.show(c,title, message, false, false);
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        task.run();
        return true;
    }


    @Override
    protected void onPostExecute(Boolean result) {
        pd.dismiss();
        if(postTask != null)
            postTask.run();
    }

and calling it via (for example):

if(loadingSchedule){

            LoadWithProgressDialog lwpd = new LoadWithProgressDialog(thisClass,"Loading","Loading Schedule", new Runnable() {
                public void run(){
                    while(loadingSchedule){
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }

                    }
                }
            },new Runnable() {
                public void run(){

                    Intent i= new Intent(thisClass, Schedule.class);
                    i.putExtra("numberIneed",index);
                    startActivity(i); 
                }
            });
            lwpd.execute();

(I shortened access to the global variable to "loadingSchedule" to make it easier to read)

How do I make this not lock the UI thread?


回答1:


Thread.sleep() in doInBackground() is locking the UI thread

Thread.sleep() in doInBackground() does not lock UI thread, as its name stated, task do in background asynchronously.

You UI thread doesn't get locked. It is actually the ProgressDialog pop up before AsyncTask started (in onPreExecute() method) and keep showing in front and block user interaction with the underlying activity during AsyncTask execution (in doInBackground() method). and finally dismissed after AsyncTask finish. (in onPostExecute() method)

I have an app that, when a specific activity opens, begins to load a lot of data in the background from my back-end

This is a common use case, it will be more efficient to create an AsyncTask implementation that load data in background, instead of create an ASyncTask that shows a ProgressDialog while periodically checking if the data has finished loading, and sleeping otherwise.

Check out the API here, it contains good example of how to use it properly.




回答2:


Your code looks correct, and should not block main thread.

So use debugger! Put breakpoint in doInBackground, Thread.sleep, onPostExecute, after lwpd.execute, and you will learn where the code gets and when.

Try to find answer to "where exactly is UI thread blocked".



来源:https://stackoverflow.com/questions/9285296/asynchtask-sleep-in-doinbackground-locking-the-ui-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!