1

Hi i need to stop an RecyclerView reloading the data when scrolling up but I don't know how to :( and I search about it but i can't find any answer

Adapter: mPostAdapterNew

RecyclerView : MPostRV_new

So can you guys help me ? thanks in advance :D

Edit: This is my code:

    private void setupAdaptaterNew() {
    mPostAdapterNew = new FirebaseRecyclerAdapter<Post, PostViewHolder>(
            Post.class,
            R.layout.item_layout_evenimente,
            PostViewHolder.class,
            mPostRef
    ) {

        @Override
        public void populateViewHolder(final PostViewHolder viewHolder, final Post model, final int position) {
            final long EndZi = viewHolder.setEndZi(model.getEndZi());
            final int EndLuna = viewHolder.setEndLuna(model.getEndLuna());
            final int EndAn = viewHolder.setEndAn(model.getEndAn());
            Calendar cal = Calendar.getInstance();
            final Button btnAddEvent = viewHolder.itemView.findViewById(R.id.BtnParticip);
            final Button btnDeleteEvent = viewHolder.itemView.findViewById(R.id.BtnNuParticip);
            final int EndOra = viewHolder.setEndOra(model.getEndOra());
            final int EndMinute = viewHolder.setEndMinute(model.getEndMinute());
            final String headline = viewHolder.setHeadline(model.getHeadline());
            final String locatie = viewHolder.setStrada(model.getStrada());
            final String organizator = viewHolder.setOrganizator(model.getOrganizator());
            final String descriere = viewHolder.setPostDescriere(model.getDescriere());
            final ContentResolver cr = getActivity().getContentResolver();
            final ContentValues values = new ContentValues();
            final ContentResolver crReminder = getActivity().getContentResolver();
            final ContentValues valuesReminder = new ContentValues();
            final Uri event = null;
            final TextView nr_persoane = viewHolder.itemView.findViewById(R.id.nr_persoane);
            final String key = this.getRef(position).getKey();
            final Cursor data = mDatabaseHelper.getData();

            cal.set(Calendar.HOUR, 24);
            cal.set(Calendar.MINUTE, 59);
            cal.set(Calendar.MILLISECOND, 0);
            cal.set(Calendar.MONTH, EndLuna);
            cal.set(Calendar.DAY_OF_MONTH, (int) EndZi);
            cal.set(Calendar.YEAR, EndAn);


            if (Calendar.getInstance().before(cal)) {
                StorageReference storageReference = FirebaseStorage.getInstance().getReferenceFromUrl(model.getImageUrl());
                Glide.with(Fragment_events_new.this)
                        .using(new FirebaseImageLoader())
                        .load(storageReference)
                        .asBitmap()
                        .centerCrop()
                        .into(new SimpleTarget<Bitmap>() {
                            @Override
                            public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                                viewHolder.postIV.setImageBitmap(resource);
                            }
                        });


                viewHolder.setHeadline(model.getHeadline());
                viewHolder.setZiua(model.getZiua());
                viewHolder.setLuna(model.getLuna());
                viewHolder.setOra(model.getOra());
                viewHolder.setOrganizator(model.getOrganizator());
                viewHolder.setCategoria(model.getCategoria());
                viewHolder.setStrada(model.getStrada());
                viewHolder.setLocalitatea(model.getLocalitatea());
                viewHolder.setPostDescriere(model.getDescriere());
                viewHolder.setNrPersoane(model.getNrPeople());
            } else {
                viewHolder.itemView.setVisibility(View.GONE);
                viewHolder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
            }

            btnAddEvent.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED ||
                            ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
                        Toast.makeText(getActivity(), "Permisii insuficiente.\n Va rugam sa activati permisiunea de CALENDAR", Toast.LENGTH_LONG).show();
                        NoPermissions();
                    } else {
                        addEvent(values, EndZi, EndAn, EndLuna, EndOra, EndMinute, headline, descriere, locatie, organizator, event, cr, valuesReminder, crReminder);
                        int i = viewHolder.setNrPersoane(model.getNrPeople()) + 1;
                        nr_persoane.setText(String.valueOf(i));
                        mPostRef.child(key).child("nrPeople").setValue(i);
                    }
                }
            });

            btnDeleteEvent.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    deleteEvent(data, headline);
                    btnAddEvent.setVisibility(View.VISIBLE);
                    btnDeleteEvent.setVisibility(View.GONE);
                    int i = viewHolder.setNrPersoane(model.getNrPeople()) - 1;
                    nr_persoane.setText(String.valueOf(i));
                    mPostRef.child(key).child("nrPeople").setValue(i);
                }
            });

            if (CheckDB(headline)) {
                btnAddEvent.setVisibility(View.GONE);
                btnDeleteEvent.setVisibility(View.VISIBLE);
            } else {
                btnAddEvent.setVisibility(View.VISIBLE);
                btnDeleteEvent.setVisibility(View.GONE);
            }
        }
    };

}

@SuppressLint("MissingPermission")
private void addEvent(ContentValues values, float EndZi, int EndAn, int EndLuna, int EndOra, int EndMinute,
                      String headline, String descriere, String locatie, String organizator,
                      Uri event, ContentResolver cr, ContentValues valuesReminder, ContentResolver crReminder) {
    long startMillis = 0;
    long endMillis = 0;


    Calendar beginTime = Calendar.getInstance();
    beginTime.set(EndAn, EndLuna, (int) EndZi, EndOra, EndMinute);
    startMillis = beginTime.getTimeInMillis();
    Calendar endTime = Calendar.getInstance();
    endTime.set(EndAn, EndLuna, (int) EndZi, EndOra, EndMinute);
    endMillis = endTime.getTimeInMillis();
    //Add Values
    values.put(CalendarContract.Events.DTSTART, startMillis);
    values.put(CalendarContract.Events.TITLE, headline);
    values.put(CalendarContract.Events.DESCRIPTION, descriere); //TODO change description here!
    TimeZone timeZone = TimeZone.getDefault();
    values.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone.getID());
    values.put(CalendarContract.Events.CALENDAR_ID, 1);
    values.put(CalendarContract.Events.DTEND, endMillis);
    values.put(CalendarContract.Events.EVENT_LOCATION, locatie);
    values.put(CalendarContract.Events.ORGANIZER, organizator);
    event = cr.insert(CalendarContract.Events.CONTENT_URI, values);
    valuesReminder.put(CalendarContract.Reminders.DTSTART, startMillis);
    Uri REMINDERS_URI_DAY = Uri.parse(getCalendarUriBase(true) + "reminders");
    valuesReminder = new ContentValues();
    valuesReminder.put("event_id", Long.parseLong(event.getLastPathSegment()));
    valuesReminder.put("method", 1);
    valuesReminder.put("minutes", 1440);

    Uri uriReminderDay = crReminder.insert(REMINDERS_URI_DAY, valuesReminder);
    Uri REMINDERS_URI_HOUR = Uri.parse(getCalendarUriBase(true) + "reminders");
    valuesReminder = new ContentValues();
    valuesReminder.put("event_id", Long.parseLong(event.getLastPathSegment()));
    valuesReminder.put("method", 1);
    valuesReminder.put("minutes", 120);
    Uri uriReminder = crReminder.insert(REMINDERS_URI_HOUR, valuesReminder);

    createDialog(headline, "Ati adaugat evenimentul in calendar!");
    String event_id = String.valueOf(Long.parseLong(event.getLastPathSegment()));
    AddData(headline, event_id);
}

private void deleteEvent(Cursor data, String headline) {
    while (data.moveToNext()) {
        if (data.getString(1).equals(headline)) {
            Uri deleteUri = null;
            deleteUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, Long.parseLong(data.getString(2)));
            int rows = getActivity().getContentResolver().delete(deleteUri, null, null);
            createDialog(headline, "Ati sters evenimentu din calendar!");
            mDatabaseHelper.deleteData(headline, data.getString(2));

        }
    }
}

private boolean CheckDB(String headline) {
    Cursor data = mDatabaseHelper.getData();
    while (data.moveToNext()) {
        if (data.getString(1).equals(headline)) {
            return true;
        }
    }
    return false;
}
  • What do you mean "stop reloading data" ? Do you mean like the scrolling gets locked on the current visible items ? – Arthur Attout Mar 31 '18 at 19:03
  • So i have an recyclerView whit datas and hen i ant to scroll up the scroll isn't smooth and i saw that in android console the values from the RecyclerView reloads the data from the adapter and the scroll isn't smooth until the refresh/reload it's done – Luis Fernando Scripcaru Mar 31 '18 at 19:05
  • Maybe you are loading too many items (or the items are too complex) it's hard to tell without any samples of your code in order to help you out – Anton Makov Mar 31 '18 at 19:08
  • @AntonMakov I've added the code but i think that i do too many things for every results because i have one more adapter but i don't have so much code in it :) – Luis Fernando Scripcaru Apr 01 '18 at 16:35
  • You need to fetch your data (to pull it from DB/web or other sources) before you creating your adapter. The slowness comes from the fact that each time you scroll the list it needs to read/fetch the data from the source db/web populate the data and create the view of the list item => too much time consuming and that's why it's very slow – Anton Makov Apr 01 '18 at 17:27
  • And how can i do it? :) Can you explain to me how to do it because i don't have a lot of experience whit android or java – Luis Fernando Scripcaru Apr 01 '18 at 17:31
  • I added my answer you should look in the link from my post to see how do you fetch those items too – Anton Makov Apr 01 '18 at 18:03

3 Answers3

2

Hi I've faced the same issue here especially if I've to load a medial like an image to RecyclerView using a little big cache solves the problem for me here you are

MPostRV_new=view.findViewById(R.id.your_layout);
MPostRV_new.setHasFixedSize(true);
MPostRV_new.setLayoutManager(new LinearLayoutManager(getContext()));
MPostRV_new.setItemAnimator(null);
MPostRV_new.setItemViewCacheSize(50);

For more info check this resource setItemViewCacheSize

Hossam Ali
  • 792
  • 4
  • 11
1

Basically you need to create a class for your recycle view adapter (you should use recycleview instead of using listview because it's newer then listview and have many optimization and new functionalities that listview doesn't have).

MyRecyclerViewAdapter

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.CustomViewHolder> {
private List<FeedItem> feedItemList;
private Context mContext;

public MyRecyclerViewAdapter(Context context, List<FeedItem> feedItemList) {
    this.feedItemList = feedItemList;
    this.mContext = context;
}

@Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null);
    CustomViewHolder viewHolder = new CustomViewHolder(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(CustomViewHolder customViewHolder, int i) {
    FeedItem feedItem = feedItemList.get(i);

    //Render image using Picasso library
    if (!TextUtils.isEmpty(feedItem.getThumbnail())) {
        Picasso.with(mContext).load(feedItem.getThumbnail())
                .error(R.drawable.placeholder)
                .placeholder(R.drawable.placeholder)
                .into(customViewHolder.imageView);
    }

    //Setting text view title
    customViewHolder.textView.setText(Html.fromHtml(feedItem.getTitle()));
}

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

class CustomViewHolder extends RecyclerView.ViewHolder {
    protected ImageView imageView;
    protected TextView textView;

    public CustomViewHolder(View view) {
        super(view);
        this.imageView = (ImageView) view.findViewById(R.id.thumbnail);
        this.textView = (TextView) view.findViewById(R.id.title);
    }
}

}

as you can see in the above example, all the items are already fetched (ready to display instead of just getting them each time the user scroll up/down the list). second there are a few functions like onCreateViewHolder where you need to create your own view holder (inflate the layout and create from it a holder that will hold all the views that will be used to show the data that you want to show in the list). second onBindViewHolder is for binding (connecting) the views in the holder with the data that the adapter is getting from it's constructor.

After you implement the adapter you should use it as follows: somewhere in your activity/fragment

...
List<FeedItem> data = manager.getItems();
MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(MainActivity.this, feedsList);
mRecyclerView.setAdapter(adapter);
...

A few things to notice here: 1) manager.getItems(); is a manager from where you can get your items from, in order to use it you need to know from where you need to get those items(web/storage or other source) then you need to implement it (there are many sites that explain how to do it. 2) if you are using fragment you should use instead of MainActivity.this getActivity()

you can see for more details here

Hope it will help you understand how to do it.

Anton Makov
  • 825
  • 2
  • 9
  • 25
0

The point of using RecyclerView as a component is that it rebuilds visible items every time you scroll so it will load the data , you cannot "prevent" it.

You have two options:

  1. Check if you have long-running operations (i.e., you query net every time or your viewholder has big images and complex structure). Try to optimize it, for example store data from net queries or resize pics

  2. Use ListView. It loads all items immediately and then if you explicitly call for update only then it will update.

Rainmaker
  • 10,294
  • 9
  • 54
  • 89
  • I load my images whit url from database and the size on the layout is 90/90 . In list view i can use images too? – Luis Fernando Scripcaru Mar 31 '18 at 19:21
  • is this database that you query internal or external? some apps with lots of images use empty containers for pics so the user doesn't have to wait for the pictures they just catch up with the rest of the layout after they are loaded. yes,listview looks visually identical , check out http://www.vogella.com/tutorials/AndroidListView/article.html – Rainmaker Mar 31 '18 at 19:54
  • Externally from Firebase – Luis Fernando Scripcaru Mar 31 '18 at 20:14
  • ok, there're similar question that firebase images load too slowly into recycler and create unsmooth scrolling. To answer the question you asked , you cannot stop reloading recycler. the way to go is listview. But you can approach this problem differently. Try looking into why your images load too slowly , how to make it faster and then it will make smoother the recycler. for example https://stackoverflow.com/questions/26856487/recyclerview-painfully-slow-to-load-cached-images-form-picasso – Rainmaker Mar 31 '18 at 20:48
  • II don't think it's from images because i have another adapter that has like 5x more times images and the scroll is smooth – Luis Fernando Scripcaru Apr 01 '18 at 16:39
  • it's good you're using Glide to help load imgs, I would try putting this line yourRecyclerview.setNestedScrollingEnabled(false); in your code because it helps people with this "unsmooth" scrolling but honestly, I cannot see other issues except for the bulky operations you have in recycler – Rainmaker Apr 01 '18 at 17:22