问题
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