[英]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.