0

I am building an application that is pretty dependent on async requests to function. I have the main Activity called MainActivity. This really doesn't do much apart from contain layouts, however it does have a recycleviewer. I then have a couple of http requests that are done to populate the recycle viewer.

To do this I have wrote a java class as follows:

public class dataforUi extends AsyncTask<String, String, JsonObject> {
    private ArrayList<UiElements> els;


    protected void onPreExecute() {
        progressDialog.setMessage("Downloading your data...");
        progressDialog.show();
        progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            public void onCancel(DialogInterface arg0) {
                RedditRequests.this.cancel(true);
            }
        });
    }



    protected JsonObject doInBackground(String... params) {
Do the http request here, get the result and populate uiElements with it
}

 @Override
    protected void onPostExecute(JsonObject jsonObject) {
        super.onPostExecute(jsonObject);
        progressDialog.hide();

    }

I have a few more classes like this but hopefully it serves as an example of what I'm trying to do.

Then back in Main Activity, I have this code:

public void getUiElements() {
        dataforUi ui = new dataforUi(findViewById(android.R.id.content));
        try {
            ui.execute("https://t").get();
            ArrayList<UiElements> r = ui.getEls();
            Log.d("MainFeedScreen", "Size of r is:" + r.size());
            UiAdapter = new UiAdapter(r);
            mRecyclerView.setAdapter(UiAdapter);
        } catch (Exception e) {

        }
    }

This works fine, but it is very jolty due to the use of .get() on execute to make it blocking. If i remove .get() the progress bar shows up and disappears when the task is done, but my ui thread has progressed past this and ha tried to populate my view with an Empty Array and therefore nothing shows.

I have done a bit of looking into it but cant find a conclusive way of managing the notification of the UI thread that an activity is done.

Would really appericiate any advice on this one.

Matt Boyle
  • 385
  • 1
  • 6
  • 25

2 Answers2

0

You need to fix your design.

On post execute, use local broadcast to notify your MainActivity that the AsyncTask is done.

viz
  • 1,247
  • 16
  • 27
  • Can you give some more advice on that? I don't see how pulling Async task out into a different class is a bad design pattern. I'm not a fan of nesting lots of class definitions in a single class file. However, thanks for the heads up about broadcast, will look into it – Matt Boyle May 29 '17 at 18:15
  • I'm not telling you that pulling Async Task out into a different class is bad. I am saying that you shouldn't do `.get()` to block your UI thread at all. You might want to have a look at [this](https://stackoverflow.com/questions/9273989/how-do-i-retrieve-the-data-from-asynctasks-doinbackground/14129332#14129332) as well. – viz May 29 '17 at 18:19
  • Here is a very nice explanation & guide to what you can do. https://stackoverflow.com/questions/18069813/activity-asynctask-broadcastreceiver-update-ui The accepted answer is much easier way to do it without any broadcast or interface. – viz May 29 '17 at 18:27
  • Thanks viz, not using get was precisely my question. – Matt Boyle May 29 '17 at 19:01
0

Try using a separate thread to process your data. I use a ListView in stead of a RecyclerView, but the principle is the same.

I have no problems with jolting views.

protected void onPostExecute(String result) {
    final String value = result;
    // dismiss the dialog after getting all data
    progressDialog.dismiss();

    if (!value.isEmpty()) {

        // updating UI from a new thread
        runOnUiThread(new Runnable() {
            public void run() {

                // ListData is my custom class that holds my data
                ArrayList<ListData> arrayDriverListData = new ArrayList<ListData>();
                ListDataAdapter adapter = new ListDataAdapter(ListActivity.this, arrayListData);
                ListData data;
                boolean b = true;

                try {
                    // My data is from a Json source from node 'history'
                    JSONObject object = new JSONObject(value);
                    JSONArray array = object.getJSONArray("history");

                    int len = array.length();
                    if (len > 0) {
                        for (int i = 0; i < len; i++) {
                            final JSONObject o = array.getJSONObject(i);
                            // Parse my data and add it to my adapter
                            adapter.add(data);
                        }
                    }
                } catch (JSONException jex) {
                    Log.e(TAG, "" + jex.getMessage());
                }
                // setListAdapter is my call to update my list view
                setListAdapter(adapter);
            }
        });
    }
}

Now just update the UI thread

private void setListAdapter(ListDataAdapter adapter){
    // my ListView 
    lvHistory.setAdapter(adapter);
}
Barns
  • 4,850
  • 3
  • 17
  • 31