android - RecyclerView - 在 for 循环中一一更新项目 imageView 的可见性
问题描述
我notifyItemChanged(position)
从 for 循环调用 set ImageViewVisibility = inVisible
,但循环结束后立即显示所有图像视图for
。而我想一次显示/隐藏一个 imageView。我需要做什么来解决这个问题?
目前的输出:
当 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);
}
}
// }
}
解决方案
您的问题是您在尝试更改所有可见性时阻塞了主线程。因此,尽管您试图休眠以在操作之间设置延迟,但之前的操作无法执行,因为线程被阻塞。换句话说,您正在排队所有操作,但直到您释放主线程并且系统可以处理它们之后它们才能生效,然后这一切同时发生。
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
您可以做的一件事是在 for 循环中触发可运行对象,就像您已经在使用 main 函数一样。
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
这样,您可以安排所有更新在您想要的时间发生并立即释放主线程。稍后,在预定的时间,主线程可以自由地处理指令并根据需要执行动画。
希望有帮助!
推荐阅读
- android - Android Studio Emulator 中的应用程序无法在真实设备上运行
- python - 如何在现有列表中存储随机数
- javascript - useState 从 react 导入但错误用作组件
- python - Django Serializer - 如何知道错误输入了哪些参数
- android - 将整个捆绑(对象)本身从某个活动的片段传递和接收到另一个活动
- python - 获得纸浆目标函数的最小值
- python - 如何为 MacOs Big Sur 使用 pyinstaller?
- javascript - 选择具有带有特定获取变量的href的链接
- python - json.loads() 需要永远然后 linux 杀死进程
- python - 在单词标记器中出现错误“AttributeError:'numpy.ndarray'对象没有属性'lower'”