1

[Update] Added repository link to download the project

I'm having this activity which connects to a URL to fetch data and display it using RecyclerView with a custom adapter. How can I edit this code to use AsyncTaskLoader instead of AsyncTask? here's the repository to download the very simple project Soonami tutorial app

public class MainActivity extends AppCompatActivity {

  private RecyclerView recyclerView;
  public static QuakesAdapter quakesAdapter;
  public static ArrayList<Event> eventsList = new ArrayList<>();
  public static final String USGS_REQUEST_URL =
        "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2018-01-01&endtime=2018-12-01&minmagnitude=6&limit=50";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    recyclerView = findViewById(R.id.recycler_view);
    quakesAdapter = new QuakesAdapter(this, eventsList);

    //defining recyclerView and setting the adapter

    quakesAdapter.notifyDataSetChanged();

    FetchData fetchData= new FetchData();
    fetchData.execute();
}


private class FetchData extends AsyncTask<String, Void, ArrayList<Event>> {

    String myDdata = "";
    String line = "";

    @Override
    protected ArrayList<Event> doInBackground(String... params) {

        try {

            //opening the connection

            if (httpURLConnection.getResponseCode() == 200) {
                InputStream inputStream = httpURLConnection.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

                while(line != null){
                    line = bufferedReader.readLine();
                    myDdata = myDdata + line;
                }

                JSONObject jsonObject = new JSONObject(myDdata);
                eventsList.clear();

                JSONArray jsonArray = jsonObject.getJSONArray("features");

                for(int i = 0; i < jsonArray.length(); i++){

                    //getting values of the 3 attributes

                    eventsList.add(new Event(title, time, tsunamiAlert));
                }

                if (inputStream != null) {
                    inputStream.close();
                }

            } else {
                Log.e("Connection Error: ", "Error response code: " + httpURLConnection.getResponseCode());
            }

            if (httpURLConnection != null) {
                httpURLConnection.disconnect();
            }

        }
        catch (MalformedURLException e) {
            e.printStackTrace();
        }

        catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(ArrayList<Event> result) {
        super.onPostExecute(result);
        quakesAdapter.notifyDataSetChanged();
    }
  }
}

I have tested multiple examples but they have different codes and triggers multiple errors with my code like this one and still looking for a solution which makes my code works fine.

PHP User
  • 2,350
  • 6
  • 46
  • 87

2 Answers2

2

Set adpter in your recyclerview and then call the loader like this way:

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Event>> {
        {

            private RecyclerView recyclerView;
            public static QuakesAdapter quakesAdapter;
            public static ArrayList<Event> eventsList = new ArrayList<>();
            public static final String USGS_REQUEST_URL =
                    "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2018-01-01&endtime=2018-12-01&minmagnitude=6&limit=50";

            @Override
            protected void onCreate (Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            recyclerView = findViewById(R.id.recycler_view);
            quakesAdapter = new QuakesAdapter(this, eventsList);

            //defining recyclerView and setting the adapter

            recyclerView.setAdapter(quakesAdapter);

            getSupportLoaderManager().initLoader(1, null, this).forceLoad();

        }

            @Override
            public Loader<List<Event>> onCreateLoader ( int id, Bundle args){
            return new FetchData(MainActivity.this);
        }
            @Override
            public void onLoadFinished (Loader < List < Event >> loader, List < Event > data){
            quakesAdapter.setData(data);
        }
            @Override
            public void onLoaderReset (Loader < List < Event >> loader) {
            quakesAdapter.setData(new ArrayList<Event>());

}

Performs actual task in background and returns the result.

private static class FetchData extends AsyncTaskLoader<List<Event>>{

        String myDdata = "";
        String line = "";
           public FetchData(Context context) {
            super(context);
        }
        @Override
        public List<Event> loadInBackground () {

            try {
                List<Event> list = new ArrayList<Event>();

                //opening the connection

                if (httpURLConnection.getResponseCode() == 200) {
                    InputStream inputStream = httpURLConnection.getInputStream();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

                    while (line != null) {
                        line = bufferedReader.readLine();
                        myDdata = myDdata + line;
                    }

                    JSONObject jsonObject = new JSONObject(myDdata);

                    JSONArray jsonArray = jsonObject.getJSONArray("features");

                    for (int i = 0; i < jsonArray.length(); i++) {

                        //getting values of the 3 attributes

                        eventsList.add(new Event(title, time, tsunamiAlert));
                    }

                    if (inputStream != null) {
                        inputStream.close();
                    }

                } else {
                    Log.e("Connection Error: ", "Error response code: " + httpURLConnection.getResponseCode());
                }

                if (httpURLConnection != null) {
                    httpURLConnection.disconnect();
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            }

            return eventsList;
        }
    }

Add a method in your adapter like this:

public void setData(List<Event> data) {
        this.data=data;
        notifyDataSetChanged();
    }
PHP User
  • 2,350
  • 6
  • 46
  • 87
Sultan Mahmud
  • 1,245
  • 8
  • 18
0

Which kind of error do you encounter?

I suggest using Java Interface and CallBack method for your AsynkTask, in this scenario, whenever your AsynkTask task is done, it notify the Activity with that callback method and you can execute notifyDataSetChange method of the adapter.

  • I'm still learning so I'm not familiar with your hint and I need to use AsyncTaskLoader to ractice Udacity course – PHP User Apr 24 '19 at 18:33
  • Ok, java callback is a design pattern which uses a [Java Interface](http://tutorials.jenkov.com/java/interfaces.html). In this design pattern, you create a Java Interface (which is a bit like java class but only contains method signatures) in your AsynkTask class, then implement that Interface in your Activity, whenever you execute the methods of your interface in your AsynkTask class, the similar methods in your activity will be triggered. In the tutorial link that you provided in your question, this pattern is used. – Shayan Khaksar Apr 24 '19 at 18:40