androidandroid-recyclerviewasynctaskloader

Android: How to add AsyncTaskLoader to this RecyclerView


[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.


Solution

  • 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();
        }