androidandroid-recyclerviewandroid-contentproviderandroid-contentresolverandroid-cursorloader

RecyclerView last item blinks every time an item is removed


I'm using a cursor loader with the RecyclerView, and everything else works just fine except every time I remove an item from the RecyclerView, the last item blinks, like this

last item blinks

my code for deletion is

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

code on swipe:

deleteData(viewHolder.getItemId());

note that I have another activity that's using the same RecyclerAdapter, ContentProvider and layout code, even most of the implementations and method approaches are the same, but that one works perfectly without any blinks, so it is a pretty weird situation for me.

Is there a specific reason that can cause this problem? I already tried disabling the animation like

recyclerView.getItemAnimator().setChangeDuration(0);

or

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

But none of that worked, not to mention that I do want the animations to work.

Edit: Break points upload:

onCreate:

"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(remove item):

"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) at android.support.v7.widget.helper.ItemTouchHelper$4.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)

Hope those helps

Edit: After a little investigation, I found out that the last item didn't actually blink, it seems that the RecyclerView first changed it's length/size, cuts off a section that has the equal size as the deleted item(deleting), so that the last item(depending on the size of the deleted item) is not visible for a while, and then the RecyclerView deletes the item that's supposed to be deleted at the beginning. I'm still working on it, trying to figure out whether it's because I messed up the order somewhere or it's some other reason.


Solution

  • Finally got it!

    Yet another stupid mistake, it's not complicated at all, I kept thinking, why I'm having this problem only on this activity, but not my previous one, and I suddenly realized that the layout in the two activities are different, turns out I set the RecyclerView's height to wrap_content, so I suppose what happened is that, the layout told the system to wrap the content in the RecyclerView, and when you delete an item, it's technically not there anymore, so, even though I have animations for the deleted item, the item is removed immediately from the layout's level, that's why it seems like Android adjusted the RecyclerView's height first, and then delete the item, what actually happened is, since RecyclerView is set to wrap_content, it removes the position of the view(item) immediately after delete, not after the animation, and that's why it looks like a blink.

    Anyways, the solution is just simply to change the RecyclerView's height from wrap_content to any other value, if you are using ConstraintLayout like I did, just change the height to 0dp, then constraint the RecyclerView to something else, or the edge.

    Thanks to everyone who tried to help me solve my problem though, I admit this is one of the stupidest yet frustrating problems I ever had.

    I believe there're others who also encountered the same problem, so just go and check if the height is set to wrap_content.