Ранее я сталкивался с этой проблемой и решил ее путем создания пользовательского LinearLayoutManager и использования его для моего RecyclerView. Но снова эта проблема возникла и не получить никакой подсказки о том, как ее решить. Все обновления и уведомления для адаптера выполняются в потоке пользовательского интерфейса.
Может кто-нибудь помочь мне решить эту проблему.
Код адаптера
using System.Collections.Generic;
using Android.Support.V7.Widget;
using Android.Views;
using TabApplications.Applications.Navigation.Models;
namespace HMI_Common.Adapters.Navigation.AddressSearch
{
public class NaviAddressItemAdapter : RecyclerView.Adapter
{
private List<AddressDetailEntity> _addressSearchItems;
private List<AddressSuggestionEntry> _addressSuggestionEntries;
private List<FTSTokenElement> _searchCriteriaEntities;
private readonly INaviAddressItemClickListener _addressItemClickListener;
private const int CountryItemType = 0, DestinationItemType = 1, AddressSuggestionType = 2;
private bool _isForCountryItemType, _isForFederalStateType, _isForAddressSuggestion;
private readonly bool _isCountrySelectionAvailable;
private readonly int _backButtonLayoutResourceID = -1;
private readonly NaviEnums.NaviMarket _currentNaviMarket;
public NaviAddressItemAdapter(List<AddressDetailEntity> addressItems, NaviEnums.NaviMarket naviMarket,
INaviAddressItemClickListener listener, bool isCountryAvailable, int backButtonLayoutID) :
this(naviMarket, listener, isCountryAvailable, backButtonLayoutID)
{
_addressSearchItems = addressItems;
}
public NaviAddressItemAdapter(List<AddressSuggestionEntry> addressItems, NaviEnums.NaviMarket naviMarket,
INaviAddressItemClickListener listener, bool isCountryAvailable, int backButtonLayoutID) :
this(naviMarket, listener, isCountryAvailable, backButtonLayoutID)
{
_addressSuggestionEntries = addressItems;
}
private NaviAddressItemAdapter(NaviEnums.NaviMarket naviMarket, INaviAddressItemClickListener listener, bool isCountryAvailable, int backButtonLayoutID)
{
_currentNaviMarket = naviMarket;
_addressItemClickListener = listener;
_backButtonLayoutResourceID = backButtonLayoutID;
_isCountrySelectionAvailable = isCountryAvailable;
_searchCriteriaEntities?.Clear();
_searchCriteriaEntities = null;
_searchCriteriaEntities = new List<FTSTokenElement>();
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
switch (GetItemViewType(position))
{
case CountryItemType:
((NaviCountryItemViewHolder)holder).DisplayCountryItemData(_addressSearchItems[position], position,
_isCountrySelectionAvailable, _isForFederalStateType, _addressSearchItems.Count - 1);
break;
case DestinationItemType:
((NaviLocationItemViewHolder)holder).DisplayAddressItemData(_addressSearchItems[position], position, _addressSearchItems.Count - 1);
break;
case AddressSuggestionType:
((NaviLocationItemViewHolder)holder).DisplaySuggestionItemData(_addressSuggestionEntries[position],
position, _searchCriteriaEntities, _addressSuggestionEntries.Count - 1);
break;
}
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
switch (viewType)
{
case CountryItemType:
var countryItemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.view_browsing_track, parent, false);
return new NaviCountryItemViewHolder(parent.Context, countryItemView, _addressItemClickListener, _backButtonLayoutResourceID);
case DestinationItemType:
case AddressSuggestionType:
var addressItemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.view_browsing_meta, parent, false);
return new NaviLocationItemViewHolder(parent.Context, _currentNaviMarket, addressItemView,
_addressItemClickListener, viewType == AddressSuggestionType, _backButtonLayoutResourceID);
default:
return null;
}
}
public override int ItemCount => _isForAddressSuggestion ? _addressSuggestionEntries.Count : _addressSearchItems.Count;
public void UpdateAddressListItems(List<AddressDetailEntity> updatedAddressItems)
{
_addressSearchItems = updatedAddressItems;
if(ItemCount > 0)
{
NotifyDataSetChanged();
}
}
public void UpdateAddressSuggestionsItems(List<AddressSuggestionEntry> updatedAddressItems)
{
var existingSuggestionsAvailable = null != _addressSuggestionEntries ? ItemCount : 0;
_addressSuggestionEntries = updatedAddressItems;
if(ItemCount > 0)
{
if (existingSuggestionsAvailable == 0)
{
NotifyDataSetChanged();
}
else
{
NotifyItemRangeInserted(existingSuggestionsAvailable, updatedAddressItems.Count - 1);
NotifyItemChanged(existingSuggestionsAvailable - 1);
}
}
}
public override int GetItemViewType(int position)
{
if (_isForCountryItemType)
{
return CountryItemType;
}
return _isForAddressSuggestion ? AddressSuggestionType : DestinationItemType;
}
public List<AddressDetailEntity> GetDisplayedAddressSearchItems()
{
return _addressSearchItems;
}
public List<AddressSuggestionEntry> GetDisplayedAddressSuggestionsItems()
{
return _addressSuggestionEntries;
}
public void UpdateIsForCountryLevelSearch(bool isForCountryLevelSearch)
{
_isForCountryItemType = isForCountryLevelSearch;
}
public void UpdateIsForFederalStateType(bool isForFederalState)
{
_isForFederalStateType = isForFederalState;
}
public bool IsAddressSearchResultsItemsDisplayed()
{
if(!_isForCountryItemType && !_isForFederalStateType && !_isForAddressSuggestion
&& null != _addressSearchItems && _addressSearchItems.Count > 0)
{
return true;
}
return false;
}
public void UpdateIsForAddressSuggestion(bool isForSuggestion)
{
_isForAddressSuggestion = isForSuggestion;
if (!isForSuggestion)
{
_addressSuggestionEntries?.Clear();
}
}
public void ClearDisplayedSearchItems()
{
_addressSearchItems?.Clear();
_addressSuggestionEntries?.Clear();
}
public void UpdateSearchCriteriaEntities(List<FTSTokenElement> criteriaItems)
{
_searchCriteriaEntities?.Clear();
_searchCriteriaEntities = null;
_searchCriteriaEntities = new List<FTSTokenElement>(criteriaItems);
}
public void RemoveViewEvents(RecyclerView.ViewHolder appropriateViewHolder)
{
if (null != appropriateViewHolder)
{
if (appropriateViewHolder is NaviCountryItemViewHolder)
{
((NaviCountryItemViewHolder)appropriateViewHolder).RemoveViewEvents();
}
else if (appropriateViewHolder is NaviLocationItemViewHolder)
{
((NaviLocationItemViewHolder)appropriateViewHolder).RemoveViewEvents();
}
}
}
}
}
Код для инициализации адаптера
private void DisplayAddressDetailEntries(List<AddressDetailEntity> addressDetailEntities, bool isForCountryItemDisplay = false)
{
if (null == _addressItemAdapter)
{
_addressItemAdapter = new NaviAddressItemAdapter(addressDetailEntities, _navigationBackend?.GetNaviMarket() ?? NaviEnums.NaviMarket.Europe,
this, IsCountryLevelSearchAvailable(),
((NavigationBaseActivity) Activity)._backButtonInfoLayout.Id);
_addressItemsRecyclerView.SetAdapter(_addressItemAdapter);
}
_addressItemAdapter.UpdateIsForCountryLevelSearch(isForCountryItemDisplay);
_addressItemAdapter.UpdateIsForFederalStateType(_isForFederalStatesSearch);
_addressItemAdapter.UpdateIsForAddressSuggestion(false);
_addressItemAdapter.UpdateAddressListItems(addressDetailEntities);
_addressItemAdapter.UpdateSearchCriteriaEntities(_searchCriteriaEntities);
DisplayLoadingView(false);
if (!isForCountryItemDisplay && !_isFirstScroll)
{
DisplayAddressResultsAnnotations(true);
}
if (_isAddressResultsDisplayedForFirstTime)
{
_isAddressResultsDisplayedForFirstTime = false;
_navigationBackend.VerifyCurrentHUSystemLanguage();
}
}
private void DisplayAddressSuggestionEntries(List<AddressSuggestionEntry> addressSuggestionEntries)
{
if(null != _addressItemAdapter && _addressItemAdapter.IsAddressSearchResultsItemsDisplayed())
{
return;
}
if (null == _addressItemAdapter)
{
_addressItemAdapter = new NaviAddressItemAdapter(addressSuggestionEntries, _navigationBackend?.GetNaviMarket() ?? NaviEnums.NaviMarket.Europe,
this, IsCountryLevelSearchAvailable(),
((NavigationBaseActivity)Activity)._backButtonInfoLayout.Id);
_addressItemsRecyclerView.SetAdapter(_addressItemAdapter);
}
_addressItemAdapter.UpdateIsForCountryLevelSearch(false);
_addressItemAdapter.UpdateIsForFederalStateType(false);
_addressItemAdapter.UpdateIsForAddressSuggestion(true);
_addressItemAdapter.UpdateAddressSuggestionsItems(addressSuggestionEntries);
DisplayLoadingView(false);
if (null != Activity)
{
((NavigationBaseActivity)Activity).RemoveAddressResultsAnnotations(isCurrentLocationToBeShown: true, isKeyboardToBeRemoved: false);
}
}
Исключение
54614: 54613 2020/04/22 19:42:43.876064 1530.7664 80 RSER ANDR LOGA 666 log info verbose 1 --------- beginning of crash
54615: 54614 2020/04/22 19:42:43.876118 1530.7665 81 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: FATAL EXCEPTION: main
54616: 54615 2020/04/22 19:42:43.876135 1530.7665 82 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: Process: com.daimler.rse.ntg6, PID: 1526
54617: 54616 2020/04/22 19:42:43.876150 1530.7666 83 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{aa13176 position=25 id=-1, oldPos=-1, pLpos:-1 no parent} android.support.v7.widget.RecyclerView{655ce4e I.ED.V... .......D 0,128-1326,925 #7f09020d app:id/rvList}, adapter:md5802e7c015aa94524afab2f053beb78c2.NaviAddressItemAdapter@106c06a, layout:md593dc4a3d225f231fc4cef6d7741b0b60.CustomLinerLayoutManager@484a07c, context:md59d95dbab71941e137ef724fbceda5f0e.NavigationBaseActivity@8ab1e87
54618: 54617 2020/04/22 19:42:43.876165 1530.7666 84 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5447)
54619: 54618 2020/04/22 19:42:43.876180 1530.7666 85 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5629)
54620: 54619 2020/04/22 19:42:43.876194 1530.7666 86 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:285)
54621: 54620 2020/04/22 19:42:43.876209 1530.7667 87 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:342)
54622: 54621 2020/04/22 19:42:43.876236 1530.7667 88 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:358)
54623: 54622 2020/04/22 19:42:43.876251 1530.7667 89 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.support.v7.widget.GapWorker.prefetch(GapWorker.java:365)
54624: 54623 2020/04/22 19:42:43.876265 1530.7667 90 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.support.v7.widget.GapWorker.run(GapWorker.java:396)
54625: 54624 2020/04/22 19:42:43.876280 1530.7668 91 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:790)
54626: 54625 2020/04/22 19:42:43.876294 1530.7668 92 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:99)
54627: 54626 2020/04/22 19:42:43.876308 1530.7668 93 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.os.Looper.loop(Looper.java:164)
54628: 54627 2020/04/22 19:42:43.876322 1530.7668 94 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6518)
54629: 54628 2020/04/22 19:42:43.876336 1530.7669 95 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
54630: 54629 2020/04/22 19:42:43.876350 1530.7669 96 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:483)
54631: 54630 2020/04/22 19:42:43.876364 1530.7669 97 RSER ANDR LOGA 666 log error verbose 1 04-22 14:12:43.866 1526 1526 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811)
54655: 54654 2020/04/22 19:42:44.053564 1530.9443 111 RSER ANDR LOGA 666 log info verbose 1 04-22 14:12:44.040 1244 5620 I am_crash: [1526,0,com.daimler.rse.ntg6,953728589,java.lang.IndexOutOfBoundsException,Inconsistency detected. Invalid view holder adapter positionViewHolder{aa13176 position=25 id=-1, oldPos=-1, pLpos:-1 no parent} android.support.v7.widget.RecyclerView{655ce4e I.ED.V... .......D 0,128-1326,925 #7f09020d app:id/rvList}, adapter:md5802e7c015aa94524afab2f053beb78c2.NaviAddressItemAdapter@106c06a, layout:md593dc4a3d225f231fc4cef6d7741b0b60.CustomLinerLayoutManager@484a07c, context:md59d95dbab71941e137ef724fbceda5f0e.NavigationBaseActivity@8ab1e87,RecyclerView.java,5447]