Black screen while AsyncTask is running

2019-08-06 05:50发布

问题:

I'm new to asking questions here so any advice about that will be appreciated...but to my problem:

I'm trying to switch from one activity to another, where I'll show some data from the server. I'm pulling the data from server via AsyncTask but there is black screen showing between the activities, when the download is longer. I already tried to put the AsyncTask from onCreate() to onStart() but no change there.

New activity:

public class SalesMenu extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setContentView(R.layout.sales_menu);        
    setProgressBarIndeterminateVisibility(true);
    super.onCreate(savedInstanceState);
}

@Override
protected void onStart() {
    List<HashMap<String, Object>> result = null;
    AsyncTask<Void, Boolean, List<HashMap<String, Object>>> aTask = new AsyncSearchRead(
            "sale.order", 
            new Object[0], 
            new String[] {"name"}, 
            this).execute();

    try {
        result = aTask.get();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    Log.d("test", (result!=null ? result.toString() : "nothing"));
    super.onStart();
}

}

My AsyncTask:

public class AsyncSearchRead extends AsyncTask<Void, Boolean, List<HashMap<String, Object>>> {
String mModel; 
boolean mCount; 
Integer mOffset;
Integer mLimit; 
String mOrder; 
boolean mReverseOrder; 
Object[] mConditions;
String[] mFields;
Activity parentActivity;

public AsyncSearchRead(String model, boolean count, Integer offset, Integer limit, 
                    String order, boolean reverseOrder, Object[] conditions, String[] fields,
                    Activity activity) {
    mModel = model;
    mCount = count;
    mOffset = offset;
    mLimit = limit;
    mOrder = order;
    mReverseOrder = reverseOrder;
    mConditions = conditions;
    mFields = fields;
    parentActivity = activity;
}

@Override
protected List<HashMap<String, Object>> doInBackground(Void... params) {
    Long[] ids;
    List<HashMap<String, Object>> results;
            //Downloading the data
    ids = SetServer.connection.search(mModel, mCount, mOffset, mLimit, mOrder, mReverseOrder, mConditions);
    results = SetServer.connection.read(mModel, ids, mFields);

    return results;
}

@Override
protected void onPostExecute(List<HashMap<String, Object>> result) {
    parentActivity.setProgressBarIndeterminateVisibility(false);
}

}

When I did not turn visibility off onPostExecute it kept spinning after showing the activity but it's only shown after the loading.

How can I get it to show the activity and only after that start to load the data and show some progress bar/loader?

Thanks for any help.

回答1:

It's because you're using .get(). .get() essentially makes an AsyncTask synchronous (makes the main thread wait until it's done), so it's basically like not running the AsyncTask at all.

My suggestion is as follows:

  1. Move List<HashMap<String, Object>> result = null; to be a member variable.
  2. Remove the whole try/catch statement (the one with .get() in it), and the call to Log.*.
  3. Move your AsyncTask to be an inner class of SalesMenu.
  4. Do this.result = result in onPostExecute(), as well as whatever other processing you need to do on it.


回答2:

In addition to @Eric's answer, which is very good advice (+1), try putting super.onCreate() before setContentView(). As a general rule, the super call should happen before anything else in overridden Android lifecycle methods, and is especially important in the case of these two methods.



回答3:

In addition to the other excellent asnwers.

In your doInBackground() method, to show progress you call publichProgress() at regular intervals, which will in turn call onProgressUpdate(). onPostExecute() is only called AFTER doInBackground() has returned.

There is a full usage example in the AsyncTask docs.



回答4:

There some points to keep under consideration while doing any long running tasks: 1) Keep them out of main thread 2) Use Async task class for short lived tasks and make them Asynchronous, use handlers with threads 3) Keep out any long running/heavy tasks from oncreate method 4) Do any task after super.onStart(); call under onStart() or onCreate super calls.

Hope this will help you out.