RecyclerView - обновить видимость элемента imageView один за другим в цикле for

Я вызываю notifyItemChanged(position) из цикла for, чтобы установить ImageViewVisibility = inVisible, но все изображения отображаются сразу после завершения цикла for. В то время как я хочу показывать/скрывать изображения по одному. Что мне нужно сделать, чтобы исправить это?

Текущий вывод:

Все представления изображений видны все вместе одновременно, когда заканчивается цикл for. (Я имею в виду Метод OnBindviewHolder вызывается только после завершения цикла for`

Ожидаемый результат:

Что касается циклов, выполняемых для каждого индекса, я хочу показывать/скрывать imageView для каждой строки один за другим (я имею в виду, что метод OnBindviewHolder должен вызываться при вызове каждого цикла for)

Что я пробовал:

Я пробовал notifyItemChanged(pos);, notifyDataSetChanged();, notifyItemInserted(pos);, но ни один из них не помог мне получить ожидаемый результат. Я также пробовал https://stackoverflow.com/a/35392153/1684778, но результат все тот же.

деятельность

private List<Multiples> items = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_display_result); 
    recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); 

    // use a linear layout manager
    layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);

    // specify an adapter (see also next example)
    items.addAll(DataGenerator.getPeopleData(this, of, value));
    mAdapter = new MyAdapter(items);
    recyclerView.setAdapter(mAdapter);


    //----------now give few seconds untill all default data is loaded in the recyclerView----------------
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            //--------------Now call for loop on every 2 seconds so that we can hide or show ImageViews in each 2 seconds 
            MyAdapter m= (MyAdapter) mAdapter;
            for (Multiples item : items) {
                Multiples multiples1=items.get(items.indexOf(item));
                multiples1.setImageShow(true);  // set true to hide loop 

                Log.i("ms","----------in activity--------"+items.indexOf(item));

                m.updateItem(item,items.indexOf(item));  // forward each row to adapter to take effect

                try {   // sleep for 2 seconds so that we can see the effect of above code(hide/show imageView for this row index  items.indexOf(item)
                    Log.i("s","#####################  going to sleep #######################"+items.indexOf(item) );
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }, 2500);

}

адаптер

public void updateItem(final Multiples newItem, final int pos) {
    newItem.setImageShow(true);
    items.set(pos, newItem); //update passed value in your adapter's data structure
    notifyItemChanged(pos);
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    // - get an element from your dataset at this position
    // - replace the contents of the view with that element

    if (holder instanceof MyAdapter.MyViewHolder) {
        final MyAdapter.MyViewHolder view = (MyAdapter.MyViewHolder) holder;
        final Multiples p = items.get(position);
        view.name.setText(p.first + " X " + p.getSecond() + "= " + p.getResult());

        // if (position>0) {
        if (p.imageShow) {
            view.image1.setVisibility(View.VISIBLE);
            view.image.setVisibility(View.INVISIBLE);
        } else {
            view.image1.setVisibility(View.INVISIBLE);
            view.image.setVisibility(View.VISIBLE);
        }
    }
    // }

}

почему -ve голосуйте, пожалуйста, напишите комментарий

Dan 08.04.2019 07:58
1
1
723
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша проблема в том, что вы блокируете основной поток, пытаясь изменить все видимости. Поэтому, хотя вы пытаетесь заснуть, чтобы установить задержку между операциями, предыдущие не могут быть выполнены, потому что поток заблокирован. Другими словами, вы ставите в очередь все действия, но они не могут вступить в силу до тех пор, пока вы не освободите основной поток и система не сможет их обработать, что затем произойдет одновременно.

public void run() {
    // THIS IS HAPPENING ON THE MAIN THREAD - ANDROID CAN'T CONTINUE DRAWING
    // UNTIL THIS METHOD FINISHES
        //--------------Now call for loop on each 2 seconds so that we can hide or show ImageViews in each 2 seconds 
        MyAdapter m= (MyAdapter) mAdapter;
        for (Multiples item : items) {
            Multiples multiples1=items.get(items.indexOf(item));
            multiples1.setImageShow(true);  // set true to hide loop 

            Log.i("ms","----------in activity--------"+items.indexOf(item));

            m.updateItem(item,items.indexOf(item));  // forward each row to adapter to take effect

            try {   // sleep for 2 seconds so that we can see the effect of above code(hide/show imageView for this row index  items.indexOf(item)
                Log.i("s","#####################  going to sleep #######################"+items.indexOf(item) );

                // THIS SLEEP IS BLOCKING THE MAIN THREAD - ANDROID CAN'T DRAW
                // UNTIL THE OUTER FUNCTION IS DONE
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    } // THE END OF THE RUN BLOCK - NOW ANDROID CAN RUN THE INSTRUCTIONS THAT
      // HAVE BEEN QUEUED UP, WHICH WILL APPEAR INSTANT

Одна вещь, которую вы можете сделать, это запустить runnables в цикле for, как вы уже делаете с основной функцией.

public void run() {
        //--------------Now call for loop on each 2 seconds so that we can hide or show ImageViews in each 2 seconds 
        MyAdapter m= (MyAdapter) mAdapter;

        int index = 0;
        for (Multiples item : items) {
            // DO NOT SLEEP TO NOT BLOCK THE MAIN THREAD - SCHEDULE WORK FOR LATER INSTEAD
            handler.postDelayed(new Runnabled() {
                Multiples multiples1=items.get(items.indexOf(item));
                multiples1.setImageShow(true);  // set true to hide loop 

                // OTHER LOGIC FOR THIS ITEM HERE

            }, 2000 * index++); // SCHEDULE EACH ITEM TO BE 2 SECONDS LATER THAN THE PREVIOUS
        }
    } // THE LOOP FINISHES INSTANTLY AND DOES NOT BLOCK THE MAIN THREAD

Таким образом, вы расписание все обновления должны происходить в нужное время и немедленно освобождаете основной поток. Позже, в назначенное время, основной поток может обрабатывать инструкции и выполнять анимацию по желанию.

Надеюсь, это поможет!

Спасибо, это работает в соответствии с вопросом. Теперь, что я должен написать, если я хочу, чтобы TTS читал заголовок каждого элемента строки, поэтому вместо временной задержки теперь я хочу воспроизводить каждый текст на основе завершения речи (преобразование текста в речь) и после воспроизведения TTS. строку, затем я хочу показать/скрыть imageView. Итак, как только TTS переместился в следующую строку, я хочу показать/скрыть изображение, просмотреть следующую строку и т. д. Пример: проверьте этот снимок экрана: i.stack.imgur.com/ddfNz.jpg

Dan 08.04.2019 08:24

Я бы предложил создать совершенно новый вопрос (вы можете ссылаться на него в качестве ссылки), а не пытаться продолжать решать разные проблемы в этих комментариях.

dominicoder 08.04.2019 21:13

Спасибо! Пожалуйста, проверьте эту ссылку, если вы можете помочь мне с этим новым вопросом: stackoverflow.com/questions/55582922

Dan 09.04.2019 01:11

Другие вопросы по теме