gpt4 book ai didi

android - 为什么 notifyItemChanged 只能在 setAdapter 之后的 Post Runnable 中起作用?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:56:32 25 4
gpt4 key购买 nike

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

RecyclerView list = (RecyclerView) findViewById(R.id.list);
list.setLayoutManager(new LinearLayoutManager(this));
final RecyclerView.Adapter adapter = getAdapter();
list.setAdapter(adapter);

adapter.notifyItemChanged(1, new Object());//this doesn't work
list.post(new Runnable() {
@Override
public void run() {
adapter.notifyItemChanged(1, new Object());//this works
}
});


}

@NonNull
private RecyclerView.Adapter getAdapter() {
return new RecyclerView.Adapter() {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ItemViewHolder( LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_view_item, parent, false));
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ItemViewHolder item = (ItemViewHolder) holder;
item.tv.setText("test");
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) {
if(payloads.isEmpty())
onBindViewHolder(holder, position);
else{
ItemViewHolder item = (ItemViewHolder) holder;
item.tv.setText("changed!!!!!! ");
}
}

@Override
public int getItemCount() {
return 40;
}

class ItemViewHolder extends RecyclerView.ViewHolder{
TextView tv;
ItemViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv);
}
}
};
}}

这里很简单的例子只是为了测试notifyItemChanged,它只在发送到消息队列时有效,而不是在setAdapter之后直接调用。setAdapter 触发对 requeSTLayout() 的调用,这是否意味着 notifyItemChanged 不会在项目布局过程中发生?

最佳答案

经过一番调查后发现 notifyItemChanged仅在 RecyclerView 时有效附上,实际上已经完成onLayout发生在 onCreate 之后.

内部 RecyclerView.onLayout()notifyItemChanged -> requestLayout() 调用, processAdapterUpdatesAndSetAnimationFlags()被称为检查要更新的项目是否有可用的 ViewHolder在这种情况下是 null因为在 onCreate() 期间, RecyclerView没有贴在 window 上,因此没有对 RecyclerView 进行测量和布局。

显然是 RecyclerView 的完整绘图在 onCreate() 之后的某个时间发生和 OnResume()

@Override
protected void onResume() {
super.onResume();
boolean a = list.isAttachedToWindow();//this is false!
}

所以要notifyItemChanged致力于 onCreate

list.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
adapter.notifyItemChanged(1, new Object());//this will update the item
}
});



new Thread((new Runnable() {
@Override
public void run() {
try {
Thread.sleep(28);//small amount of delay,below 20 doesn't seem to work
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
@Override
public void run() {
adapter.notifyItemChanged(1, new Object());//also works
}
});
}
})).start();

我猜这是因为 ViewRootImpl.performTraversal()由系统控制,它发生在 DecorView 之后的某个时间附加到 onCreate 期间的窗口

我假设这只会在 onCreate 期间发生和 onResume ,如果稍后调用它可能不会发生。

关于android - 为什么 notifyItemChanged 只能在 setAdapter 之后的 Post Runnable 中起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41992586/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com