Reputation: 305
Struggling with this so bad!
I created a viewpager with 2 pages, one being an audio player that is working perfectly, and the second page being the news list. It's a fragment with a recyclerview as a child.
Gradle
dependencies {
implementation 'com.android.support.constraint:constraint-layout:1.1.1'
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project(':library')
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.android.volley:volley:1.1.0'
}
ViewPager Adapter
private class mPagerAdapter extends FragmentStatePagerAdapter {
public mPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int pos) {
switch(pos) {
case 0: return PlayerPage.newInstance();
case 1: return News.newInstance();
default: return PlayerPage.newInstance();
}
}
@Override
public int getCount() {
return 2;
}
}
News Fragment
public class News extends Fragment {
private List<NewsBlueprint> newsList = new ArrayList<>();
private RecyclerView recyclerView;
private NewsAdapter newsAdapter;
private ProgressBar progressBar;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_news, container, false);
progressBar = (ProgressBar) v.findViewById(R.id.progress_bar);
recyclerView = (RecyclerView) v.findViewById(R.id.news_recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getBaseContext()));
recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(View.DRAWING_CACHE_QUALITY_HIGH);
// Fill with test
newsList.add(new NewsBlueprint("hi", "hi", "hi", "hi"));
try {
new Thread(new Runnable() {
@Override
public void run() {
newsAdapter = new NewsAdapter(newsList);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
recyclerView.setAdapter(newsAdapter);
}
});
}
}).start();
} catch (Exception ex) {
ex.printStackTrace();
}
getNews();
return v;
}
public static News newInstance() {
return new News();
}
public void getNews() {
newsList.clear();
progressBar.setVisibility(View.VISIBLE);
String url = "I removed link for privacy on StackOverflow";
RequestQueue mRequestQueue;
Cache cache = new DiskBasedCache(getActivity().getCacheDir(), 1024 * 1024); // 1MB cap
Network network = new BasicNetwork(new HurlStack());
mRequestQueue = new RequestQueue(cache, network);
mRequestQueue.start();
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
try {
JSONObject current = null;
for (int i = 0; i < response.length(); i++) {
current = response.getJSONObject(i);
// Get the topStory's title from the volume information
String topStoryTitle = current.getJSONObject("title").getString("rendered");
// Get the current topStory's section information
// The appropriate section that the story belongs to is contained in the subsection
String topStorySection = current.getJSONObject("content").getString("rendered");
// Get the date on which the news was published
// Extract date information from the JSON response
String topStoryDateTime = current.getString("date");
// Get the story url
String storyUrl = current.getString("link");
JSONObject res = current.getJSONObject("_links");
JSONArray multimedia = res.getJSONArray("wp:featuredmedia");
String href = multimedia.getJSONObject(0).getString("href");
newsList.add(new NewsBlueprint(topStoryTitle, topStorySection, topStoryDateTime, href));
Toast.makeText(getContext(), "Looping " + topStoryTitle, Toast.LENGTH_SHORT).show();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getContext(), "Make sure you are connected to the internet", Toast.LENGTH_SHORT).show();
}
});
mRequestQueue.add(jsonArrayRequest);
newsAdapter.notifyDataSetChanged();
progressBar.setVisibility(View.INVISIBLE);
}
}
News Adapter
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.MyViewHolder>{
private List<NewsBlueprint> news;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public ImageView thumbnail;
public MyViewHolder(View view) {
super(view);
title = view.findViewById(R.id.title);
thumbnail = view.findViewById(R.id.thumbnail);
}
}
public NewsAdapter(List<NewsBlueprint> newsList) {
this.news = newsList;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.news_row, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
NewsBlueprint newsBlueprint = news.get(position);
holder.title.setText(newsBlueprint.getTitle());
// Set thumbnail
//Picasso.get().load(newsBlueprint.getImageURL()).into(holder.thumbnail);
}
public int getItemCount() {
return news.size();
}
}
News Blueprint
Is just a class to represent a news item
The result is an empty RecyclerView
I made sure the data returned from the JSON is correct as I displayed the title of a news in a Toast.
Upvotes: 0
Views: 434
Reputation:
newsAdapter.notifyDataSetChanged();
must be called after you've modified the newsList (jsonArrayRequest runs in the background, the function calling it continues directly without waiting for the response), not after you've started getting the news. Moreover, it's not a good idea to modify an array of an adapter from another Thread and it's totally wrong to create an Adapter on a background Thread.
Upvotes: 4