Search code examples
androidandroid-annotations

Performing data loading unitl succesfull or user break


In my app I performing loading data from web and then displaying it to user. Before loading data app shows progress dialog. I have problem if user locks phone in the middle of loading operation, or server is overloaded and can't respond in time my application freezes, because it doesn't dismiss progress dialog, or in some cases it crashes because lack on needed data.

If some error happened while loading data I want show some dialog to user to let him know about error and ask him should application repeat last request. I tried to use AlertDialog for it, but I haven't succeed.

Here is code of one activity (There is no progress dialog here, but it demonstrates how I loading data):

    @EActivity(R.layout.layout_splash)
    @RoboGuice
    public class SplashScreenActivity extends Activity {

    @Inject
    private AvtopoiskParserImpl parser;

    @Bean
    BrandsAndRegionsHolder brandsAndRegionsHolder;

    @ViewById(R.id.splash_progress)
    ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        loadData();
    }

    @Background
    protected void loadData() {
        publishProgress(10);
        LinkedHashMap<String, Integer> brands = null;
        try {
            brands = parser.getBrands();
        } catch (IOException e) {
            Log.e(e.getMessage());
        }
        publishProgress(50);

        LinkedHashMap<String, Integer> regions = null;
        try {
            regions = parser.getRegions();
        } catch (IOException e) {
            Log.e(e.getMessage());
        }

        publishProgress(70);
        populateData(brands, regions);
    }

    @UiThread
    protected void populateData(LinkedHashMap<String, Integer> brands, LinkedHashMap<String, Integer> regions) {
        Intent intent = new Intent(SplashScreenActivity.this, SearchActivity_.class);
        brandsAndRegionsHolder.brandsMap = brands;
        brandsAndRegionsHolder.regionsMap = regions;
        publishProgress(100);
        startActivity(intent);
        finish();
    }

    @UiThread
    void publishProgress(int progress) {
        progressBar.setProgress(progress);
    }

}

parser.getBrands() and parser.getRegions() are loading data from the web.

I want to do something like this:

    boolean repeatRequest = true;
    while (repeatRequest) {
        try {
            brands = parser.getBrands();
            repeatRequest = false;
        } catch (IOException e) {
            Log.e(e.getMessage());
            repeatRequest = showErrorDialog();
        }
    }

But I didn't manage to do so because this code executes in background thread, but dialog should be shown in UI thread. I believe that it should be standard approach of doing so, but didn't manage to find it. Any ides how can I implement this?


Solution

  • The best way is to use AsyncTask.

    private class LoadDataTask extends AsyncTask<Void, Integer, Object> {
        private ProgressDialog mProgress;
    
        protected Object doInBackground(Void... params) {
            // This method runs in background
            Object result = null;
            try {
                result = parser.parse();
            } catch (Exception e) {
                result = e.getMessage();
            }
            return result;
        }
    
        protected void onProgressUpdate(Integer... progress) {
            // This method runs in UI thread
            mProgress.setProgress(progress[0]);
        }
    
        protected void onPreExecute() {
            // This method runs in UI thread
            mProgress = new ProgressDialog(context);
            mProgress.show();
        }
    
        protected void onPostExecute(Object result) {
            // This method runs in UI thread
            mProgress.dismiss();
    
            if (result instance of String) {
                // Here you can launch AlertDialog with error message and proposal to retry
                showErrorDialog((String) result);
            } else {
                populateData(result);
            }
        }
    }