Search code examples
androidjsongsonretrofit2flickr

Photos not appearing in RecyclerView


I am trying to add flickr images with their titles in a recycler view the problem encountering me is that I want to pass the images and their titles to FlickrPhoto class in the loop (please take a look above to see what I'm saying ) if you notice this line photos.add(new FlickrPhoto(title,uri)); you will see that it inside loop in enqueue function which is at the background task , So I recognize that line doesn't executed .. but when I've tried after enqueue function it works for me but ofcourse for just one image because , I'm outside the loop. I've tried many solutions but all fails

Here is my PhotoListActivity

package com.example.karim.bluecrunch;

/**
 * Created by karim on 8/26/16.
 */
public class FlickrPhoto {
    String title , image ;
    public  FlickrPhoto(String title , String image )
    {
        this.image = image;
        this.title = title;
    }
}

and here is my PhotosRecyclerViewAdapter

package com.example.karim.bluecrunch;
public class PhotosRecyclerViewAdapter extends RecyclerView.Adapter<PhotosRecyclerViewAdapter.PhotoViewHolder> {

    List<FlickrPhoto> photos = Collections.emptyList();
    Context context;
    LayoutInflater inflater;

    public PhotosRecyclerViewAdapter(Context context , List<FlickrPhoto> photos)
    {
        this.context = context;
        this.photos = photos;
        inflater = LayoutInflater.from(context);
    }

    @Override
    public PhotoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View row = inflater.inflate(R.layout.single_row,parent,false);
        return new PhotoViewHolder(row);
    }

    @Override
    public void onBindViewHolder(PhotoViewHolder holder, int position) {
        FlickrPhoto photo = photos.get(position);
        holder.textView.setText(photo.title);
        Uri uri = Uri.parse(photo.image);
        Glide.with(context).load(uri).placeholder(R.drawable.image_placeholder).crossFade().into(holder.imageView);

    }

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

    public class PhotoViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;
        private ImageView imageView;

        public PhotoViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.photoTitle);
            imageView = (ImageView) itemView.findViewById(R.id.flickrPhoto);
        }



    }
}

and here is my PhotosListActivity

package com.example.karim.bluecrunch;

public class PhotosListActivity extends AppCompatActivity {
    List<FlickrPhoto> photos ;
    ArrayList<String> photosTitles;
    ArrayList<String> photoURLS;
    String title;
    String uri;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photos_list);

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.photo_recycler_view);
        recyclerView.setLayoutManager(new GridLayoutManager(getApplicationContext(),2));
        PhotosRecyclerViewAdapter adapter = new PhotosRecyclerViewAdapter(this,getPhotos());
        recyclerView.setAdapter(adapter);
    }

    public List<FlickrPhoto> getPhotos()
    {

        photos = new ArrayList<>();

        final String API_KEY = "fdac2e9676991ac53b34651adab52518";
        final String METHOD = "flickr.photos.search";
        final String AUTH_TOKEN = "72157671978046542-6e266595ffed01f8";
        final String API_SIG = "58e08d365779a8f2e946a2b5320199e2";
        final String FORMAT = "json";
        final int CALL_BACK = 1;

        HandleRetrofit handleRetrofit = HandleRetrofit.retrofit.create(HandleRetrofit.class);
        Call<Photos> call = handleRetrofit.Photos(METHOD,API_KEY,FORMAT,CALL_BACK,AUTH_TOKEN,API_SIG);
        call.enqueue(new Callback<Photos>() {
            @Override
            public void onResponse(Call<Photos> call, Response<Photos> response) {
                Log.d("MainActivity", "Status Code = " + response.code());
                PhotosRetrofit photosRetrofit = response.body().photos;
                for (int i = 0; i < photosRetrofit.getPhoto().size(); i++) {
                    uri="https://farm"+photosRetrofit.getPhoto().get(i).getFarm()+".staticflickr.com/"+
                            photosRetrofit.getPhoto().get(i).getServer()+"/"+
                            photosRetrofit.getPhoto().get(i).getId()+"_" +
                            photosRetrofit.getPhoto().get(i).getSecret()+".jpg";

                    title= photosRetrofit.getPhoto().get(i).getTitle();

                    photos.add(new FlickrPhoto(title,uri));


                    Log.w(">>>>>>>>>>>","https://farm"+photosRetrofit.getPhoto().get(i).getFarm()+".staticflickr.com/"+
                            photosRetrofit.getPhoto().get(i).getServer()+"/"+
                            photosRetrofit.getPhoto().get(i).getId()+"_" +
                            photosRetrofit.getPhoto().get(i).getSecret()+".jpg");
                }

            }

            @Override
            public void onFailure(Call<Photos> call, Throwable t) {
                Toast.makeText(PhotosListActivity.this,"Error :"+t.getMessage(),Toast.LENGTH_LONG).show();
                Log.w("---___--- Error ",t.getMessage());
            }
        });
    /*    Log.w("Hello",uri.toString());
        Log.w("Hello",title.toString());*/
        photos.add(new FlickrPhoto("karim","https://farm9.staticflickr.com/8450/29141814932_a62977990d.jpg"));
        return photos;
    }
}

All things works fine , but the main problem at this line in my Activity

photos.add(new FlickrPhoto(title,uri));

I think it can't be done in the background tasks because this line

photos.add(new FlickrPhoto("karim","https://farm9.staticflickr.com/8450/29141814932_a62977990d.jpg"));

works fine after the enqueue function , but I don't know how to do such a trick to solve this problem .

EDIT

Please note that The loop

for (int i = 0; i < photosRetrofit.getPhoto().size(); i++) 
{
uri="https://farm"... ;
title= ..;
 **photos.add(new FlickrPhoto(title,uri));**
 Log.w(">>>>>>>>>>>","https://farm"+photosRetrofit.getPhoto()‌​.get(i).getFarm()+".‌​staticflickr.com/"+p‌​hotosRetrofit.getPho‌​to().get(i).getServe‌​r()+"/"+photosRetrof‌​it.getPhoto().get(i)‌​.getId()+"_" +photosRetrofit.getPhoto().get(i).getSecret()+".jpg");
 }

doesn't skipped because , if you try to log either title or uri inside the loop it will shown successfully in Logcat . The main problem is that this line of code photos.add(new FlickrPhoto(title,uri)); passes the data "title and uri " to the FlickrPhoto class's constructor and this operation is in the enqueue -> onResponse (Background task) and I don't know why it is not working

It is excepted to load data (Images & Titles ) into recycler view but Actually nothing happens and

I've tried a couple of things

First , before return photos () arrayList at the PhotosListActivity class I've tried to pass a fixed data to the FlickrPhoto class's Constructor And it works and images shown into recycler view

Second , I've tried to add a default constructor and setter , getter for title and image to FlickrPhoto class and initialize it on OnCreate function at PhotosListActivity class then on the enqueue I used my setter and getter and it works and load all data successfully but when I've try to run again everything gone ! :( , and I don't know why

doing setters and getters was like this FlickrPhoto.java class

package com.example.karim.bluecrunch;

/**
 * Created by karim on 8/26/16.
 */
public class FlickrPhoto {
    String title , image ;
    public FlickrPhoto(){}
    public  FlickrPhoto(String title , String image )
    {
        this.image = image;
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

}

and PostListActivity Class

package com.example.karim.bluecrunch;

import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.http.Url;

public class PhotosListActivity extends AppCompatActivity {
    List<FlickrPhoto> photos ;
    ArrayList<String> photosTitles;
    ArrayList<String> photoURLS;
    FlickrPhoto flickrPhoto ;
    String title;
    String uri;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photos_list);

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.photo_recycler_view);
        recyclerView.setLayoutManager(new GridLayoutManager(this,2));
        PhotosRecyclerViewAdapter adapter = new PhotosRecyclerViewAdapter(this,getPhotos());
        recyclerView.setAdapter(adapter);

        flickrPhoto = new FlickrPhoto();



    }

    public List<FlickrPhoto> getPhotos()
    {

        photos = new ArrayList<>();

        final String API_KEY = "fdac2e9676991ac53b34651adab52518";
        final String METHOD = "flickr.photos.search";
        final String AUTH_TOKEN = "72157671978046542-6e266595ffed01f8";
        final String API_SIG = "58e08d365779a8f2e946a2b5320199e2";
        final String FORMAT = "json";
        final int CALL_BACK = 1;

        HandleRetrofit handleRetrofit = HandleRetrofit.retrofit.create(HandleRetrofit.class);
        Call<Photos> call = handleRetrofit.Photos(METHOD,API_KEY,FORMAT,CALL_BACK,AUTH_TOKEN,API_SIG);
        call.enqueue(new Callback<Photos>() {
            @Override
            public void onResponse(Call<Photos> call, Response<Photos> response) {
                Log.d("MainActivity", "Status Code = " + response.code());
                PhotosRetrofit photosRetrofit = response.body().photos;
                //photosRetrofit.getPhoto().size()
                for (int i = 0; i < photosRetrofit.getPhoto().size(); i++) {
                    uri="https://farm"+photosRetrofit.getPhoto().get(i).getFarm()+".staticflickr.com/"+
                            photosRetrofit.getPhoto().get(i).getServer()+"/"+
                            photosRetrofit.getPhoto().get(i).getId()+"_" +
                            photosRetrofit.getPhoto().get(i).getSecret()+".jpg";

                    title= photosRetrofit.getPhoto().get(i).getTitle();

                    flickrPhoto.setImage(uri);
                    flickrPhoto.setTitle(title);

                    photos.add(new FlickrPhoto(flickrPhoto.getTitle(),flickrPhoto.getImage()));


                    Log.w("++++++++++++",photosRetrofit.getPhoto().get(i).getTitle());

                    Log.w(">>>>>>>>>>>","https://farm"+photosRetrofit.getPhoto().get(i).getFarm()+".staticflickr.com/"+
                            photosRetrofit.getPhoto().get(i).getServer()+"/"+
                            photosRetrofit.getPhoto().get(i).getId()+"_" +
                            photosRetrofit.getPhoto().get(i).getSecret()+".jpg");



                }

            }

            @Override
            public void onFailure(Call<Photos> call, Throwable t) {
                Toast.makeText(PhotosListActivity.this,"Error :"+t.getMessage(),Toast.LENGTH_LONG).show();
                Log.w("---___--- Error ",t.getMessage());
            }
        });
    /*    Log.w("Hello",uri.toString());
        Log.w("Hello",title.toString());*/
        photos.add(new FlickrPhoto("karim","https://farm9.staticflickr.com/8450/29141814932_a62977990d.jpg"));
        return photos;
    }
}

Solution

  • The problem is that RecyclerView does not automatically update after adding elements to the array list with its data. You need to call notifyDataSetChanged() on your adapter to force this update.