0

In my app when the user clicked on "Add Images" button it allows the user to select images from gallery and load it into the Recycler View. But when user come back to a previous activity by pressing back button and again he pressed "Add Images" button the previously selected images are lost from Recyclerview. I have tried onSavedInstanceState() but it not works in my case. I checked various StackOverflow solutions but nothing is working for me.

Here is my main activity called RecorderActivity

public class RecorderActivity extends AppCompatActivity {
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.getItemId()==R.id.add_images) {
            Intent intent = new Intent(context,GridViewActivity.class);
            intent.putExtra("call","1");
            startActivity(intent);
        }
        else if(item.getItemId()==R.id.add_pdf_ppt) {
            Toast.makeText(context, "Under Development", Toast.LENGTH_SHORT).show();
        }
        else if(item.getItemId()==R.id.rearrange_items) {
            Intent i=new Intent(RecorderActivity.this,GridViewActivity.class);
            i.putExtra("call","2");
            startActivity(i);
        }
        return super.onOptionsItemSelected(item);
    }
}

Here when "Add Images" options button from the toolbar is clicked it opens GridViewActivity where the user can add images from the gallery but when user come back to previous activity i.e. RecorderActivity and clicked again "Add Images" button, the previously selected images are lost from recyclerView.

Here is my GridViewActivity code

This is updated code where I saved ArrayList to shared preferences by using Gson and in onCreate() method I have retrieved ArrayList from sharedPreferences and set it to the recycler view but recyclerview shows the cards only not images inside the card. This is the problem! In sharedPreferences I'm uses one count variable to indicates total images in sharedPreferences.

public class GridViewActivity extends AppCompatActivity {
    Context context=GridViewActivity.this;
    RecyclerView recyclerView;
    int PICK_IMAGE_MULTIPLE=1;
    static ArrayList<Images> arrayList;
    static ImagesAdapter imagesAdapter;
    AutoFitGridLayoutManager autoFitGridLayoutManager;
    SharedPref sharedPref;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_grid_view);
        recyclerView=findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        autoFitGridLayoutManager=new AutoFitGridLayoutManager(context,250);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setLayoutManager(autoFitGridLayoutManager);
        arrayList=new ArrayList<>();
        sharedPref=new SharedPref(context);
        if (sharedPref.getCount()==0) {
            Toast.makeText(context, "No images...", Toast.LENGTH_SHORT).show();
        }
        else {
            Gson gson=new Gson();
            String response=sharedPref.getImages();
            arrayList=gson.fromJson(response,new TypeToken<ArrayList<Images>>(){}.getType());
            Log.d("ROHIT", String.valueOf(arrayList.size()));
            imagesAdapter=new ImagesAdapter(context,arrayList);
            setRecyclerView();
        }
    }

    public void setRecyclerView() {
        ItemTouchHelper.Callback callback=new ItemMoveCallback(imagesAdapter);
        ItemTouchHelper touchHelper=new ItemTouchHelper(callback);
        touchHelper.attachToRecyclerView(recyclerView);
        recyclerView.setAdapter(imagesAdapter);
    }

     @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.getItemId()==R.id.add_imges_cam) {
            //open camera
        }
        else if(item.getItemId()==R.id.add_imges_gallery) {
            //open gallery to select images
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,"Select Picture"), PICK_IMAGE_MULTIPLE);
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        int count=0;
        if(requestCode==PICK_IMAGE_MULTIPLE && resultCode==RESULT_OK) {
            String[] filePath = {MediaStore.Images.Media.DATA};

            if (data.getData() != null) {
                //if single image is selected
                Uri imageUri = data.getData();
                Cursor cursor = getContentResolver().query(imageUri, filePath, null, null, null);
                cursor.moveToFirst();
                arrayList.add(new Images(imageUri.toString()));
                cursor.close();
            } else {
                if (data.getClipData() != null) {
                    ClipData mClipData = data.getClipData();
                    for (int i = 0; i < mClipData.getItemCount(); i++) {
                        ClipData.Item item = mClipData.getItemAt(i);
                        Uri uri = item.getUri();
                        // Get the cursor
                        Cursor cursor = getContentResolver().query(uri, filePath, null, null, null);
                        // Move to first row
                        cursor.moveToFirst();
                        arrayList.add(new Images(uri.toString()));
                        count++;
                        cursor.close();
                    }
                }
            }
            imagesAdapter=new ImagesAdapter(context,arrayList);
            sharedPref.save(arrayList);
            Log.d("ROHIT","data saved arraylist"+arrayList.size());
            sharedPref.updateCount(count);
            Log.d("ROHIT","data saved");
            setRecyclerView();
        }
    }

}

This is SharedPref.java

public class SharedPref {
    SharedPreferences sharedPreferences;
    SharedPreferences.Editor editor;
    Context context;

    public SharedPref(Context context) {
        this.context=context;
        sharedPreferences=context.getSharedPreferences("Grid_images",Context.MODE_PRIVATE);
        editor=sharedPreferences.edit();
    }

    public void save(ArrayList<Images> arrayList) {
        Gson gson=new Gson();
        Object src;
        String json=gson.toJson(arrayList);
        editor.putString("grid_images",json);
        editor.apply();
        editor.commit();
    }

    public void updateCount(int i) {
        editor.putInt("images_count",i);
        editor.apply();
        editor.commit();
    }

    public int getCount() {
        return sharedPreferences.getInt("images_count",0);
    }

    public String getImages() {
        return sharedPreferences.getString("grid_images",null);
    }

This is Images.java class

public class Images implements Parcelable {
    private String image;

    public Images(String image) {
        this.image=image;
    }

    protected Images(Parcel in) {
        image = in.readString();
    }

    public static final Creator<Images> CREATOR = new Creator<Images>() {
        @Override
        public Images createFromParcel(Parcel in) {
            return new Images(in);
        }

        @Override
        public Images[] newArray(int size) {
            return new Images[size];
        }
    };

    public String getImage() {
        return image;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(String.valueOf(image));
    }
}

This is ImageAdapter class code

public class ImagesAdapter extends RecyclerView.Adapter<ImagesAdapter.MyViewHolder> implements ItemMoveCallback.ItemTouchHelperContract {
    ArrayList<Images> images;
    Context context;

    public class MyViewHolder extends RecyclerView.ViewHolder {
        ImageView imageView;
        View rowView;
        ImageButton bt_remove;
        public MyViewHolder(View itemView) {
            super(itemView);
            rowView=itemView;
            imageView=itemView.findViewById(R.id.imageview);
            bt_remove=itemView.findViewById(R.id.bt_delete);
        }
    }

    public ImagesAdapter(Context context,ArrayList<Images> images) {
        this.context=context;
        this.images=images;
    }

    public ImagesAdapter(Context context) {
        this.context=context;
    }
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.images_grid,parent,false);
        MyViewHolder myViewHolder=new MyViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, final int position) {
        Images current_image=images.get(position);
        holder.imageView.setImageURI(Uri.parse(current_image.getImage()));

        holder.bt_remove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                images.remove(position);
                notifyItemRemoved(position);
                notifyItemRangeChanged(position,images.size());
            }
        });
    }

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

    @Override
    public void onRowMoved(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(images, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(images, i, i - 1);
            }
        }
        notifyItemMoved(fromPosition, toPosition);
    }

    @Override
    public void onRowSelected(MyViewHolder myViewHolder) {
        myViewHolder.rowView.setBackgroundColor(context.getResources().getColor(R.color.recycler_drag));
    }

    @Override
    public void onRowClear(MyViewHolder myViewHolder) {
        myViewHolder.rowView.setBackgroundColor(Color.WHITE);
    }
}

Here is the output:

After selecting 4 images from gallery it is displayed in recyclerview in GridViewActivity enter image description here

But after pressing back button and go again to GridViewActivity the recyclerview display like this enter image description here

Please Do not mark it as a Duplicate Question. I search about this but no solution is worked for me. Please tell me what should I have to do in order to fix this problem!

Rohit Suthar
  • 967
  • 9
  • 22
  • Just to be clear. You are selecting images from gallery in `GridViewActivity`. Selected images are send back to `RecorderActivity`. When you're going again to `GridViewActivity` from `RecorderActivity`, previously selected images are not selected? – DawidJ Jan 24 '19 at 18:17
  • I do not know what you want to happen but everytime you go to `GridViewActivity` you are creating a new instance of the Activity. So everything will be cleared because using a back button is simply like destroying the current activity and resume the previous activity. – Xenolion Jan 24 '19 at 18:18
  • NO I have the option to select an image in recorder activity when the user clicked on it GridviewActivity starts where I have two option sect image from gallery or from the camera and the selected image is displayed in recycler view but when I come back to RecorderActivity and go again to GridViewActivity recyclerview contents are lost. – Rohit Suthar Jan 24 '19 at 18:20

2 Answers2

1

This is happening because you are creating a new ArrayList everytime you come back from Gallery.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    arrayList=new ArrayList<>();
    ...
    // and then you are re-initializing your recycler view 
    imagesAdapter=new ImagesAdapter(context,arrayList);
    setRecyclerView();

So when the user does not pick any image from the gallery then inside onActivityResult() you do not get any image uri, but before that you create a new ArrayList and re-initialize your recyclerview.

That is why your recycler view shows no items.

Keep that ArrayList as a class member variable and keep adding/removing data based on onActivityResult().

Vishal Arora
  • 2,524
  • 2
  • 11
  • 14
  • Ok thats fine but when I'm go back from GridViewActivity to RecorderActivity and come back to GridViewActivity recyclerview losts it contents. In this case onActivityResult() method is not invoked. so what could be problem – Rohit Suthar Jan 24 '19 at 18:27
  • Because you are not saving the selected image uris anywhere in GridViewActivity. And GridViewActivity gets destroyed once you back press from it to land on RecorderActivity. If you want to save the list of images then you need to save their Uris that you receive in onActivityResult() to some persistent storage such as Db, Shared Preferences. And then when you open GridViewActivity from "ADD Images" then you need to load the list of Uris from that persistent storage and load and show all the images in your recyclerview. – Vishal Arora Jan 24 '19 at 18:32
  • According to you I saved my arraylist to SharedPreferences using Gson but after getting arraylist from sharedprefrences recyclerview is showing cards properly but image is not showing inside card – Rohit Suthar Jan 24 '19 at 19:53
  • Can you add the code for onBindViewHolder() of your recycler view adapter along with the data you are passing to the adapter? – Vishal Arora Jan 24 '19 at 19:55
  • I upadated my question with upadated code and output screenshots please review it – Rohit Suthar Jan 24 '19 at 20:31
  • Please add the code for ImagesAdapter and Images Class. – Vishal Arora Jan 24 '19 at 20:37
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/187287/discussion-between-vishal-arora-and-rohit-suthar). – Vishal Arora Jan 24 '19 at 20:53
0

Replace your Activity with this and try:

public class GridViewActivity extends AppCompatActivity {
    Context context=GridViewActivity.this;
    RecyclerView recyclerView;
    int PICK_IMAGE_MULTIPLE=1;
    static ArrayList<Images> arrayList;
    static ImagesAdapter imagesAdapter;
    AutoFitGridLayoutManager autoFitGridLayoutManager;
    SharedPref sharedPref;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_grid_view);
        recyclerView=findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        autoFitGridLayoutManager=new AutoFitGridLayoutManager(context,250);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setLayoutManager(autoFitGridLayoutManager);

        arrayList=new ArrayList<>();                        // move this line above adapter initialization
        imagesAdapter=new ImagesAdapter(context,arrayList);

        setRecyclerView();                               // forgot to invoke this method here. 

        sharedPref=new SharedPref(context);
        if (sharedPref.getCount()==0) {
            Toast.makeText(context, "No images...", Toast.LENGTH_SHORT).show();
        }
        else {
            Gson gson=new Gson();
            String response=sharedPref.getImages();
            arrayList=gson.fromJson(response,new TypeToken<ArrayList<Images>>(){}.getType());
            Log.d("ROHIT", String.valueOf(arrayList.size()));
            imagesAdapter.notifyDataSetChanged();    // change is here
        }
    }

    public void setRecyclerView() {
        ItemTouchHelper.Callback callback=new ItemMoveCallback(imagesAdapter);
        ItemTouchHelper touchHelper=new ItemTouchHelper(callback);
        touchHelper.attachToRecyclerView(recyclerView);
        recyclerView.setAdapter(imagesAdapter);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.getItemId()==R.id.add_imges_cam) {
            //open camera
        }
        else if(item.getItemId()==R.id.add_imges_gallery) {
            //open gallery to select images
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,"Select Picture"), PICK_IMAGE_MULTIPLE);
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        int count=0;
        if(requestCode==PICK_IMAGE_MULTIPLE && resultCode==RESULT_OK) {
            String[] filePath = {MediaStore.Images.Media.DATA};

            if (data.getData() != null) {
                //if single image is selected
                Uri imageUri = data.getData();
                Cursor cursor = getContentResolver().query(imageUri, filePath, null, null, null);
                cursor.moveToFirst();
                arrayList.add(new Images(imageUri.toString()));
                cursor.close();
            } else {
                if (data.getClipData() != null) {
                    ClipData mClipData = data.getClipData();
                    for (int i = 0; i < mClipData.getItemCount(); i++) {
                        ClipData.Item item = mClipData.getItemAt(i);
                        Uri uri = item.getUri();
                        // Get the cursor
                        Cursor cursor = getContentResolver().query(uri, filePath, null, null, null);
                        // Move to first row
                        cursor.moveToFirst();
                        arrayList.add(new Images(uri.toString()));
                        count++;
                        cursor.close();
                    }
                }
            }

            sharedPref.save(arrayList);
            Log.d("ROHIT","data saved arraylist"+arrayList.size());
            sharedPref.updateCount(count);
            Log.d("ROHIT","data saved");
            imagesAdapter.notifyDataSetChanged();
        }
    }

}
Deep Patel
  • 2,584
  • 2
  • 15
  • 28
  • Ok i will check – Rohit Suthar Jan 25 '19 at 05:42
  • java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference – Rohit Suthar Jan 25 '19 at 05:48
  • when i came back in activity recyclerview displays only empty cards image is not displaying. Same problem as i have uploaded ouput scrrenshot on question – Rohit Suthar Jan 25 '19 at 05:50
  • have you tried debugging your code and check for the values in arraylist? I think when you are coming back, your arraylist item values are getting updated or null. – Deep Patel Jan 25 '19 at 05:54
  • If you have noted, count of your list remains same, just the data is getting changed with empty values, I think you should try debugging for values once – Deep Patel Jan 25 '19 at 05:55
  • NO I debug my code, I know what is happening when it gets arraylist back from sharedPreferences I debug and check the uri content it is correct not null but image is not showing. I also tried to get the Uri and pass it to some another activity and set this Uri to display image in imageview but it is sending Uri correctly to the another activity but image is not showiing – Rohit Suthar Jan 25 '19 at 05:56
  • Finally I got what is happening. When I send Uri to some another activity before storing it to sharedPref it is displaying image, but when I get Uri from SharedPref and then i tried to display image it is not showing. So the prolem is with Gson but what problem it is? – Rohit Suthar Jan 25 '19 at 06:01
  • Please try now. with updated answer. Change is in onCreate > else condition – Deep Patel Jan 25 '19 at 06:05
  • Now after selecting images from gallery it is not showing in recyclerview – Rohit Suthar Jan 25 '19 at 06:08
  • Please give it a last try with a line having comment // forgot to invoke this method here. – Deep Patel Jan 25 '19 at 06:17
  • I have tried but when i come back to activity now it also not displays any card in recyclerview It just shows only empty blank activity – Rohit Suthar Jan 25 '19 at 06:24