简体   繁体   English

无法使用 URI 在 RecyclerView 中设置图像

[英]Can't set image in RecyclerView using URI

I'm working an app which pulls info from the SQLite database and displays it in a RecyclerView.我正在开发一个应用程序,它从 SQLite 数据库中提取信息并将其显示在 RecyclerView 中。 I am having trouble setting the image in the RecyclerView using the URI.我无法使用 URI 在 RecyclerView 中设置图像。

                    Uri mImageUri=data.getData();
                    imgUri = data.getData();

                    // Get path (Path will be stored in database)
                    String imgToString = imgUri.toString();

                    // Get URI back from path
                    imgUri = Uri.parse(imgToString);

                    // Set ImageView
                    plainImage.setImageURI(imgUri);

                    // Set Glide image
                    Glide.with(this)
                            .asBitmap()
                            .load(imgUri)
                            .into(image);

This is a snippet from my OnActivityResult() after choosing pictures from gallery.这是从图库中选择图片后我的 OnActivityResult() 的片段。 Setting the images in a basic activity using this code works.使用此代码在基本活动中设置图像是可行的。 I'm taking the toString() from the URI and saving this in my database.我从 URI 中获取 toString() 并将其保存在我的数据库中。 (I will be moving selected pictures to an app folder before taking URIs in final version of app) (在最终版本的应用程序中获取 URI 之前,我会将选定的图片移动到应用程序文件夹)

However when I retrieve the URI strings from the database, parse them back into URIs, and attempt to set the image in the RecyclerView this method no longer works.但是,当我从数据库中检索 URI 字符串,将它们解析回 URI,并尝试在 RecyclerView 中设置图像时,此方法不再有效。

Here is the OnBindViewHolder() from the RecyclerAdapter这是来自 RecyclerAdapter 的 OnBindViewHolder()


    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        Log.d(TAG, "onBindViewHolder: called.");


        // Load only first image for now
        if(mImages.get(position).size() > 0) {

            tempUri = Uri.parse(mImages.get(position).get(0));

            // Make glide work with image
            Glide.with(mContext)
                    .asBitmap()
                    .load(tempUri)
                    .into(holder.image);

            // With regular ImageView
            holder.imageViewTest.setImageURI(tempUri);
        }
        holder.weight.setText(mWeights.get(position).toString());
        holder.location.setText(mLocations.get(position));
        holder.confidence.setText(mConfidences.get(position).toString());

        // Open item view
        holder.parentLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(mContext, ItemView.class);
                // Attach additional data to intent
                intent.putExtra("image_url", mImages.get(position));
                intent.putExtra("location", mLocations.get(position));
                intent.putExtra("confidence", mConfidences.get(position));
                intent.putExtra("weight", mWeights.get(position));
                mContext.startActivity(intent);
            }
        });

    }

The URI seems fine when inspecting the variable.检查变量时,URI 似乎很好。 What might be causing this and how can I get the images to set in the RecyclerView?什么可能导致这种情况,我怎样才能在 RecyclerView 中设置图像?

Thanks谢谢

EDIT编辑

Here is the Adapter code这是适配器代码

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {


    private static final String TAG = "RecyclerViewAdapter";

    private ArrayList<ArrayList<String>> mImages;
    private ArrayList<Float> mWeights;
    private ArrayList<Float> mConfidences;
    private ArrayList<String> mLocations;
    private ArrayList<Integer> mSharkEntryIds;
    private Context mContext;
    private Uri tempUri;

    public RecyclerViewAdapter(Context context, ArrayList<Integer> ids, ArrayList<ArrayList<String>> images, ArrayList<Float> weights
            , ArrayList<Float> confidences, ArrayList<String> locations) {


        this.mContext = context;
        this.mSharkEntryIds = ids;
        this.mImages = images;
        this.mWeights = weights;
        this.mLocations = locations;
        this.mConfidences = confidences;
    }


    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_list_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
        Log.d(TAG, "onBindViewHolder: called.");


        // Load only first image for now
        if(mImages.get(position).size() > 0) {

            tempUri = Uri.parse(mImages.get(position).get(0));

            // Make glide work with image
            Glide.with(mContext)
                    .asBitmap()
                    .load(tempUri)
                    .into(holder.image);

        }
        holder.weight.setText(mWeights.get(position).toString() + " kg");
        holder.location.setText(mLocations.get(position));
        holder.confidence.setText(mConfidences.get(position).toString() + " %");

        // Open item view
        holder.parentLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(mContext, ItemView.class);
                // Attach additional data to intent
                intent.putExtra("id", mSharkEntryIds.get(position));
                intent.putExtra("image_url", mImages.get(position));
                intent.putExtra("location", mLocations.get(position));
                intent.putExtra("confidence", mConfidences.get(position));
                intent.putExtra("weight", mWeights.get(position));
                mContext.startActivity(intent);
            }
        });

    }

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

    public class ViewHolder extends RecyclerView.ViewHolder{

        CircleImageView image;
        TextView weight;
        TextView confidence;
        TextView location;
        RelativeLayout parentLayout;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            image = itemView.findViewById(R.id.thumbnail);
            weight = itemView.findViewById(R.id.biomassText);
            confidence = itemView.findViewById(R.id.confidenceText);
            location = itemView.findViewById(R.id.locationText);
            parentLayout = itemView.findViewById(R.id.parent_layout);
        }
    }

}

Here is the code in which I initialize the RecyclerView这是我初始化 RecyclerView 的代码

// Vars
private ArrayList<Integer> mSharkEntryIds = new ArrayList<>();
private ArrayList<String> mLocations = new ArrayList<>();
//private ArrayList<String> mImageUrls = new ArrayList<>();
private ArrayList<ArrayList<String>> mImagePaths = new ArrayList<>();
private ArrayList<Float> mConfidences = new ArrayList<>();
private ArrayList<Float> mWeights = new ArrayList<>();
private DatabaseHelper mDatabaseHelper;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_view);

    mDatabaseHelper = new DatabaseHelper(this);

    Log.d(TAG, "onCreate: started");

    //initImageBitmaps();

    // Populate list view
    Cursor data = mDatabaseHelper.getSharkEntriesFromDatabase();
    while(data.moveToNext()){
        mSharkEntryIds.add(data.getInt(0));
        mWeights.add(data.getFloat(1));
        mLocations.add(data.getString(2));
        mConfidences.add(data.getFloat(3));
    }
    Log.d(TAG, "onCreate: test");

    // Get associated image paths
    ArrayList<String> photosForEntry;

    for(Integer id : mSharkEntryIds){
        data = mDatabaseHelper.getPhotosWithSharkID(id);
        photosForEntry = new ArrayList<>();
        while(data.moveToNext()){
            photosForEntry.add(data.getString(0));
        }
        mImagePaths.add(photosForEntry);
    }

    initRecyclerView();

}

private void initRecyclerView(){
    Log.d(TAG, "initRecyclerView: init recyclerview");
    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, mSharkEntryIds, mImagePaths, mWeights, mConfidences, mLocations);
    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

}

I am thinking that you are doing it wrong, I will assume that you got the paths in string form in your mImages我认为您做错了,我会假设您在mImages中获得了字符串形式的路径

Do you see this part of your onBindViewHolder :你看到你的onBindViewHolder的这一部分:

    ...................
    // Load only first image for now
    if(mImages.get(position).size() > 0) {

        tempUri = Uri.parse(mImages.get(position).get(0));

        // Make glide work with image
        Glide.with(mContext)
                .asBitmap()
                .load(tempUri)
                .into(holder.image);

        // With regular ImageView
        holder.imageViewTest.setImageURI(tempUri);
    }
    ..................

Change it to this:将其更改为:

     ........
    // Load only first image for now
    if(position == 0) {

        tempUri = Uri.parse(mImages.get(position));

        // Make glide work with image
        Glide.with(mContext)
                .asBitmap()
                .load(tempUri)
                .into(holder.image);

        // With regular ImageView
        holder.imageViewTest.setImageURI(tempUri);
    }
    ..............

UPDATE:更新:

Your code seems fine and you say that the Uri's are present in the list, so my guess here is maybe set the layout manager before setting the adapter:您的代码看起来不错,并且您说 Uri 存在于列表中,所以我的猜测可能是在设置适配器之前设置布局管理器:

I mean in your initRecyclerView() :我的意思是在你的initRecyclerView()中:

 ..........

//add this first
recyclerView.setLayoutManager(new LinearLayoutManager(this));

//add this next
recyclerView.setAdapter(adapter);

......

I have fixed the issue:我已经解决了这个问题:

The log included this message:日志包含以下消息:

java.lang.SecurityException(Permission Denial: opening provider com.android.providers.downloads.DownloadStorageProvider from ProcessRecord{985e802 27308:com.oshea.sharkbiomass/u0a82} (pid=27308, uid=10082) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs) java.lang.SecurityException(Permission Denial: opening provider com.android.providers.downloads.DownloadStorageProvider from ProcessRecord{985e802 27308:com.oshea.sharkbiomass/u0a82} (pid=27308, uid=10082) requires that you obtain access using ACTION_OPEN_DOCUMENT或相关 API)

The problem was in my on click listener for the select photo button.问题出在我的 select 照片按钮的点击监听器中。

// Select photo button listener
        btnSelectPhotos.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(intent, 1);
            }
        });

I changed this to:我将其更改为:

// Select photo button listener
        btnSelectPhotos.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
                startActivityForResult(intent, 1);
            }
        });

(Changed ACTION_GET_CONTENT to ACTION_OPEN_DOCUMENT) and it worked. (将 ACTION_GET_CONTENT 更改为 ACTION_OPEN_DOCUMENT)并且它起作用了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM