使用RecyclerView和可扩展卡的奇怪故障

时间:2018-01-10 19:07:17

标签: java android android-recyclerview android-cardview

我正试图通过每个路线应用程序的小步行时间进入Android应用程序开发 但是有一点小故障阻止我继续下去 我试图谷歌多次没有结果,这就是事情:

RecyclerView onClick-expand cards onBindViewHolder,一旦我添加太多项目,就会显示重新加载整个列表的奇怪行为。它也会以某种方式将整个列表移动一秒钟。 作为参考,这是我的github项目:https://github.com/TheInsayn/velocity

以下是它应该如何表现:
Imgur

但是在我添加了第6个项目后,它的行为如下:

Imgur

以下是我用于适配器的代码(特别是isExpandedclass RecyclerAdapterWalks extends RecyclerView.Adapter<RecyclerAdapterWalks.WalkCardHolder> { private List<Walk> mWalkList; private RecyclerView mRecyclerView; private int mExpandedPosition = -1; class WalkCardHolder extends RecyclerView.ViewHolder { TextView mWalkRoute; TextView mWalkDuration; TextView mWalkDate; TextView mWalkWeekday; RelativeLayout mExpansion; TextView mAverageTime; WalkCardHolder(View view) { super(view); mWalkRoute = view.findViewById(R.id.txt_walk_route); mWalkDuration = view.findViewById(R.id.txt_walk_duration); mWalkDate = view.findViewById(R.id.txt_walk_date); mWalkWeekday = view.findViewById(R.id.txt_walk_weekday); mExpansion = view.findViewById(R.id.walk_card_expansion); mAverageTime = view.findViewById(R.id.txt_walk_average); } } RecyclerAdapterWalks(List<Walk> routes, RecyclerView rv) { mWalkList = routes; mRecyclerView = rv; setHasStableIds(true); } @Override public WalkCardHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_walk, parent, false); return new WalkCardHolder(view); } @Override public void onBindViewHolder(WalkCardHolder holder, int position) { Walk walk = mWalkList.get(position); holder.mWalkRoute.setText(walk.getRoute().getName()); holder.mWalkDuration.setText(DateFormat.format("mm:ss", new Date(walk.getDuration()))); holder.mWalkDate.setText(DateFormat.format("dd.MM.yyyy", walk.getDate())); holder.mWalkWeekday.setText(DateFormat.format("EEEE", walk.getDate())); //handle expansion in list final boolean isExpanded = position == mExpandedPosition; holder.mExpansion.setVisibility(isExpanded ? View.VISIBLE : View.GONE); holder.itemView.setActivated(isExpanded); holder.itemView.setOnClickListener(v -> { mExpandedPosition = isExpanded ? -1 : position; TransitionManager.beginDelayedTransition(mRecyclerView); notifyDataSetChanged(); }); if (isExpanded) { Date avg = new Date(walk.getRoute().getAverageWalkTime(mRecyclerView.getContext())); CharSequence min = DateFormat.format("m", avg); CharSequence sec = DateFormat.format("s", avg); String boldText = walk.getRoute().getName(); String timeStr = "average walk duration for " + boldText + ": "; if (!min.equals("0")) timeStr += min + "m and "; timeStr += sec + "s"; int idx = timeStr.indexOf(boldText); SpannableString str = new SpannableString(timeStr); str.setSpan(new StyleSpan(Typeface.BOLD), idx, idx + boldText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); holder.mAverageTime.setText(str); } } @Override public int getItemCount() { return mWalkList.size(); } ):
我甚至使用了来自I / O 2016的Google的参考建议。(我真的不想使用第三方库)

setHasStableIds(true)

我在RelativeLayout的FrameLayout中的CoordinatorLayout中的RecyclerView中有CardView ...

有人知道可能导致这种情况的原因吗? 对不起,很长的帖子,谢谢你的帮助。 :)

编辑:在Adapter的构造函数中使用CREATE TABLE SANORD ( ID INT, NAME VARCHAR2(20), ODATE DATE, CUST INT); Table created. INSERT INTO SANORD VALUES (90, 'SMITH','26-DEC-17',1002); 1 row created. INSERT INTO SANORD VALUES (135, 'JOHNSON','09-DEC-17',1002); 1 row created. INSERT INTO SANORD VALUES (235, 'JOHNSON','01-JAN-18',1002); 1 row created. INSERT INTO SANORD VALUES (322, 'JOHNSON','04-JAN-18',1002); 1 row created. COMMIT; SELECT id, name, odate, cust FROM sanord WHERE (name, odate) IN ( select name, max(odate) from sanord where cust = 1002 group by name) ; ID NAME ODATE CUST ---------- -------------------- --------- ---------- 90 SMITH 26-DEC-17 1002 322 JOHNSON 04-JAN-18 1002 似乎有所帮助。 但现在转型远非顺利 小清单(更糟):
Imgur
更长的清单(更好):
Imgur

2 个答案:

答案 0 :(得分:0)

由于notifyDataSetChanged();行,它正在重新加载整个列表。这刷新了整个清单。如果您只添加了一个元素,我会建议使用notifyItemInserted(int position),或者如果您要更新单个项目,那么只需使用函数notifyItemChanged(int position)

答案 1 :(得分:0)

根据@napster的意见,我终于在一个老话题的帮助下解决了我的问题 我非常信任来自I / O的Nick Butcher的例子 引用:“这是一个可怕的解决方案” 使用https://stackoverflow.com/a/48092441/9165497中的技术 一切都有所改善,我现在认为问题已经解决了。

现在我的代码看起来像这样,一切都更顺畅,没有问题:

final boolean isExpanded = position == mExpandedPosition;
holder.mExpansion.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
holder.itemView.setActivated(isExpanded);
if (isExpanded) mPreviousExpandedPosition = holder.getAdapterPosition();
holder.itemView.setOnClickListener(v -> {
    mExpandedPosition = isExpanded ? -1 : holder.getAdapterPosition();
    notifyItemChanged(mPreviousExpandedPosition);
    notifyItemChanged(holder.getAdapterPosition());
});