Функция onBindViewHolder() RecyclerView не привязывает TextView из списка к держателю представления

#android #arraylist #android-recyclerview #textview #listadapter

Вопрос:

У меня есть этот адаптер RecyclerView, который поддерживает список объектов представления (текстовые представления и изображения) У
меня есть пользовательский держатель представления, в котором есть данные элемента TextView
Внутри onBindViewHolder я пытаюсь привязать данные элемента TextView пользовательского держателя представления к текстовому представлению из списка
Журнал показывает, что правильный текст сразу же, но после того, как обратный вызов вернул текст по умолчанию «TextView» выводится на экран
, это мой класс:

 public class UnwantedRealityAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    Context mContext;
    String habitPath;
    List<View> list;

    public UnwantedRealityAdapter(Context context, int id){
        mContext = context;
        habitPath = context.getExternalFilesDir(null).getPath()   "/"   String.format("d",id)   ".txt";
        getFileToList();
    }

    /**
     * all file lines start with a digit that indicates what is the content of the line
     * 1 text
     * 2 image path
     */
    public void getFileToList() {
        // open the file to read
        list = new ArrayList<>();
        try {
            BufferedReader bufferedReader = new BufferedReader( new FileReader(habitPath) );
            String line;
            TextView tv;
            ImageView imageView;
            while((line = bufferedReader.readLine())!=null){
                if(line.charAt(0) == '1'){ // text
                    tv = new TextView(mContext);
                    tv.setText(line.substring(1));
                    list.add(tv);
                }
                else{
                    imageView = new ImageView(mContext);
                    imageView.setImageURI(Uri.fromFile(new File(line.substring(1))));
                    list.add(imageView);
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(list.get(position) instanceof TextView)
            return 1;
        if(list.get(position) instanceof ImageView)
            return 2;

        return -1; // error
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view;
        switch(viewType){
            case 1:
                view = LayoutInflater.from(mContext).inflate(R.layout.text_item, parent, false);
                TextViewHolder textViewHolder = new TextViewHolder(view);
                return textViewHolder;
            case 2:
                view = LayoutInflater.from(mContext).inflate(R.layout.image_item, parent, false);
                ImageViewHolder imageViewHolder = new ImageViewHolder(view);
                return imageViewHolder;
            default:
                return null;
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        int viewType = getItemViewType(position);
        switch(viewType){
            case 1:  
                //THIS IS THE PROBLEMATIC LINE
                ((TextViewHolder)holder).textView = (TextView) list.get(position);
                Log.i("===", "at position: "  position   " text is: "   ((TextViewHolder)holder).textView.getText()); 
                // this log shows correct output
                   
                break;
            case 2:
                ((ImageViewHolder)holder).imageView = (ImageView) list.get(position);
                break;
        }
    }

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

    class TextViewHolder extends RecyclerView.ViewHolder{
        TextView textView;
        public TextViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.textView);
        }
    }

    class ImageViewHolder extends RecyclerView.ViewHolder{
        ImageView imageView;
        public ImageViewHolder(@NonNull View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.imageView);
        }
    }
}
 

Я не хочу использовать метод setText:

 ((TextViewHolder)holder).textView.setText( ( (TextView) list.get(position) ).getText() );  
 

пожалуйста, посоветуйте
почему указатель TextView меняет свое значение обратно после возврата обратного вызова?

это то, что я вижу:
введите описание изображения здесь

и это то, что я хочу видеть:
введите описание изображения здесь

Комментарии:

1. Вы не должны «держаться» за список представлений. Проанализируйте ваши входные данные в строку/Uri, а затем используйте их для настройки текста или setImage во время onBindViewHolder.

2. Спасибо. является ли это плохой практикой? почему это так?

3. Вы нарушаете практически всю концепцию шаблона «повторного просмотра», который заключается в повторном использовании одного и того же представления между несколькими элементами (во время прокрутки).

4. почему ты так говоришь? я изменяю только значение указателя. насколько я могу судить, тот же держатель представления все еще используется повторно. что я упускаю?

5. Изменение ссылки на textview владельцев представлений не изменяет его иерархию представлений, исходный textview уже является ее частью. Что касается повторного использования, вы, похоже, не понимаете ту часть, в которой вид переработчика создаст только достаточное количество представлений для заполнения окна просмотра (например, 5), в то время как вы сразу создадите представление для всех элементов (даже если ваш ввод приведет к созданию 1000 элементов).