问题描述
我的应用程序的问题如上图所示。
输入数据后,如果我在将项目添加为可滚动后滚动,数据就会消失。
作为进一步的解释,有时输入的数据会出现在已添加的其他项目中。
为了解释该应用程序,它是一个运动记录应用程序,它使用 multi-type recycler view
。
我使用了 listadapter
和 DiffUtil
。并且图片与Detail item
有关。
TextWatcher
用于保存输入的数据。
-
在支架内使用
setIsRecyclable(false)
-> 这个方法奏效了。但我听说setIsRecyclable(false)
是一个没有recycle
的函数。 如果我使用它,这不是一个很好的方法,因为使用RecyclerView
没有优势吗?
RoutineAdapter.java
public class Routinelistadapter extends listadapter<Object,RecyclerView.ViewHolder> {
Context context;
Routinelistadapter.OnRoutineItemClickListener routinelistener;
Routinelistadapter.OnRoutineAddClickListener routineAddListener;
final static int TYPE_ROUTINE = 1;
final static int TYPE_ROUTINE_DETAIL = 2;
final static int TYPE_ROUTINE_FOOTER = 3;
public Routinelistadapter(@NonNull DiffUtil.ItemCallback<Object> diffCallback) {
super(diffCallback);
}
// add routine interface
public interface OnRoutineAddClickListener {
public void onAddRoutineClick();
}
public void setonAddRoutineClickListener(Routinelistadapter.OnRoutineAddClickListener listener) {
this.routineAddListener = listener;
}
// add/remove detail interface
public interface OnRoutineItemClickListener {
public void onAddBtnClicked(int curRoutinePos);
public void onDeleteBtnClicked(int curRoutinePos);
public void onWritingCommentBtnClicked(int curRoutinePos);
}
public void setonRoutineClickListener(Routinelistadapter.OnRoutineItemClickListener listener) {
this.routinelistener = listener;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,int viewType) {
context = parent.getContext();
View itemView;
if(viewType == TYPE_ROUTINE){
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.routine_item,parent,false);
return new Routinelistadapter.RoutineViewHolder(itemView);
}
else if(viewType == TYPE_ROUTINE_DETAIL){
itemView = LayoutInflater.from(context).inflate(R.layout.routine_detail_item,false);
return new Routinelistadapter.RoutineDetailViewHolder(itemView);
}
else {
itemView = LayoutInflater.from(context).inflate(R.layout.add_routine_item,false);
return new Routinelistadapter.RoutineAddFooterViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder,int position) {
Object curItem;
switch (getItemViewType(position)) {
case TYPE_ROUTINE:
curItem = getItem(position);
setRoutineData((Routinelistadapter.RoutineViewHolder) holder,(RoutineModel) curItem);
break;
case TYPE_ROUTINE_DETAIL:
curItem = getItem(position);
RoutineDetailModel item = (RoutineDetailModel) curItem;
((Routinelistadapter.RoutineDetailViewHolder) holder).bind(item);
((RoutineDetailViewHolder) holder).weight.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s,int start,int count,int after) {
}
@Override
public void onTextChanged(CharSequence s,int before,int count) {
}
@Override
public void afterTextChanged(Editable s) {
item.setWeight(((RoutineDetailViewHolder) holder).weight.getText().toString());
}
});
break;
case TYPE_ROUTINE_FOOTER:
break;
}
}
private void setRoutineData(Routinelistadapter.RoutineViewHolder holder,RoutineModel routineItem){
holder.routine.setText(routineItem.getRoutine());
}
public Object getRoutineItem(int position) {
if(getCurrentList() == null || position < 0 || position >= getCurrentList().size())
return null;
return getItem(position);
}
@Override
public int getItemCount() {
return getCurrentList().size() + 1;
}
@Override
public int getItemViewType(int position) {
if(position == getCurrentList().size()) {
return TYPE_ROUTINE_FOOTER;
}
else {
Object obj = getItem(position);
if(obj instanceof RoutineModel) {
return TYPE_ROUTINE;
}
else {
// obj instanceof RoutineDetailModel
return TYPE_ROUTINE_DETAIL;
}
}
}
private class RoutineViewHolder extends RecyclerView.ViewHolder {
public TextView routine;
public Button addSet;
public Button deleteSet;
public Button comment;
public RoutineViewHolder(@NonNull View itemView) {
super(itemView);
routine = itemView.findViewById(R.id.routine);
addSet = itemView.findViewById(R.id.add_set);
deleteSet = itemView.findViewById(R.id.delete_set);
comment = itemView.findViewById(R.id.write_comment);
addSet.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onAddBtnClicked(getAdapterPosition());
}
});
deleteSet.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onDeleteBtnClicked(getAdapterPosition());
}
});
comment.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(routinelistener != null && getAdapterPosition() != RecyclerView.NO_POSITION)
routinelistener.onWritingCommentBtnClicked(getAdapterPosition());
}
});
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
private TextView set;
private EditText weight;
public RoutineDetailViewHolder(@NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
private void bind(RoutineDetailModel item) {
set.setText(item.getSet().toString() + "set");
weight.setText(item.getWeight());
}
}
private class RoutineAddFooterViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public RoutineAddFooterViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.add_text);
ConstraintLayout regionForClick = itemView.findViewById(R.id.clickable_layout);
regionForClick.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (routineAddListener != null) {
routineAddListener.onAddRoutineClick();
}
}
});
}
}
}
更新
适配器
public class Routinelistadapter extends listadapter<Object,RecyclerView.ViewHolder> {
// detail add / remove iterface
public interface OnRoutineItemClickListener {
public void onAddBtnClicked(int curRoutinePos);
public void onDeleteBtnClicked(int curRoutinePos);
public void onWritingCommentBtnClicked(int curRoutinePos);
public void onWritingWeight(int curRoutinePos,View view); // write weight
}
public void setonRoutineClickListener(Routinelistadapter.OnRoutineItemClickListener listener) {
if(this.routinelistener != null)
this.routinelistener = null;
this.routinelistener = listener;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder,(RoutineModel) curItem);
break;
case TYPE_ROUTINE_DETAIL:
((Routinelistadapter.RoutineDetailViewHolder) holder).bind();
break;
case TYPE_ROUTINE_FOOTER:
break;
}
}
private class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
private TextView set;
private EditText weight;
public RoutineDetailViewHolder(@NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
weight.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s,int after) {
}
@Override
public void onTextChanged(CharSequence s,int count) {
}
@Override
public void afterTextChanged(Editable s) {
routinelistener.onWritingWeight(getAdapterPosition(),itemView);
}
});
}
private void bind() {
RoutineDetailModel item = (RoutineDetailModel) getItem(getAdapterPosition());
set.setText(item.getSet().toString() + "set");
weight.setText(item.getWeight()); // Setting the saved value
}
}
活动
public class WriteRoutineActivity extends AppCompatActivity implements WritingCommentDialogFragment.OnDialogClosedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_routine);
initViews();
setPageTitle(getIntent());
setRoutineRecyclerview();
diffUtil2 = new RoutineDiffUtil2();
listadapter = new Routinelistadapter(diffUtil2);
items = new ArrayList<>();
routine_rv.setAdapter(listadapter);
listadapter.setonRoutineClickListener(new Routinelistadapter.OnRoutineItemClickListener() {
@Override
public void onWritingWeight(int curRoutinePos,View v) {
RoutineDetailModel item = (RoutineDetailModel) listadapter.getRoutineItem(curRoutinePos);
EditText weight = v.findViewById(R.id.weight);
item.setWeight(weight.getText().toString()); // This is saved to set the value again when recycled.
});
}
}
如果您需要任何其他额外代码,请告诉我
解决方法
问题在于您在 TextWatcher
中添加的 onBindViewHolder
。
目前您已经设置好每次 RecyclerView
绑定视图(每个实际视图可能发生多次),您添加一个新的 TextWatcher
然后还设置文本到项目的权重,然后触发您之前添加的观察者,将项目的权重设置为其他内容,在本例中为空字符串。
您应该做的是在添加另一个监听器之前移除所有监听器,或者在 onCreateViewHolder
中添加监听器并使用支架的适配器位置来获取您的项目。
这是一些伪代码来阐明我的建议:
在 onCreateViewHolder
RoutineDetailViewHolder {
private EditText weight;
RoutineDetailViewHolder {
weight.addTextChangedListener {
items[adapterPosition].setWeight(...)
}
}
}
在再次绑定之前移除监听器:
RoutineDetailViewHolder {
private EditText weight;
private TextWatcher weightWatcher;
void bind() {
weight.removeTextChangedListener(weightWatcher);
weightWatcher = new TextWatcher();
weight.addOnTextChangedListener(weightWatcher);
}
}