Android DiffUtil.ItemCallback areContentsTheSame with different IDs

The best way to achieve what you want is to override the getChangePayload() method in your DiffUtil.Callback implementation.

When areItemsTheSame(int, int) returns true for two items and areContentsTheSame(int, int) returns false for them, DiffUtil calls this method to get a payload about the change.

For example, if you are using DiffUtil with RecyclerView, you can return the particular field that changed in the item and your ItemAnimator can use that information to run the correct animation.

Default implementation returns null.

So, make sure that your areContentsTheSame() method returns false when the database id changes, and then implement getChangePayload() to check for this case and return a non-null value. Maybe something like this:

@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
    if (onlyDatabaseIdChanged(oldItemPosition, newItemPosition)) {
        return Boolean.FALSE;
    } else {
        return null;
    }
}

It doesn't matter what object you return from this method, as long as it's not null in the case where you don't want to see the default change animation be played.

For more details on why this works, see the answer to this question: https://stackoverflow.com/a/47355363/8298909