Reputation:
I have a simple RecyclerView. that shows a bunch of images fetched from an API. but when I run the app the RecyclerView doesn't show any. when I debug it shows that my list is empty! I assume the issue relies on the loadimages function. but I have tried before with a simple TextView and it worked.I'm still new to this and I'm just practicing.
Main Activity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
MallsAdapter adapter = new MallsAdapter(getApplicationContext());
recyclerView.setAdapter(adapter);
}
Adapter Activity:
public class MallsAdapter extends RecyclerView.Adapter<MallsAdapter.MallsViewHolder> {
public static class MallsViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public LinearLayout containerView;
public MallsViewHolder(@NonNull View itemView) {
super(itemView);
containerView = itemView.findViewById(R.id.pics_row);
imageView = itemView.findViewById(R.id.flowers_pic);
}
}
public List<Flowers> images = new ArrayList<>();
private static List<Drawable> drawables = new ArrayList<>();
private RequestQueue requestQueue;
public MallsAdapter(Context context) {
requestQueue = Volley.newRequestQueue(context);
loadImages();
}
@NonNull
@Override
public MallsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.malls_item, parent, false);
return new MallsViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MallsViewHolder holder, int position) {
holder.imageView.setBackground(drawables.get(position));
}
@Override
public int getItemCount() {
if (images != null) {
return images.size();
} else {
return 0;
}
}
public static class DownloadImage extends AsyncTask<String, Void, Drawable> {
@Override
protected Drawable doInBackground(String... strings) {
return downloadImage(strings[0]);
}
@Override
protected void onPostExecute(Drawable drawable) {
drawables.add(drawable);
}
private Drawable downloadImage(String urlLink) {
URL url;
InputStream in;
BufferedInputStream buf;
try {
url = new URL(urlLink);
in = url.openStream();
buf = new BufferedInputStream(in);
Bitmap bMap = BitmapFactory.decodeStream(buf);
return new BitmapDrawable(bMap);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
private void loadImages() {
String url = "https://pixabay.com/api/?key=15507399-305bf88eb0892f7cdf58fb66b&image_type=photo&pretty=true&q=yellow+flowers";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray hits = response.getJSONArray("hits");
for (int i = 0; i < hits.length(); i++) {
JSONObject pics = hits.getJSONObject(i);
images.add(new Flowers(pics.getString("id"), pics.getString("largeImageURL")));
}
for (int i = 0; i < images.size(); i++) {
Flowers flowers = new Flowers(images.get(i).getId(), images.get(i).getImageURL());
new DownloadImage().execute(flowers.getImageURL());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("test", "Error", error);
}
});
requestQueue.add(request);
}
Upvotes: 0
Views: 82
Reputation: 1387
2 things: first, the adapter shouldn't have any knowledge how your data is fetched, in fact it's not even its responsibility to do that job. In an MVVM architecture for example you'd have your activity calling the ViewModel, which in turn calls the repository to fetch the data, then, once the data is obtained, the activity passes it on to the adapter.
Second, and most important for your problem, when your adapter receives new data your adapter won't guess there's new stuff to render, so whenever there is new data it should call notifyDataSetChanged
, which will in turn call getItemCount
and onBindViewHolder
to refresh your list.
Example:
// On your adapter
public void submitData(List<MyData> data) {
this.data = data;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return data.size();
}
Upvotes: 1