Проблема с использованием ScrollListener для извлечения данных из БД Firebase Realtime, когда пользователь прокручивает до нижней части RecyclerView - PullRequest
0 голосов
/ 30 мая 2019

У меня есть приложение, которое извлекает данные объекта из БД Firebase Realtime, добавляет их в ArrayList, который затем добавляется в RecyclerView.Я использую onScrollListener в моем RecyclerView, чтобы, когда пользователь прокручивает до нижней части RecyclerView, вызывается функция, чтобы получить больше данных из Firebase, добавить их в ArrayList и уведомить RecyclerViewAdapter об изменении набора данных.

Когда я запускаю свое приложение, оно отображает начальную загрузку данных в моем RecyclerView, а затем немедленно начинает вызывать функцию для непрерывного извлечения дополнительных данных из моей БД, пока не останется больше данных для извлечения, и мой RecyclerView обновится с этими данными.;это происходит независимо от того, прокручиваю ли я (в любом направлении / любой величины) или нет.

В идеале, я бы хотел, чтобы приложение извлекало данные только в том случае, если пользователь прокручивал до нижней части RecyclerView, и делалтак одно нажатие за раз.Мне очень тяжело отлаживать эту проблему, так как логика кажется правильной;любая помощь будет очень полезна.

Соответствующие глобальные переменные

RecyclerView rvVertical;
RecyclerViewAdapter rvaVertical;
long mTotalChildren = 0;
int mLastKey = 0;

ChildEventListener childEventListenerMain, childEventListenerPager;
boolean Loading = false;

private ArrayList<BlogObject> blogArray = new ArrayList<>();
private ArrayList<BlogObject> tempList = new ArrayList<>();

Просмотр загружен

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.socialmediatab, container, false);

    rvVertical = (RecyclerView) view.findViewById(R.id.bloglistRecyclerView);
    Loading = true;
    Log.d(TAG, "onCreateView - Loading = " + Loading);
    firstEventListener();
    regAdapterVertical();

    addOnScrollListener();
    return view;
}

Первая функция, которая вызывается.инициализирует первое извлечение данных из Firebase

private void firstEventListener() {

    FirebaseDatabase.getInstance().getReference().child("blogs").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            mTotalChildren = dataSnapshot.getChildrenCount();
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) { }
    });

    final Query BlogQuery = FirebaseDatabase.getInstance().getReference().child("blogs").orderByChild("createdAt").limitToLast(3);

    childEventListenerMain = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot ds, String s) {
            Loading = true;
            Log.d(TAG, "First get blogs instance - Loading = " + Loading);
            BlogObject addblog = ds.getValue(BlogObject.class);

            if (addblog != null) {
                BlogObject addBlog = new BlogObject(ds.getValue(BlogObject.class).getImage(), ds.getValue(BlogObject.class).getTitle(), ds.getValue(BlogObject.class).getTimeStamp(), ds.getValue(BlogObject.class).getCreatedAt());
                blogArray.add(addBlog);
                rvaVertical.notifyDataSetChanged();
                mLastKey = blogArray.get(0).getCreatedAt();
                rvVertical.scrollToPosition(blogArray.size() - 1);
            }
        }
        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) { }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) { }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) { }

        @Override
        public void onCancelled(DatabaseError databaseError) { }
    };

    BlogQuery.addChildEventListener(childEventListenerMain);
    ValueEventListener BlogChildSingleListener = new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            Loading = false;
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) { }
    };

    BlogQuery.addListenerForSingleValueEvent(BlogChildSingleListener);
}

Добавление прослушивателя прокрутки к моему представлению Recycler.В идеале предполагается, что он будет получать больше данных из Firebase только в том случае, если пользователь прокручивает до нижней части RecyclerView

private void addOnScrollListener() {
    rvVertical.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            Log.d(TAG, "Just Entered onScrolled and Loading = " + Loading);
            super.onScrolled(recyclerView, dx, dy);

            if(!rvVertical.canScrollVertically(1)) {
                LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                if (blogArray.size() >= 3 && !Loading && linearLayoutManager.findLastCompletelyVisibleItemPosition() == blogArray.size() - 1 && blogArray.size() < mTotalChildren) {
                    Loading = true;
                    getMoreBlogs();
                    Log.d(TAG, "Right After getMoreBlogs gets called. Loading = " + Loading);
                }
            }
        }
    });
}

Инициализация адаптера с первым извлечением данных

private void regAdapterVertical() {
    LinearSnapHelper linearSnapHelper = new SnapHelperOneByOne();
    linearSnapHelper.attachToRecyclerView(rvVertical);
    rvaVertical = new RecyclerViewAdapter(blogArray);
    rvVertical.setAdapter(rvaVertical);
    rvVertical.setLayoutManager((RecyclerView.LayoutManager) new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
}

Это моя функция, чтобы получить больше данных из Firebase.Он вызывается в моем Scroll Listener

public void getMoreBlogs() {
    tempList.clear();

    Query getMoreQuery = FirebaseDatabase.getInstance().getReference().child("blogs").orderByChild("createdAt").endAt(mLastKey).limitToLast(3);
    childEventListenerPager = new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot ds, String s) {
            Loading = true;
            BlogObject blogObject = ds.getValue(BlogObject.class);
            if (blogObject != null) {
                BlogObject addBlog = new BlogObject(ds.getValue(BlogObject.class).getImage(), ds.getValue(BlogObject.class).getTitle(), ds.getValue(BlogObject.class).getTimeStamp(), ds.getValue(BlogObject.class).getCreatedAt());
                tempList.add(addBlog);
            }
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) { }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) { }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) { }

        @Override
        public void onCancelled(DatabaseError databaseError) { }
    };

    getMoreQuery.addChildEventListener(childEventListenerPager);

    ValueEventListener addtoAdapter = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            tempList.remove(tempList.size() - 1);
            blogArray.addAll(0, tempList);
            mLastKey = blogArray.get(0).getCreatedAt();
            rvaVertical.notifyDataSetChanged();
            Loading = false;
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };

    getMoreQuery.addListenerForSingleValueEvent(addtoAdapter);
}
}

Это мой Logcat of Loading (логический), который я отслеживал на протяжении всей программы, так как считаю, что это была основная часть проблемы.Я приложил это ниже:

2019-05-30 10:26:14.590 24930-24970/com.yourgesture.newsocialmediatab I/FirebaseAuth: [FirebaseAuth:] Loading module via FirebaseOptions.
2019-05-30 10:26:14.956 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: onCreateView - Loading = true
2019-05-30 10:26:16.399 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: First get blogs instance - Loading = true
2019-05-30 10:26:16.406 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: First get blogs instance - Loading = true
2019-05-30 10:26:16.534 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Just Entered onScrolled and Loading = false
2019-05-30 10:26:16.539 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Right After getMoreBlogs gets called. Loading = true
2019-05-30 10:26:16.663 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Just Entered onScrolled and Loading = false
2019-05-30 10:26:16.666 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Right After getMoreBlogs gets called. Loading = true
2019-05-30 10:26:16.826 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Just Entered onScrolled and Loading = false
2019-05-30 10:26:16.828 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Right After getMoreBlogs gets called. Loading = true
2019-05-30 10:26:16.976 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Just Entered onScrolled and Loading = false
2019-05-30 10:26:16.977 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Right After getMoreBlogs gets called. Loading = true
2019-05-30 10:26:17.229 24930-24930/com.yourgesture.newsocialmediatab D/Social Media Tab: Just Entered onScrolled and Loading = false

1 Ответ

0 голосов
/ 30 мая 2019

В вашем firstEventListener ()

getReference (). Child ("blogs") фактически извлекает целые дочерние данные, которые будут рассматриваться как операция чтения, даже если вы их не используете.

Так что в вашем подходе не будет никакого сохранения данных.

Позвольте мне поделиться одним из подходов:

private void getUsers(String nodeId) {
    Query query;

    if (nodeId == null)
        query = FirebaseDatabase.getInstance().getReference()
                .child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
                .orderByKey()
                .limitToFirst(mPostsPerPage);
    else
        query = FirebaseDatabase.getInstance().getReference()
                .child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
                .orderByKey()
                .startAt(nodeId)
                .limitToFirst(mPostsPerPage);

    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            UserModel user;
            List<UserModel> userModels = new ArrayList<>();
            for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                userModels.add(userSnapshot.getValue(UserModel.class));
            }

            mAdapter.addAll(userModels);
            mIsLoading = false;
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            mIsLoading = false;
        }
    });
}

В новой функции важны три новые переменные: mPostsPerPage: Это константа Integer, определенная в классе MainActivity.java, которая указывает, сколько записей будет запрошено на странице.

mIsLoading: это логическое значение, определенное в MainActivity, которое используется для отслеживания того, находится ли FirebaseЗапрос к базе данных выполняется или нет.

Consts.FIREBASE_DATABASE_LOCATION_USERS: это константа, определенная в классе Consts.java, где хранится просто местоположение узла «users»

Ref: https://blog.shajeelafzal.com/2017/12/13/firebase-realtime-database-pagination-guide-using-recyclerview/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...