Хобрук: Ваш путь к мастерству в программировании

Невозможно установить изображение в RecyclerView с помощью URI

Я работаю над приложением, которое извлекает информацию из базы данных SQLite и отображает ее в RecyclerView. У меня возникли проблемы с настройкой изображения в RecyclerView с использованием URI.

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

Это фрагмент моего OnActivityResult() после выбора изображений из галереи. Установка изображений в базовом действии с использованием этого кода работает. Я беру toString() из URI и сохраняю его в своей базе данных. (Я буду перемещать выбранные изображения в папку приложения, прежде чем принимать URI в окончательной версии приложения)

Однако, когда я извлекаю строки URI из базы данных, анализирую их обратно в URI и пытаюсь установить изображение в RecyclerView, этот метод больше не работает.

Вот OnBindViewHolder() из RecyclerAdapter


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

    }

URI выглядит нормально при проверке переменной. Что может быть причиной этого и как я могу установить изображения в RecyclerView?

Спасибо

ИЗМЕНИТЬ

Вот код адаптера

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

}

Вот код, в котором я инициализирую 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));

}

Ответы:


1

Я думаю, что вы делаете это неправильно, я предполагаю, что вы получили пути в строковой форме в вашем mImages

Вы видите эту часть вашего 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);
    }
    ..................

Измените его на это:

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

ОБНОВЛЕНИЕ:

Ваш код выглядит нормально, и вы говорите, что Uri присутствуют в списке, поэтому я предполагаю, что здесь может быть установлен менеджер компоновки перед настройкой адаптера:

Я имею в виду в вашем initRecyclerView():

 ..........

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

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

......
13.05.2020
  • Спасибо за ваш вклад, я понимаю, к чему вы клоните, но на самом деле mImages содержит ArrayLists строк, представляющих изображения. Это связано с тем, что одна запись может иметь несколько изображений, поэтому каждая запись имеет свой собственный список изображений ArrayList. Таким образом, get(0) просто получает одно изображение для отображения в представлении отдельного элемента. Переменная position указывает на то, какой элемент находится в RecyclerView. Я проверил, что Uri не является нулевым. 13.05.2020
  • Ни один вид изображения в адаптере не показывает изображение 14.05.2020
  • Я предлагаю вам показать полный код адаптера и то, как вы инициализируете свой адаптер. 14.05.2020
  • Спасибо, Хасан, я добавил адаптер и код инициализации в качестве редактирования. 14.05.2020
  • Привет, Хасан, я изменил порядок этих строк, но, к сожалению, это не решило проблему. 16.05.2020
  • Я решил проблему, спасибо за помощь, Хасан. 16.05.2020

  • 2

    Я исправил проблему:

    В журнале было это сообщение:

    java.lang.SecurityException(Отказ в разрешении: открытие провайдера com.android.providers.downloads.DownloadStorageProvider из ProcessRecord{985e802 27308:com.oshea.sharkbiomass/u0a82} (pid=27308, uid=10082) требует, чтобы вы получили доступ, используя ACTION_OPEN_DOCUMENT или связанные API)

    Проблема была в моем прослушивателе кликов для кнопки выбора фотографии.

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

    Я изменил это на:

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

    (Изменил ACTION_GET_CONTENT на ACTION_OPEN_DOCUMENT), и это сработало.

    16.05.2020
    Новые материалы

    Учебные заметки JavaScript Object Oriented Labs
    Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

    Разбор строк запроса в vue.js
    Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

    Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
    «Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..