每次移除项目时,RecyclerView最后一项都会闪烁

问题描述 投票:0回答:6

我正在使用带RecyclerView的游标加载器,其他一切工作正常,除了每次从RecyclerView中删除一个项目时,最后一项闪烁,就像这样

last item blinks

我的删除代码是

public void deleteData(long id){
    Uri uri = ContentUris.withAppendedId(URI, id);
    getContentResolver().delete(uri, null, null);
}

刷卡代码:

deleteData(viewHolder.getItemId());

请注意,我有另一个使用相同的RecyclerAdapterContentProvider和布局代码的活动,即使大多数实现和方法方法是相同的,但是一个没有任何闪烁的完美工作,所以对我来说这是一个非常奇怪的情况。

是否有可能导致此问题的具体原因?我已经尝试过禁用动画了

recyclerView.getItemAnimator().setChangeDuration(0);

要么

((DefaultItemAnimator) recyclerViewObject.getItemAnimator()).setSupportsChangeAnimations(false);

但这一切都没有效果,更不用说我确实希望动画能够发挥作用。

编辑:上传断点:

的onCreate:

“主@ 4668” PRIO = 5 TID = 0X2 NID = NA可运行java.lang.Thread.State中:在RUNNABLE com.jackz314.todo.HistoryActivity.onCreateLoader(HistoryActivity.java:803)在android.support.v4.app。 LoaderManagerImpl.createLoader(LoaderManager.java:539)在android.support.v4.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:548)在android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:603)在COM .jackz314.todo.HistoryActivity.displayAllNotes(HistoryActivity.java:394)在com.jackz314.todo.HistoryActivity.deleteExpiredNotes(HistoryActivity.java:767)在com.jackz314.todo.HistoryActivity.onCreate(HistoryActivity.java:129) 在android.app.Activity.performCreate(Activity.java:6975)在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)在android.app。 ActivityThread.handleLaunchActivity(ActivityThread.java:2892)在android.app.ActivityThread.-wrap11(ActivityThread.java:-1)在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1593) 在Android.os.Handler.dispatchMessage(Handler.java:105)的android.app.Looper.loop(Looper.java:164)在android.app.ActivityThread.main(ActivityThread.java:6541)的java.lang上。 reflect.Method.invoke(Method.java:-1)在com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:240)在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 $ 4 .onSwiped(HistoryActivity.java:434)在android.os.Handler.handleCallback(Handler.java:789)的android.support.v7.widget.helper.ItemTouchHelper $ 4.run(ItemTouchHelper.java:686) .Handler.dispatchMessage(Handler.java:98)位于android.app.Looper.loop(Looper.java:164)的android.app.ActivityThread.main(ActivityThread.java:6541),位于java.lang.reflect.Method。在Com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)的com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:240)中调用(Method.java:-1)

希望那些帮助

编辑:经过一番调查后,我发现最后一项实际上没有闪烁,似乎RecyclerView首先改变了它的长度/大小,切断了与删除项目大小相同的部分(删除),所以最后一项(取决于已删除项目的大小)暂时不可见,然后RecyclerView删除应该在开头删除的项目。我还在努力,想弄清楚是不是因为我搞砸了某个地方的订单,或者是其他原因。

android android-recyclerview android-contentprovider android-contentresolver android-cursorloader
6个回答
1
投票

终于明白了!

还有另一个愚蠢的错误,它并不复杂,我一直在思考,为什么我只在这个活动上遇到这个问题,而不是我以前的活动,我突然意识到这两个活动的布局是不同的,原来我将RecyclerView的高度设置为wrap_content,所以我想发生了什么,布局告诉系统将内容包装在RecyclerView中,当你删除一个项目时,它在技术上不再存在,所以,即使我有动画为删除项目,该项目立即从布局的级别删除,这就是为什么Android似乎首先调整了RecyclerView的高度,然后删除项目,实际发生的是,因为RecyclerView设置为wrap_content,它删除了视图的位置(项目)删除后立即,而不是动画后,这就是为什么它看起来像一个闪烁。

无论如何,解决方案只是简单地将RecyclerView的高度从wrap_content更改为任何其他值,如果你像我一样使用ConstraintLayout,只需将高度更改为0dp,然后将RecyclerView限制为其他内容或边缘。

感谢所有试图帮助我解决问题的人,我承认这是我遇到过的最愚蠢而令人沮丧的问题之一。

我相信还有其他人也遇到了同样的问题,所以就去检查一下是否将高度设置为wrap_content


0
投票

让断点放在数据对象上,该对象与RecyclerViewAdapter绑定并检查数据是否闪烁。在这种情况的大多数情况下,我意识到数据可能会受到影响并使视图变化无法控制。因为我不知道你如何处理数据,所以我无法为你提供更详细的答案。


0
投票

你试过这个,禁用动画吗?

adapter.setHasStableIds(true);
recyclerView.setItemAnimator(null);

0
投票

Jackz下面的代码在DetailsActivity中,它有一个btnDelete,它会触发并转到DBHelper并删除记录并返回到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中与Adapter对话的代码

    // 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());
}

0
投票

我和你一样陷入困境。我相信问题是CursorLoader每次从数据库中删除时都会重新启动,因此onLoadFinished每次都会触发并交换游标。

如果我们将数据从游标加载到List并将其传递给适配器,则问题可以“解决”。不过,我发现这是一种解决方法,而不是一个真正的解决方案。


0
投票

我确实有同样的问题,这让我发疯。

您的解决方案在我的情况下不起作用,可能是因为我的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>
© www.soinside.com 2019 - 2024. All rights reserved.