每次删除项目时,RecyclerView 最后一项都会闪烁
RecyclerView last item blinks every time an item is removed
我正在使用带有 RecyclerView
的游标加载器,其他一切正常,除了每次我从 RecyclerView 中删除一个项目时,最后一个项目会闪烁,就像这样
我的删除代码是
public void deleteData(long id){
Uri uri = ContentUris.withAppendedId(URI, id);
getContentResolver().delete(uri, null, null);
}
刷卡验证码:
deleteData(viewHolder.getItemId());
请注意,我还有另一个 activity 使用相同的 RecyclerAdapter
、ContentProvider
和布局代码,甚至大多数实现和方法方法都是相同的,但那个有效完全没有眨眼,所以这对我来说是一个很奇怪的情况。
是否有导致此问题的具体原因?我已经试过禁用动画
recyclerView.getItemAnimator().setChangeDuration(0);
或
((DefaultItemAnimator) recyclerViewObject.getItemAnimator()).setSupportsChangeAnimations(false);
但是 none 有效,更不用说我确实希望动画有效。
编辑:断点上传:
创建时:
"main@4668" prio=5 tid=0x2 nid=NA runnable
java.lang.Thread.State: RUNNABLE at com.jackz314.todo.HistoryActivity.onCreateLoader(HistoryActivity.java:803)
at
android.support.v4.app.LoaderManagerImpl.createLoader(LoaderManager.java:539)
at
android.support.v4.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:548) at
android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:603)
at
com.jackz314.todo.HistoryActivity.displayAllNotes(HistoryActivity.java:394)
at
com.jackz314.todo.HistoryActivity.deleteExpiredNotes(HistoryActivity.java:767)
at
com.jackz314.todo.HistoryActivity.onCreate(HistoryActivity.java:129)
at android.app.Activity.performCreate(Activity.java:6975) at
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(ActivityThread.java:-1) at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105) at
android.os.Looper.loop(Looper.java:164) at
android.app.ActivityThread.main(ActivityThread.java:6541) at
java.lang.reflect.Method.invoke(Method.java:-1) at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
onDelete(删除项目):
"main@4668" prio=5 tid=0x2 nid=NA runnable java.lang.Thread.State:
RUNNABLE at
com.jackz314.todo.HistoryActivity.deleteData(HistoryActivity.java:791)
at
com.jackz314.todo.HistoryActivity.onSwiped(HistoryActivity.java:434)
at
android.support.v7.widget.helper.ItemTouchHelper.run(ItemTouchHelper.java:686)
at android.os.Handler.handleCallback(Handler.java:789) at
android.os.Handler.dispatchMessage(Handler.java:98) at
android.os.Looper.loop(Looper.java:164) at
android.app.ActivityThread.main(ActivityThread.java:6541) at
java.lang.reflect.Method.invoke(Method.java:-1) at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
希望这些有帮助
编辑: 稍微查了一下,发现最后一项居然没有闪烁,好像是RecyclerView
先改成了length/size, 截掉一段与被删除项大小相等的部分(deleting), 使最后一项(取决于被删除项的大小)暂时不可见, 然后 RecyclerView
删除应该在开头删除的项目。我仍在努力,想弄清楚是因为我在某处弄乱了订单还是其他原因。
让我们在与RecyclerViewAdapter 绑定的数据对象处放置断点,并检查数据是否闪烁。在大多数情况下,像这种情况,我意识到数据可能受到影响并使视图更改无法控制。因为不知道你是怎么处理数据的,所以没法给你更详细的解答。
您是否尝试过禁用动画?
adapter.setHasStableIds(true);
recyclerView.setItemAnimator(null);
Jackz 下面的代码在 DetailsActivity 中,它有一个 btnDelete,它触发并转到 DBHelper 并删除记录,returns DetailsActivity 然后调用 ListActivity 以从基于列表的列表中删除项目在位置上 NOT 记录 ID
private void addListenerOnButtonDelete() {
btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Calls the Method deleteDBRow in DatabaseHelper
// which acts on the TABLE_INFO to remove a record by getting the record ID
helper.deleteDBRow(String.valueOf(dbList.get(position).getID()));
ListActivity.removeListRow(position);
// Code line above calls Method in ListActivity to notify recycler view of changes
// NOTICE the List keeps items by position not ID <== READ
etWebSite.setText("");
etUN.setText("");
etPW.setText("");
etSecQuestion.setText("");
etSecAnswer.setText("");
etNotes.setText("");
Intent intent = new Intent(DetailsActivity.this, ListActivity.class);
startActivity(intent);
}
});
}
这是与适配器对话的 ListActivity 中的代码
// This method is called from DetailsActivity and notifies Recycler View that the DB was changed
// and the method makes the same changes to the Recycler View kind of a sync of DB and Recycler View
public static void removeListRow(int position) {
dbList.remove(position);
mAdapter.notifyItemRemoved(position);
mAdapter.notifyItemRangeChanged(position, dbList.size());
}
我遇到了和你一样的问题。我认为问题在于每次我们从数据库中删除内容时 CursorLoader 都会重新启动,因此每次都会触发 onLoadFinished 并交换游标。
如果我们将数据从游标加载到列表并将其传递给适配器,则问题可能是 "solved"。不过,我认为这是一种解决方法,而不是真正的解决方案。
终于明白了!
又是一个愚蠢的错误,一点都不复杂,我一直在想,为什么我只有这个activity有这个问题,而我以前的没有,我突然意识到布局在这两个活动是不同的,原来我将 RecyclerView
的高度设置为 wrap_content
,所以我想发生了什么,布局告诉系统将内容包装在 RecyclerView
,当你删除一个项目时,它在技术上不再存在,所以,即使我有删除项目的动画,项目也会立即从布局级别删除,这就是为什么 Android 调整了 RecyclerView
的高度,然后删除item,实际发生的是,由于RecyclerView
设置为wrap_content
,它删除后立即删除视图(项目)的位置,而不是之后动画,这就是它看起来像眨眼的原因。
无论如何,解决方法就是将 RecyclerView
的高度从 wrap_content
更改为任何其他值,如果您像我一样使用 ConstraintLayout
,只需更改高度 0dp
,然后将 RecyclerView
约束到其他东西或边缘。
感谢所有试图帮助我解决问题的人,我承认这是我遇到过的最愚蠢但最令人沮丧的问题之一。
我相信还有其他人也遇到了同样的问题,所以去检查高度是否设置为wrap_content
。
我也有同样的问题,这让我抓狂。
你的解决方案对我不起作用,可能是因为我的 RecyclerViewer 在 LinearLayout 中?
到目前为止我发现的唯一解决方法是禁用那样的动画
cardRecyclerView.itemAnimator = null
但我真的很想重新启用动画,因为没有它会有点不稳定。
这是我的布局,有人知道如何避免在移除卡片时最后一项闪烁吗?提前谢谢你
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="wrap_content">
<fragment
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.bendk97.platenumber.activities.main.Toolbar"/>
<fragment
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.bendk97.platenumber.activities.main.SearchBar"/>
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminateTint="@android:color/white"
android:id="@+id/progressBar" android:visibility="invisible"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
我正在使用带有 RecyclerView
的游标加载器,其他一切正常,除了每次我从 RecyclerView 中删除一个项目时,最后一个项目会闪烁,就像这样
我的删除代码是
public void deleteData(long id){
Uri uri = ContentUris.withAppendedId(URI, id);
getContentResolver().delete(uri, null, null);
}
刷卡验证码:
deleteData(viewHolder.getItemId());
请注意,我还有另一个 activity 使用相同的 RecyclerAdapter
、ContentProvider
和布局代码,甚至大多数实现和方法方法都是相同的,但那个有效完全没有眨眼,所以这对我来说是一个很奇怪的情况。
是否有导致此问题的具体原因?我已经试过禁用动画
recyclerView.getItemAnimator().setChangeDuration(0);
或
((DefaultItemAnimator) recyclerViewObject.getItemAnimator()).setSupportsChangeAnimations(false);
但是 none 有效,更不用说我确实希望动画有效。
编辑:断点上传:
创建时:
"main@4668" prio=5 tid=0x2 nid=NA runnable java.lang.Thread.State: RUNNABLE at com.jackz314.todo.HistoryActivity.onCreateLoader(HistoryActivity.java:803) at android.support.v4.app.LoaderManagerImpl.createLoader(LoaderManager.java:539) at android.support.v4.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:548) at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:603) at com.jackz314.todo.HistoryActivity.displayAllNotes(HistoryActivity.java:394) at com.jackz314.todo.HistoryActivity.deleteExpiredNotes(HistoryActivity.java:767) at com.jackz314.todo.HistoryActivity.onCreate(HistoryActivity.java:129)
at android.app.Activity.performCreate(Activity.java:6975) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) at android.app.ActivityThread.-wrap11(ActivityThread.java:-1) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Method.java:-1) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
onDelete(删除项目):
"main@4668" prio=5 tid=0x2 nid=NA runnable java.lang.Thread.State: RUNNABLE at com.jackz314.todo.HistoryActivity.deleteData(HistoryActivity.java:791) at com.jackz314.todo.HistoryActivity.onSwiped(HistoryActivity.java:434) at android.support.v7.widget.helper.ItemTouchHelper.run(ItemTouchHelper.java:686) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Method.java:-1) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
希望这些有帮助
编辑: 稍微查了一下,发现最后一项居然没有闪烁,好像是RecyclerView
先改成了length/size, 截掉一段与被删除项大小相等的部分(deleting), 使最后一项(取决于被删除项的大小)暂时不可见, 然后 RecyclerView
删除应该在开头删除的项目。我仍在努力,想弄清楚是因为我在某处弄乱了订单还是其他原因。
让我们在与RecyclerViewAdapter 绑定的数据对象处放置断点,并检查数据是否闪烁。在大多数情况下,像这种情况,我意识到数据可能受到影响并使视图更改无法控制。因为不知道你是怎么处理数据的,所以没法给你更详细的解答。
您是否尝试过禁用动画?
adapter.setHasStableIds(true);
recyclerView.setItemAnimator(null);
Jackz 下面的代码在 DetailsActivity 中,它有一个 btnDelete,它触发并转到 DBHelper 并删除记录,returns DetailsActivity 然后调用 ListActivity 以从基于列表的列表中删除项目在位置上 NOT 记录 ID
private void addListenerOnButtonDelete() {
btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Calls the Method deleteDBRow in DatabaseHelper
// which acts on the TABLE_INFO to remove a record by getting the record ID
helper.deleteDBRow(String.valueOf(dbList.get(position).getID()));
ListActivity.removeListRow(position);
// Code line above calls Method in ListActivity to notify recycler view of changes
// NOTICE the List keeps items by position not ID <== READ
etWebSite.setText("");
etUN.setText("");
etPW.setText("");
etSecQuestion.setText("");
etSecAnswer.setText("");
etNotes.setText("");
Intent intent = new Intent(DetailsActivity.this, ListActivity.class);
startActivity(intent);
}
});
}
这是与适配器对话的 ListActivity 中的代码
// This method is called from DetailsActivity and notifies Recycler View that the DB was changed
// and the method makes the same changes to the Recycler View kind of a sync of DB and Recycler View
public static void removeListRow(int position) {
dbList.remove(position);
mAdapter.notifyItemRemoved(position);
mAdapter.notifyItemRangeChanged(position, dbList.size());
}
我遇到了和你一样的问题。我认为问题在于每次我们从数据库中删除内容时 CursorLoader 都会重新启动,因此每次都会触发 onLoadFinished 并交换游标。
如果我们将数据从游标加载到列表并将其传递给适配器,则问题可能是 "solved"。不过,我认为这是一种解决方法,而不是真正的解决方案。
终于明白了!
又是一个愚蠢的错误,一点都不复杂,我一直在想,为什么我只有这个activity有这个问题,而我以前的没有,我突然意识到布局在这两个活动是不同的,原来我将 RecyclerView
的高度设置为 wrap_content
,所以我想发生了什么,布局告诉系统将内容包装在 RecyclerView
,当你删除一个项目时,它在技术上不再存在,所以,即使我有删除项目的动画,项目也会立即从布局级别删除,这就是为什么 Android 调整了 RecyclerView
的高度,然后删除item,实际发生的是,由于RecyclerView
设置为wrap_content
,它删除后立即删除视图(项目)的位置,而不是之后动画,这就是它看起来像眨眼的原因。
无论如何,解决方法就是将 RecyclerView
的高度从 wrap_content
更改为任何其他值,如果您像我一样使用 ConstraintLayout
,只需更改高度 0dp
,然后将 RecyclerView
约束到其他东西或边缘。
感谢所有试图帮助我解决问题的人,我承认这是我遇到过的最愚蠢但最令人沮丧的问题之一。
我相信还有其他人也遇到了同样的问题,所以去检查高度是否设置为wrap_content
。
我也有同样的问题,这让我抓狂。
你的解决方案对我不起作用,可能是因为我的 RecyclerViewer 在 LinearLayout 中?
到目前为止我发现的唯一解决方法是禁用那样的动画
cardRecyclerView.itemAnimator = null
但我真的很想重新启用动画,因为没有它会有点不稳定。
这是我的布局,有人知道如何避免在移除卡片时最后一项闪烁吗?提前谢谢你
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="wrap_content">
<fragment
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.bendk97.platenumber.activities.main.Toolbar"/>
<fragment
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.bendk97.platenumber.activities.main.SearchBar"/>
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminateTint="@android:color/white"
android:id="@+id/progressBar" android:visibility="invisible"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</LinearLayout>