Integrating Loaders and recycler view not working

493 views Asked by At

I am using a loader and a OkHttp client to get data from a news API and populate the data in a recycler view. I used a progress bar to show until the the loader is finished loading the data . But all I see is the progress bar, the recycler view is not showing up. Please help me

MainActivity.java

    public class MainActivity extends AppCompatActivity    implements     LoaderManager.LoaderCallbacks<ArrayList<News>> {

private static final int LOADER_ID = 1 ;
private String url =  "https://newsapi.org/v1/articles?source=the-times-of-india&sortBy=latest&apiKey=<API KEY>";
private ProgressBar progressBar;
private NewsAdapter mAdapter;
private RecyclerView recList;

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

    progressBar = (ProgressBar) findViewById(R.id.progress_bar);
    progressBar.setVisibility(View.VISIBLE);

    recList = (RecyclerView) findViewById(R.id.cardList);
    recList.setHasFixedSize(true);
    LinearLayoutManager llm = new LinearLayoutManager(this);
    llm.setOrientation(LinearLayoutManager.VERTICAL);
    recList.setLayoutManager(llm);
    recList.setHasFixedSize(true);
    getSupportLoaderManager().initLoader(LOADER_ID , null , this);
}


@Override
public Loader<ArrayList<News>> onCreateLoader(int id, Bundle args) {
    return new AsyncTaskLoader<ArrayList<News>>(this) {
        @Override
        public ArrayList<News> loadInBackground() {
            return makeConnectionAndParseData(url);
        }
    };
}

@Override
public void onLoadFinished(Loader<ArrayList<News>> loader, ArrayList<News> data) {

    progressBar.setVisibility(View.INVISIBLE);
    mAdapter = new NewsAdapter(data);
    recList.setAdapter(mAdapter);
    // The data is brought back here after the network call is executed in the variable data.
    // Update the recycler view here to show the list of news
    // Take care of exception cases like no network connection , invalid url and other extreme cases

}

@Override
public void onLoaderReset(Loader<ArrayList<News>> loader) {
    // Reset the recycler view . The UI should not show recycler view when the loader is reset
    // Update the UI with a text view to let the user know about the error


}




private String makeNetworkConnection(String url)
{
    OkHttpClient client = new OkHttpClient();

    try {

        Request request = new Request.Builder()
                .url(url)
                .build();

        Response response = client.newCall(request).execute();
        return response.body().toString();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }

}

private ArrayList<News> parseJsonIntoArrayList(String json)
{
    final ArrayList<News> newsArrayList;

    try {
        newsArrayList = null;
        JSONObject object = new JSONObject(json);
        JSONArray articles = object.getJSONArray("articles");
        for (int i=0 ; i<articles.length() ; i++)
        {
            JSONObject articleObjects = articles.getJSONObject(i);
            String author = articleObjects.getString("author");
            String title = articleObjects.getString("title");
            String desc = articleObjects.getString("description");
            String imageUrl = articleObjects.getString("imageUrl");
            String clickableUrl = articleObjects.getString("url");

            newsArrayList.add(new News(title,desc,imageUrl,clickableUrl,author));
        }

        return newsArrayList;
    } catch (JSONException e) {
        e.printStackTrace();
        return null;
    }

}

private ArrayList<News> makeConnectionAndParseData(String url)
{
    String jsonResponse = makeNetworkConnection(url);

    return parseJsonIntoArrayList(jsonResponse);

}}

NewsAdapter.java

    public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {

ArrayList<News> mNewsData;


public NewsAdapter(ArrayList<News> newsData)
{
    mNewsData = newsData;
}

public class NewsHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private TextView titleTv , descTv ;
    private ImageView newsImageView;

    public NewsHolder(View itemView) {
        super(itemView);

        titleTv = (TextView) itemView.findViewById(R.id.newsTitle);
        descTv = (TextView) itemView.findViewById(R.id.newsDesc);
        newsImageView = (ImageView) itemView.findViewById(R.id.newsImage);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // Handle the click item here.
    }
}

@Override
public NewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View inflatedView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.list_item , parent , false);

    return new NewsHolder(inflatedView);
}

@Override
public void onBindViewHolder(NewsHolder holder, int position) {

    News news = mNewsData.get(position);
    holder.titleTv.setText(news.getNewsTitle());
    holder.descTv.setText(news.getNewsSubtitle());
    String imageUrl = news.getImageUrl();
    Picasso.with(holder.newsImageView.getContext())
            .load(imageUrl)
            .into(holder.newsImageView);

}

@Override
public int getItemCount() {
    return mNewsData.size();
}}

In android monitor , there was

    01-10 14:55:59.319 10318-10318/com.sriram.news E/RecyclerView: No adapter attached; skipping layout

Please tell me where I have gone wrong And is my implementation of the recycler view correct? I'm still confused about recycler view.

Thanks in advance

1

There are 1 answers

0
injung On

Place

mAdapter = new NewsAdapter();
recList.setAdapter(mAdapter);

above

recList.setLayoutManager(llm);
recList.setHasFixedSize(true);

and fix NewsAdapter.java

public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {

    ArrayList<News> mNewsData;

    // remove constructor

    public void addAll(List<News> newsData) {
        mNewsData = newsData;
    }

    ...

}

MainActivity.java

@Override
public void onLoadFinished(Loader<ArrayList<News>> loader, ArrayList<News> data) {
    progressBar.setVisibility(View.INVISIBLE);
    mAdapter.addAll(data);
    mAdapter.notifyDataSetChanged();
}