1

In my app I am using a RecyclerView, that is supposed to continue loading images when the user scrolls down. But this brought me to an issue I couldn't resolve. Basically, I saying

        loadPhotos.LoadMoreItems(3);

which means, load 3 photos to begin with. As soon as a certain point is reached (via scrolling) continue loading another 3 pictures (which make up one row):

        var onScrollListener = new XamarinRecyclerViewOnScrollListener(mLayoutManager);
        onScrollListener.LoadMoreEvent += (object sender, EventArgs e) => 
        {
            int oldCount = loadPhotos.pictures.Count;
            loadPhotos.LoadMoreItems(3);
            mAdapter.NotifyItemRangeChanged(oldCount - 1, loadPhotos.pictures.Count);
        };

If I only load 3 photos, to begin with, the phone loads 3 photos and a split-second after, it loads the next row, because the position is reached. So this does in fact work, but If I would start scrolling I get this error:

 “cannot call this method while RecyclerView is computing a layout or scrolling” 

On this line:

mAdapter.NotifyItemRangeChanged(oldCount - 1, loadPhotos.pictures.Count);

Another interesting fact is, that I can get this to work on small phones, but phones with a larger screen (Samsung s8) will have a crash sooner.

So, I am really confused on how to do all that. Just as extra info, this is my whole activity:

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        SetContentView(Resource.Layout.Fragment_Gallery);


        galleryType = Intent.GetIntExtra("galleryType", 0);

        picturesinarow = Intent.GetIntExtra("picturesinarow", 1);

        recyclerLayout = Intent.GetIntExtra("recyclerLaoyut", (int)RecyclerLayout.Multiplepics);

        hasHeader = Intent.GetBooleanExtra("hasHeader", false);

        // Instantiate the photo album:
        loadPhotos = new BookOfLife.CustomRecyclerView.ReloadAdapter(this.galleryType);
        loadPhotos.LoadMoreItems(3);//(Constants.ITEMSPERPAGE);

        // Get our RecyclerView layout:
        mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);



        //............................................................
        // Layout Manager Setup:

        // Use the built-in linear layout manager:
        //mLayoutManager = new LinearLayoutManager(this);

        // Or use the built-in grid layout manager (two horizontal rows):
        mLayoutManager = new GridLayoutManager(this, this.picturesinarow, GridLayoutManager.Vertical, false);

        // Plug the layout manager into the RecyclerView:
        mRecyclerView.SetLayoutManager(mLayoutManager);

        //............................................................
        // Adapter Setup:

        // Create an adapter for the RecyclerView, and pass it the
        // data set (the photo album) to manage:
        mAdapter = new PhotoAlbumAdapter(loadPhotos, this.picturesinarow, (RecyclerLayout)this.recyclerLayout, this.hasHeader);

        // Register the item click handler (below) with the adapter:
        mAdapter.ItemClick += OnItemClick;

        // Plug the adapter into the RecyclerView:
        mRecyclerView.SetAdapter(mAdapter);
        //.........................................................................

        //Set Spanwidth for GridHeader
        mLayoutManager.SetSpanSizeLookup(new GridViewSpansizeLookup(mAdapter, mLayoutManager));


        // On Scroll Listener
        var onScrollListener = new XamarinRecyclerViewOnScrollListener(mLayoutManager);
        onScrollListener.LoadMoreEvent += (object sender, EventArgs e) => 
        {
            int oldCount = loadPhotos.pictures.Count;
            loadPhotos.LoadMoreItems(3);//(Constants.LOADNEXTITEMSTHRESHHOLD);


            mAdapter.NotifyItemRangeChanged(oldCount - 1, loadPhotos.pictures.Count);
        };

        mRecyclerView.AddOnScrollListener(onScrollListener);
    }

Hope, you guys can help me out here :)

FreakyAli
  • 13,349
  • 3
  • 23
  • 63
innomotion media
  • 862
  • 11
  • 30
  • You're loading images synchronously, that's why phones with smaller screens are able to show your content, but on bigger screens your code is called far before it can complete reading previous images. You can use BlockingCollection to load images asynchronously, and then display them. Producer/Consumer pattern. – bamanow Jan 09 '18 at 12:53
  • okay sounds reasonable. but I dont really know how to use that in my problem – innomotion media Jan 09 '18 at 12:56
  • 1
    VirtualizingCollection of some sort. And research Producer/Consumer pattern. That seems like an exact answer to your problem. – bamanow Jan 09 '18 at 12:58
  • thank you! i did however found another easy way for now :) – innomotion media Jan 09 '18 at 13:05
  • Does this answer your question? [Android RecyclerView : notifyDataSetChanged() IllegalStateException](https://stackoverflow.com/questions/27070220/android-recyclerview-notifydatasetchanged-illegalstateexception) – Sam Oct 15 '21 at 11:52

1 Answers1

2

Okay I seem to have found an easy fix for this:

if (!mRecyclerView.isComputingLayout())
    mAdapter.NotifyItemRangeChanged(oldCount - 1, loadPhotos.pictures.Count);

I just need to make sure, I have always enough photos so that the recycler view would scroll.

Yida Lin
  • 167
  • 2
  • 10
innomotion media
  • 862
  • 11
  • 30