gpt4 book ai didi

android - 在 LiveData 中加载数据观察 Recycler View : Inconsistency detected. Invalid view holder adapter positionViewHolder

转载 作者:搜寻专家 更新时间:2023-11-01 08:20:55 27 4
gpt4 key购买 nike

我正在开发一个包含照片和相册的示例社交媒体应用程序。将 Android 架构组件 Room、LiveData 和 ViewModel 与 Retrofit 结合使用。 Room 周围有一个存储库层,用于处理数据操作。

RecyclerView -> ViewModel -> Repository -> Room <- Retrofit

@Entity(tableName = "photos",
foreignKeys = {@ForeignKey(entity = AlbumModel.class, parentColumns = "id", childColumns = "album_id")},
indices = {@Index(name = "index_album", value = "album_id")})
public class PhotoModel {

@PrimaryKey
private int id;

@ColumnInfo(name = "album_id")
private int albumId;

private String title;
private String url;
private String thumbnail_url;
}

ViewModel
public class PhotoViewModel extends AndroidViewModel {
private LiveData<List<PhotoModel>> photos;
private PhotoRepository photoRepository;

public LiveData<List<PhotoModel>> getAlbumPhotos(int album_id) {
if(photos == null) {
photos = photoRepository.getAlbumPhotos(album_id);
}
return photos;
}

}

PhotoRepository
public class PhotoRepository implements PhotosInterface {
private LiveData<List<PhotoModel>> photos;
private PhotoDao photoDao;
private AlbumRepository albumRepository;

public LiveData<List<PhotoModel>> getAlbumPhotos(int album_id) {
PhotoController.getAlbumPhotos(this, album_id);
if (photos == null) {
photos = photoDao.getAlbumPhotos(album_id);
}
return photos;
}
}

@Dao
public abstract class PhotoDao {

@Query("SELECT * FROM photos WHERE album_id=:album_id ORDER BY id DESC")
public abstract LiveData<List<PhotoModel>> getAlbumPhotos(int album_id);
}

这就是问题所在:当从服务器获取照片时,它会检查相册,因为 album_id 是照片模型中的外键。这发生在 AsycTask 中。因此,照片未按顺序插入,导致列表适配器更新列表和 UI,从而导致下面提到的错误。这与基于相同架构的应用程序中的其他 Recycler View 存在相同的问题。

//Inserting photos through Photos Dao in Retro callback
private void InsertPhotoWithAlbum(PhotoDao photoDao, AlbumRepository albumRepository, PhotoModel photo) {
if(photoDao.getPhotoObjectById(photo.getId()) == null ) {
if(albumRepository.getAlbumObjectById(photo.getAlbumId()) != null) {
photoDao.insertPhoto(photo);
} else {
albumRepository.fetchAlbum(photo.getAlbumId());
photoDao.insertPhoto(photo);
}
}
}

现在相册包含照片并使用 StaggeredGridLayoutManager 在 RecyclerView 中列出。下面是 RecyclerView 的 ListAdapter。

public class CustomListAdapter extends ListAdapter<PhotoModel, CustomListAdapter.PhotoViewHolder> implements AlbumDetailActivity.RecyclerViewOnClickListener{
private List<PhotoModel> photos;
private Context mContext;

public CustomListAdapter(@NonNull DiffUtil.ItemCallback<PhotoModel> diffCallback, Context context) {
super(diffCallback);
mContext = context;
PhotoViewModel photoViewModel = ViewModelProviders.of(AlbumDetailActivity.this).get(PhotoViewModel.class);
photoViewModel.getAlbumPhotos(album_id).observe(AlbumDetailActivity.this, new Observer<List<PhotoModel>>() {
@Override
public void onChanged(@Nullable List<PhotoModel> photoModels) {
submitList(photoModels);
photos = photoModels;
}
});
// photos = photoViewModel.getAlbumPhotosObjects(album_id);
}

@NonNull
@Override
public PhotoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.listitem_photos_list, null);
PhotoViewHolder viewHolder = new PhotoViewHolder(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

}
});
return viewHolder;
}

@Override
public void onBindViewHolder(@NonNull PhotoViewHolder holder, int position) {
PhotoModel photo = photos.get(position);
holder.tv_title.setText(photo.getTitle());
Picasso.get().load(photo.getThumbnail_url()).into(holder.iv_photo_thumbnail);
}

public class PhotoViewHolder extends RecyclerView.ViewHolder {
TextView tv_title;
ImageView iv_photo_thumbnail;

public PhotoViewHolder(View itemView) {
super(itemView);
tv_title = itemView.findViewById(R.id.tv_photo_title);
iv_photo_thumbnail = itemView.findViewById(R.id.iv_photo_thumbnail);
}

}

@Override
public int getItemCount() {
return photos == null ? 0 : photos.size();
}

@Override
public void onItemClick(PhotoModel photo) {
Toast.makeText(mContext, "Clicked on : " + photo.getId() + ":" + photo.getTitle() , Toast.LENGTH_SHORT).show();
}
}

加载照片时,应用程序崩溃并出现以下错误。

E/AndroidRuntime: FATAL EXCEPTION: main
Process: assess.talview.com.yalview_yasma, PID: 14830
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{b4cfec1 position=42 id=-1, oldPos=39, pLpos:39 scrap [attachedScrap] tmpDetached not recyclable(1) no parent} android.support.v7.widget.RecyclerView{a26494c VFED..... .F....ID 0,0-1080,1731 #7f08007b app:id/recyclerview_photos}, adapter:assess.talview.com.yalview_yasma.album.AlbumDetailActivity$CustomListAdapter@6a61dfa, layout:android.support.v7.widget.StaggeredGridLayoutManager@b391fab, context:assess.talview.com.yalview_yasma.album.AlbumDetailActivity@520aa8f
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5610)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5792)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5752)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5748)
at android.support.v7.widget.LayoutState.next(LayoutState.java:100)
at android.support.v7.widget.StaggeredGridLayoutManager.fill(StaggeredGridLayoutManager.java:1611)
at android.support.v7.widget.StaggeredGridLayoutManager.onLayoutChildren(StaggeredGridLayoutManager.java:685)
at android.support.v7.widget.StaggeredGridLayoutManager.onLayoutChildren(StaggeredGridLayoutManager.java:607)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3763)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3527)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:4082)
at android.view.View.layout(View.java:19659)
at android.view.ViewGroup.layout(ViewGroup.java:6075)
at android.support.design.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1191)
at android.support.design.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:876)
at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:895)
at android.view.View.layout(View.java:19659)
at android.view.ViewGroup.layout(ViewGroup.java:6075)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:19659)
at android.view.ViewGroup.layout(ViewGroup.java:6075)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
at android.view.View.layout(View.java:19659)
at android.view.ViewGroup.layout(ViewGroup.java:6075)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:19659)
at android.view.ViewGroup.layout(ViewGroup.java:6075)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
at android.view.View.layout(View.java:19659)
at android.view.ViewGroup.layout(ViewGroup.java:6075)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:761)
at android.view.View.layout(View.java:19659)
at android.view.ViewGroup.layout(ViewGroup.java:6075)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2496)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2212)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
E/AndroidRuntime: at android.view.Choreographer.doFrame(Choreographer.java:658)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

搜索错误建议提交新列表的副本而不是现有列表,这没有任何区别。

如何解决这个问题?有没有 LiveData 是否有解决方法或不同的方法来处理这个问题?

最佳答案

对于遇到同样问题的人:

问题是当数据列表变大时,数据适配器位置大于数据大小,因为 getItemCount 被覆盖且未更新。所以它在 RecyclerView.Recycle.validateViewHolderForOffsetPosition 方法中没有达到这个条件。

解决方案是不覆盖列表适配器的getItemCount 方法,让Recycler View 处理数据大小。之后该应用程序完美运行。

关于android - 在 LiveData 中加载数据观察 Recycler View : Inconsistency detected. Invalid view holder adapter positionViewHolder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51274925/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com