【问题标题】:RecyclerView Bugs?RecyclerView 错误?
【发布时间】:2019-03-04 06:12:40
【问题描述】:

我有一个笔记应用程序。在主要活动中,注释将与RecyclerView 一起列出。要在数据库中应用更改,我使用FirestoreRecyclerOptions。
但我有一个大问题。首先,一切正常。当 ListItems 更改一次或多次时,一切都会变得混乱。 然后发生了这些事情:

  1. RecyclerViewItems 不可见 (https://www.dropbox.com/s/76e0pi3bgmqdk4u/empty_list.mp4?dl=0)
  2. RecyclerViewItem 不显示 (https://www.dropbox.com/s/5ai92ypev1509qg/dont_show.mp4?dl=0)
  3. RecyclerViewItem 没有删除 (https://www.dropbox.com/s/3k2k3ryecfwnqil/dosnt_remove.mp4?dl=0)

在视频中,您可以看到滚动回收站视图后所有项目都将正常工作。我不知道为什么?也许recyclerview比真正重新加载?

这是我如何设置 RecyclerView 以及当我调用适配器时(MainActivity 的片段):

public class MainActivity extends AppCompatActivity implements RecyclerItemTouchHelper.RecyclerItemTouchHelperListener {

private FirebaseFirestore db;
public NoteListAdapter adapter;
private RecyclerView recyclerView;
private RecyclerView.LayoutManager recyclerViewLayoutManager;

private ListenerRegistration firestoreListener;
private RecyclerItemTouchHelper.RecyclerItemTouchHelperListener listener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    recyclerView = findViewById(R.id.rvNoteList);
    db = FirebaseFirestore.getInstance();

    setUpRecyclerView();
}

private void setUpRecyclerView() {
    FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder().setPersistenceEnabled(true).build();
    db.setFirestoreSettings(settings);

    Query query = db.collection("users").document(firebase_user_uid).collection("notes");


    FirestoreRecyclerOptions<Note> response = new FirestoreRecyclerOptions.Builder<Note>().setQuery(query, Note.class).build();
    adapter = new NoteListAdapter(response, MainActivity.this);

    recyclerViewLayoutManager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false);
    recyclerView.setLayoutManager(recyclerViewLayoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.addItemDecoration(new CustomRecyclerViewDivider(this, LinearLayoutManager.VERTICAL, 16));

    recyclerView.setAdapter(adapter);

    ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT, MainActivity.this);
    new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView);

    adapter.checkIflayoutMustImprove();
}


@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position) {
    adapter.removeItem(viewHolder.getAdapterPosition());
}

private void deleteNote(String id) {
    db.collection("users").document(firebase_user_uid).collection("notes")
            .document(id)
            .delete()
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    mFirebaseAnalytics.logEvent(NOTE_DELETED_EVENT, null);
                }
            });
    adapter.notifyDataSetChanged();
}

@Override
public void onStart() {
    super.onStart();
    adapter.startListening();
}

@Override
public void onStop() {
    super.onStop();
    adapter.stopListening();
}}  

这里是 ItemRecyclerTouchHelper:

public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
private RecyclerItemTouchHelperListener listener;

public RecyclerItemTouchHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
    super(dragDirs, swipeDirs);
    this.listener = listener;
}

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    return true;
}

@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
    if (viewHolder != null) {
        final View foregroundView = ((NoteViewHolder) viewHolder).viewForeground;

        getDefaultUIUtil().onSelected(foregroundView);
    }
}

@Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
                            RecyclerView.ViewHolder viewHolder, float dX, float dY,
                            int actionState, boolean isCurrentlyActive) {
    final View foregroundView = ((NoteViewHolder) viewHolder).viewForeground;
    getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
            actionState, isCurrentlyActive);
}

@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    final View foregroundView = ((NoteViewHolder) viewHolder).viewForeground;
    getDefaultUIUtil().clearView(foregroundView);
}

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
                        RecyclerView.ViewHolder viewHolder, float dX, float dY,
                        int actionState, boolean isCurrentlyActive) {
    final View foregroundView = ((NoteViewHolder) viewHolder).viewForeground;

    getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
            actionState, isCurrentlyActive);
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
}

@Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
    return super.convertToAbsoluteDirection(flags, layoutDirection);
}

public interface RecyclerItemTouchHelperListener {
    void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position);
}}  

我在这个问题上坐了两个星期,我真的需要帮助。我希望任何人都可以帮助我。我什至不知道问题是什么。问题是 RecyclerView 或 Firebase 还是一个简单的错误?当您需要任何其他文件时,请告诉我。 谢谢你帮助我。

编辑 NoteListAdapter

公共类 NoteListAdapter 扩展 FirestoreRecyclerAdapter{

private Context context;
private RelativeLayout no_data_layout;
private Animation fadeIn, fadeOut;

public NoteListAdapter(@NonNull FirestoreRecyclerOptions<Note> options, @NonNull Context context) {
    super(options);
    this.context = context;
}

@Override
protected void onBindViewHolder(@NonNull NoteViewHolder holder, int position, @NonNull Note note) {
    holder.bind(context, note, getSnapshots().getSnapshot(position).getId(), note.getNote_image_url());

    checkIflayoutMustImprove();

    //setAlarms
    if (note.getRemindeDate() != null) {
        if (note.getRemindeDate().before(new Date())) {
            note.setRemindeDate(null);
        }
        if (note.getRemindeDate() != null) {
            Intent i = new Intent(context, TodoNotificationService.class);
            i.putExtra(TodoNotificationService.TODOUUID, note.getId());
            i.putExtra(TodoNotificationService.TODOTEXT, note.getTitle());
            i.putExtra(TodoNotificationService.TODOCONTENT, note.getContent());
            MainActivity.createAlarm(context, i, getSnapshots().getSnapshot(position).getId().hashCode(), note.getRemindeDate().getTime());
        }
    }
    if (note.getRemindeDate() == null) {
        Intent i = new Intent(context, TodoNotificationService.class);
        int id = getSnapshots().getSnapshot(position).getId().hashCode();
        MainActivity.deleteAlarm(context, i, id);
    }
}

@Override
public int getItemCount() {
    return getSnapshots().size();
}

@NonNull
@Override
public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_note_view, parent, false);
    return new NoteViewHolder(view);
}

public void removeItem(int position) {
    getSnapshots().getSnapshot(position).getReference().delete();
    notifyItemRemoved(position);

    checkIflayoutMustImprove();
}}

【问题讨论】:

  • 你真的不应该调用任何 'notifyItemRemoved' 或 'notifyDatasetChanged' 方法,你应该做的就是:监听 FireStore,并更新 FireStore。 FirebaseUI 库应该会为您处理剩下的事情
  • @Linxy 但是我该怎么办?因为它似乎不起作用。我不认为删除所有notifyDataSetChanged() 会更好。还有其他解决方案吗?

标签: android firebase android-recyclerview google-cloud-firestore recyclerview-layout


【解决方案1】:

感谢您的所有帮助,但没有人能回答这个问题。我在我的应用程序中编写了一个沉浸模式()。即使有任何交互,他也会将屏幕设置为全屏。我注意到,当我删除了沉浸式模式()方法时,我曾经在 recyclerview 上遇到的所有错误都消失了。我不能说为什么,但现在它起作用了。但是感谢大家。 :)

【讨论】:

    【解决方案2】:

    放这条线

    adapter.notifyDataSetChanged();
    

    在你的

    addOnCompleteListener()
    

    所以你的 onCompleteListener 看起来像这样

    addOnCompleteListener(new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        mFirebaseAnalytics.logEvent(NOTE_DELETED_EVENT, null);
                        adapter.notifyDataSetChanged();
                    }
                });
    

    如果这不起作用,那么您也应该发布您的适配器类。

    【讨论】:

    • 谢谢。它使它的工作时间更长。但是一段时间后添加和删除项目它就不再起作用了。 “也发布您的适配器类”是什么意思?可以举个例子吗?
    • 你是什么意思它使它工作更长时间?问题是您对adapter.notifyDataSetChanged() 的调用在onCompleteListener 完成之前运行(onCompleteListener 异步运行)。我的意思是你需要发布NoteListAdapter.class
    • @Mina..嘿,谢谢。我在我的问题中发布了我的适配器。所以它工作了一段时间。但是一段时间后我遇到了同样的问题。当我添加一个项目时,没有修复的是 iusse,只有当我在回收站视图中滚动时,列表才会更新。 (注意:我在firestore中添加了一条注释,firestorequerylistener应该在mainactivity中自动更新)
    • 您在添加项目时是否调用notifyDataSetChanged()?您在哪里添加新项目的代码?
    • 我不打电话给adapter.notifyDataSetChanged()。我只将它添加到firestore。这将在单独的活动中发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多