notifyItemChanged(position)仅在第一次工作

时间:2018-07-09 08:43:11

标签: android android-recyclerview android-adapter

尝试更新适配器中的项目时出现奇怪的行为。

让我先解释一下:
对于这个问题,可以说我的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());

1 个答案:

答案 0 :(得分:1)

您似乎不了解RecyclerView的核心ViewHolder模式。通过将mLayoutView存储在onCreateViewHolder中并在onBindViewHolder中重用,将使适配器陷入灾难。

onCreateViewHolder仅被调用足够的次数以获取足够的ViewHolders来填充视口(因此,如果您看到5个项目,则被称为6-7次)。

onBindViewHolder用于显示ViewHolders中数据集中的数据。只要视图进入和离开视口,就会多次调用它(即使您看到5个项目,在滚动时也会无限期调用它)。您会注意到,ViewHolders离开视口已在此方法中重新使用并绑定到另一个项目(您可以出于学习目的在此方法中记录textview的文本)。

我的建议是删除mLayoutView,并让您的onBindViewHolder实际上将数据绑定到函数参数中提供的ViewHolder。您不能在此处创建新的ViewHolders