【问题标题】:RecyclerView items are lost after come back to activityRecyclerView 项目在恢复活动后丢失
【发布时间】:2019-06-18 13:23:54
【问题描述】:

在我的应用程序中,当用户单击“添加图片”按钮时,它允许用户从图库中选择图片并将其加载到回收站视图中。但是,当用户通过按返回按钮返回上一个活动并再次按“添加图像”按钮时,以前选择的图像会从 Recyclerview 中丢失。我已经尝试过 onSavedInstanceState() 但它不适用于我的情况。我检查了各种 StackOverflow 解决方案,但没有什么对我有用。

这是我的主要活动,称为 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);
    }
}

在这里,当单击工具栏中的“添加图像”选项按钮时,它会打开 GridViewActivity,用户可以在其中从图库中添加图像,但是当用户返回上一个活动,即 RecorderActivity 并再次单击“添加图片”按钮,之前选择的图片会从recyclerView中丢失。

这是我的 GridViewActivity 代码

这是更新的代码,我使用 Gson 将 ArrayList 保存到共享首选项,在 onCreate() 方法中,我从 sharedPreferences 中检索了 ArrayList 并将其设置为回收站视图,但回收站视图仅显示卡片而不显示卡片内的图像。这就是问题!在 sharedPreferences 中,我使用一个计数变量来指示 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();
        }
    }

}

这是 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);
    }

这是 Images.java 类

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));
    }
}

这是 ImageAdapter 类代码

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);
    }
}

这是输出:

从图库中选择 4 张图片后,它会显示在 GridViewActivity 的 recyclerview 中

但是在按下返回按钮并再次进入 GridViewActivity 后,recyclerview 显示如下

请不要将其标记为重复问题。 我对此进行了搜索,但没有适合我的解决方案。 请告诉我我应该怎么做才能解决这个问题!

【问题讨论】:

  • 只是为了清楚。您正在从GridViewActivity 的图库中选择图像。选定的图像将发送回RecorderActivity。当您从RecorderActivity 再次转到GridViewActivity 时,之前选择的图像没有被选择?
  • 我不知道你想发生什么,但每次你去GridViewActivity 你正在创建一个新的活动实例。所以一切都会被清除,因为使用后退按钮就像销毁当前活动并恢复上一个活动一样。
  • NO 当用户单击它时,我可以选择在记录器活动中选择一个图像 GridviewActivity 开始,我有两个选项 sect 来自画廊或相机的图像,并且所选图像显示在回收器视图中但是当我回到 RecorderActivity 并再次进入 GridViewActivity 时,recyclerview 内容丢失了。

标签: android android-studio arraylist android-recyclerview recyclerview-layout


【解决方案1】:

发生这种情况是因为您每次从 Gallery 回来时都会创建一个新的 ArrayList。

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();

因此,当用户没有从图库中选择任何图像然后在 onActivityResult() 中时,您不会获得任何图像 uri,但在此之前您创建一个新的 ArrayList 并重新初始化您的回收视图。

这就是您的回收站视图不显示任何项目的原因。

将该 ArrayList 保留为类成员变量,并根据 onActivityResult() 继续添加/删除数据。

【讨论】:

  • 好的,但是当我从 GridViewActivity 返回到 RecorderActivity 并返回到 GridViewActivity 时,recyclerview 会丢失它的内容。在这种情况下,不会调用 onActivityResult() 方法。那么可能是什么问题
  • 因为您没有在 GridViewActivity 的任何位置保存选定的图像 uri。一旦您从它向后按下以降落在 RecorderActivity 上,GridViewActivity 就会被破坏。如果要保存图像列表,则需要将在 onActivityResult() 中收到的 Uris 保存到一些持久性存储中,例如 Db、共享首选项。然后,当您从“添加图像”打开 GridViewActivity 时,您需要从该持久存储中加载 Uris 列表并加载并显示您的 recyclerview 中的所有图像。
  • 据你说,我使用 Gson 将我的 arraylist 保存到 SharedPreferences,但是在从 sharedprefrences recyclerview 获取 arraylist 后,recyclerview 可以正确显示卡片,但图像没有显示在卡片内
  • 您能否将您的回收站视图适配器的 onBindViewHolder() 代码与您传递给适配器的数据一起添加?
  • 我用更新的代码和输出截图更新了我的问题,请查看它
【解决方案2】:

用这个替换你的 Activity 并尝试:

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();
        }
    }

}

【讨论】:

  • 好的,我会检查
  • java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“int java.util.ArrayList.size()”
  • 当我在活动 recyclerview 回来时只显示空卡片图像未显示。与我上传有关问题的输出 scrrenshot 的问题相同
  • 您是否尝试过调试代码并检查 arraylist 中的值?我认为当您回来时,您的数组列表项值正在更新或为空。
  • 如果你已经注意到,你的列表计数保持不变,只是数据被空值改变,我认为你应该尝试调试一次值
猜你喜欢
  • 1970-01-01
  • 2022-12-23
  • 2016-11-06
  • 1970-01-01
  • 1970-01-01
  • 2018-10-31
  • 2017-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多