尝试更新适配器中的项目时出现奇怪的行为。
让我先解释一下:
对于这个问题,可以说我的TextView
中的ViewHolder
是(FirstText
),然后将文本更新为(SecondText
),它可以完美地工作,它像预期。
然后我再次将其更改为(ThirdText
),然后返回到(FirstText
),而不是预期的(ThirdText
)。如果我关闭“活动”并再次打开它,则文本为({ThirdText
)。
换句话说,该项目仅每秒钟正确更新一次。
我希望这是有道理的。这是我的适配器:
public class MainActivityVideoAdapter extends Adapter<RecyclerView.ViewHolder> {
Context context;
View myLayoutView;
ArrayList<PathModel> thumbPathList;
ArrayList<PathModel> videoPathList;
long _id;
class MenuViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView videoName;
CircularImageView videoThumb;
ImageButton viewholderOtions;
MenuViewHolder(View itemView) {
super(itemView);
viewholderOtions = myLayoutView.findViewById(R.id.viewholderOptions);
videoName = myLayoutView.findViewById(R.id.FilePath);
videoThumb = myLayoutView.findViewById(R.id.VideoThumbnail);
itemView.setOnClickListener(this);
viewholderOtions.setOnClickListener(this);
}
//Handling click events
@Override
public void onClick(View v) {
if (v == viewholderOtions) {
int position = (int) v.getTag();
showPopupMenu(viewholderOtions, position);
}
}
}
public MainActivityVideoAdapter(Context context, ArrayList<PathModel> thumbPathList, ArrayList<PathModel> videoPathList) {
this.context = context;
this.thumbPathList = thumbPathList;
this.videoPathList = videoPathList;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
myLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.video_list, parent, false);
return new MenuViewHolder(myLayoutView);
}
public void onBindViewHolder(final RecyclerView.ViewHolder myHolder, final int position) {
MenuViewHolder ad = new MenuViewHolder(myLayoutView);
PathModel videoPathModel = this.videoPathList.get(position);
PathModel thumbathModel = this.thumbPathList.get(position);
File file = new File(videoPathModel.getPath());
final String filename = file.getName();
ad.videoName.setText(filename);
ad.videoName.setTypeface(custom_font_desc);
ad.videoThumb.setImageURI(Uri.parse(thumbathModel.getPath()));
ad.viewholderOtions.setTag(position);
}
private void showPopupMenu(final View view, final int position) {
final PopupMenu popup = new PopupMenu(view.getContext(), view);
popup.setGravity(Gravity.END);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.popup_menu, popup.getMenu());
popup.show();
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.rename:
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/KelsonSansLight.otf");
final String[] Rename = {"newname.mp4"};
LayoutInflater layoutInflater = LayoutInflater.from(context);
View promptView = layoutInflater.inflate(R.layout.dialoginput, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setView(promptView);
final String[] nameExtention = new String[1];
final EditText editText = (EditText) promptView.findViewById(R.id.input_text);
final TextView title = (TextView) promptView.findViewById(R.id.title);
title.setTypeface(font);
editText.setTypeface(font);
alertDialogBuilder.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Rename[0] = editText.getEditableText().toString();
if (!Rename[0].endsWith(".mp4")) {
Rename[0] = Rename[0] + ".mp4";
}
nameExtention[0] = editText.getEditableText().toString();
if (!Rename[0].equalsIgnoreCase("newname.mp4")) {
String temporary = fileRename(videoPathList.get(position).getPath(), Rename[0]);
String temporary2 = fileRename(videoPathList.get(position).getPath().replace(".mp4", ".jpg"), Rename[0].replace(".mp4", ".jpg"));
if (temporary != null && temporary2 != null) {
SQLiteHelper helper = new SQLiteHelper(context);
PathModel path1 = new PathModel();
path1.setPath(temporary);
PathModel path2 = new PathModel();
path2.setPath(temporary2);
String id_of_thumbpath = helper.getMainThumbID(thumbPathList.get(position).getPath());
videoPathList.set(position, path1);
thumbPathList.set(position, path2);
helper.updateMainThumbPath(temporary2, temporary, id_of_thumbpath);
helper.updateMainVideoPath(videoPathList.get(position).getPath(), id_of_thumbpath);
helper.close();
MainActivityVideoAdapter.this.notifyItemChanged(position);
Toast.makeText(view.getContext(), "Video Renamed", Toast.LENGTH_LONG).show();
}
}
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = alertDialogBuilder.create();
alert.show();
return true;
default:
return true;
}
}
});
}
//Rename files
public String fileRename(String _path, String nameChange) {
Log.d("FilePath", _path);
File file = new File(_path);
Log.d("FileName", file.getName());
Log.d("FileDir", file.getParent());
File rename = new File(file.getParent() + "/" + nameChange);
if (file.renameTo(rename))
return rename.getPath();
else
return null;
}
因此,在更新特定项目后,我叫MainActivityVideoAdapter.this.notifyItemChanged(position);
我在Log
中放置了一个onBindViewHolder
,当我调用上面的代码时就会调用它。
我注意到的另一件事是,当我在片段中调用((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
时,项目变得混乱了,这是我的片段:
public class MyFragment extends Fragment {
RecyclerView recyclerView;
private DBManager dbManager;
private long _id;
ArrayList<PathModel> MAINVideoPathList = new ArrayList<>();
ArrayList<PathModel> MAINThumbPathList = new ArrayList<>();
SQLiteHelper sqLiteHelper;
MainActivityVideoAdapter videoAdapter;
View v;
LinearLayoutManager layoutManager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
v = View.inflate(getContext(),R.layout.fragment_my, null);
sqLiteHelper = new SQLiteHelper(getActivity());
dbManager = new DBManager(getActivity());
dbManager = dbManager.open();
_id = Long.parseLong("1");
this.MAINThumbPathList = this.sqLiteHelper.MAINGetAllThumbPath(String.valueOf(this._id));
this.MAINVideoPathList = this.sqLiteHelper.MAINGetAllVideoPath(String.valueOf(this._id));
recyclerView = (RecyclerView) v.findViewById(R.id.frag2recycler);
txtEmptyAdapter = (TextView) v.findViewById(R.id.txtEmptyAdapter);
txtEmptyAdapter.setTypeface(custom_font_desc);
((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
videoAdapter = new MainActivityVideoAdapter(getContext(), this.MAINThumbPathList, this.MAINVideoPathList);
layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setStackFromEnd(true);
layoutManager.setReverseLayout(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(videoAdapter);
videoAdapter.notifyDataSetChanged();
dbManager.close();
sqLiteHelper.close();
return v;
}
}
}
@Override
public void onResume() {
super.onResume();
MAINThumbPathList.clear();
MAINVideoPathList.clear();
MAINThumbPathList.addAll(sqLiteHelper.MAINGetAllThumbPath(String.valueOf(this._id)));
MAINVideoPathList.addAll(sqLiteHelper.MAINGetAllVideoPath(String.valueOf(this._id)));
videoAdapter = new MainActivityVideoAdapter(getContext(), this.MAINThumbPathList, this.MAINVideoPathList);
videoAdapter.notifyDataSetChanged();
recyclerView.setAdapter(videoAdapter);
sqLiteHelper.close();
if (recyclerView.getAdapter().getItemCount() > 0){
txtEmptyAdapter.setVisibility(View.GONE);
}else {
txtEmptyAdapter.setVisibility(View.VISIBLE);
}
}
我不确定自己在做什么错。任何帮助将不胜感激。
我认为还值得一提的是,我尝试在特定位置移除物品,并且使用以下命令效果很好:
thumbPathList.remove(position);
videoPathList.remove(position);
MainActivityVideoAdapter.this.notifyItemRemoved(position);
MainActivityVideoAdapter.this.notifyItemRangeChanged(position, thumbPathList.size());
MainActivityVideoAdapter.this.notifyItemRangeChanged(position, videoPathList.size());
答案 0 :(得分:1)
您似乎不了解RecyclerView的核心ViewHolder
模式。通过将mLayoutView
存储在onCreateViewHolder
中并在onBindViewHolder
中重用,将使适配器陷入灾难。
onCreateViewHolder
仅被调用足够的次数以获取足够的ViewHolders
来填充视口(因此,如果您看到5个项目,则被称为6-7次)。
onBindViewHolder
用于显示ViewHolders
中数据集中的数据。只要视图进入和离开视口,就会多次调用它(即使您看到5个项目,在滚动时也会无限期调用它)。您会注意到,ViewHolders
离开视口已在此方法中重新使用并绑定到另一个项目(您可以出于学习目的在此方法中记录textview的文本)。
我的建议是删除mLayoutView
,并让您的onBindViewHolder
实际上将数据绑定到函数参数中提供的ViewHolder
。您不能在此处创建新的ViewHolders
。