MArc Abi Hanna
MArc Abi Hanna

Reputation: 43

FirebaseRecyclerAdapter, PopulateViewHolder called many times when scrolling

I am using a FirebaseRecyclerAdapter to get data from Firebase and fill up a recycler view. The code works fine, but when I start to scroll, the recycler view calls the PopulateViewHolder method with every scroll which makes the scrolling lag alot and sometimes I lose some of the data at the beginning of the recycler view.

my code is:

    final FirebaseRecyclerAdapter<Post, PostsViewHolder> adapt = new FirebaseRecyclerAdapter<Post, PostsViewHolder>(Post.class, R.layout.layout_cardview, PostsViewHolder.class, mRef) {

        @Override
        protected void populateViewHolder(PostsViewHolder viewHolder, Post model, int position) {
            Log.i("CHECK", "POPULATEVIEWHOLDER");
            test.setLongitude(model.getLongitude());
            Log.d("LONGITUDE", model.getLongitude() + "");
            test.setLatitude(model.getLatitude());
            Log.d("LATITUDE", test.getLatitude() + "");
            try {
                if ((location.distanceTo(test) / 1000.0) < 10) {
                    viewHolder.Content.setText(model.getContent());
                    viewHolder.Time.setText(model.getTime());
                } else {
                    viewHolder.delete();
                }
            }catch(Exception e){
                Toast.makeText(getApplicationContext(), "Please Make sure Location is enabled", Toast.LENGTH_LONG).show();
            }
        }
    };
    adapt.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            rv.getLayoutManager().smoothScrollToPosition(rv,null,positionStart);
        }
    });

The PostsViewHolder is:

    public static class PostsViewHolder extends RecyclerView.ViewHolder{

    TextView Content;
    TextView Time;
    CardView cv;

    public PostsViewHolder(View v) {
        super(v);
        Content = (TextView) v.findViewById(R.id.textview_descriptionBrief);
        cv = (CardView) v.findViewById(R.id.post_cardview);
        Time = (TextView) v.findViewById(R.id.textView_time);
    }

    public void delete(){
        cv.setLayoutParams(new RecyclerView.LayoutParams(0,0));
    }
}

and the Post class model contains the getters and setters and fields for each post.

the XML for the list is:

    <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_lookup"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorWhite"
tools:context="com.app.postit.postit.LookupActivity">

<!--<android.support.v7.widget.Toolbar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:id="@+id/toolbar_lookupActivity">

</android.support.v7.widget.Toolbar>-->

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical"
    android:id="@+id/recyclerview_lookupActivity"
    />

<android.support.design.widget.FloatingActionButton
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:layout_alignParentEnd="true"
    android:layout_alignParentBottom="true"
    android:layout_marginRight="10dp"
    android:layout_marginBottom="10dp"
    android:id="@+id/button_floatingButton"
    android:scaleType="center"
    app:backgroundTint="@color/colorWhite"
    app:fabSize="mini"
    android:src="@drawable/ic_add_circle_blue_48dp"
    app:elevation="5dp"
    />

The layout manager is a linear layout manager and the method containing the adapter is only called once in the onCreatemethod.

Upvotes: 4

Views: 1006

Answers (1)

Gabriele Mariotti
Gabriele Mariotti

Reputation: 365158

It is correct.
The populateViewHolder method is called by onBindViewHolder method.

You can check the official javadoc.
This method is called by RecyclerView to display the data at the specified position.

As you scroll you will start getting view holders that were used for rows that went off screen and you have to replace old data that they held with new data.
To do it this method is called.

Check your code.
If there are some time consuming methods (for example if you loading images) in this step, you should use asynchronous tasks.

Upvotes: 2

Related Questions