tinkoff-mobile-tech / ScrollingPagerIndicator

Pager indicator inspired by Instagram. Lightweight and easy to set up.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

crash in recyclerView

alvinrxg opened this issue · comments

Hello,
in our recyclerView is an item with ScrollingPagerIndicator.
It crashes when we are trying to reload some data.

    java.lang.IllegalStateException: Observer ru.tinkoff.scrollingpagerindicator.ViewPagerAttacher$1@6f7b8cb was not registered.
        at android.database.Observable.unregisterObserver(Observable.java:69)
        at android.support.v4.view.PagerAdapter.unregisterDataSetObserver(PagerAdapter.java:311)
        at ru.tinkoff.scrollingpagerindicator.ViewPagerAttacher.detachFromPager(ViewPagerAttacher.java:80)
        at ru.tinkoff.scrollingpagerindicator.ScrollingPagerIndicator.detachFromPager(ScrollingPagerIndicator.java:268)
        at ru.tinkoff.scrollingpagerindicator.ScrollingPagerIndicator.attachToPager(ScrollingPagerIndicator.java:250)
        at ru.tinkoff.scrollingpagerindicator.ScrollingPagerIndicator.attachToPager(ScrollingPagerIndicator.java:201)

could you please add a check while detachFromPager() ?

Hi! Thank you for report. Could you provide some code example to reproduce this issue, please?

@N-Olifer here's a sample:

// dependencies

implementation 'com.hannesdorfmann:adapterdelegates3:3.0.1'
implementation 'ru.tinkoff.scrollingpagerindicator:scrollingpagerindicator:1.0.4'
// File: RecyclerViewAdapter.java

public class RecyclerViewAdapter extends RecyclerView.Adapter {

    private List<RecyclerViewData> dataList;
    private AdapterDelegatesManager<List<RecyclerViewData>> adapterDelegatesManager;

    public RecyclerViewAdapter(List<RecyclerViewData> dataList) {
        this.dataList = dataList;

        adapterDelegatesManager = new AdapterDelegatesManager<>();
        adapterDelegatesManager.addDelegate(new ItemDelegate());
        adapterDelegatesManager.addDelegate(new ViewPagerDelegate());
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return adapterDelegatesManager.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        adapterDelegatesManager.onBindViewHolder(dataList, position, holder);
    }

    @Override
    public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) {
        adapterDelegatesManager.onViewDetachedFromWindow(holder);
    }

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

    @Override
    public int getItemViewType(int position) {
        return adapterDelegatesManager.getItemViewType(dataList, position);
    }

}
// File: ViewPagerDelegate.java
public class ViewPagerDelegate extends AdapterDelegate<List<RecyclerViewData>> {

    @Override
    protected boolean isForViewType(@NonNull List<RecyclerViewData> items, int position) {
        return items.get(position) instanceof RecyclerViewData.ViewPagerData;
    }

    @NonNull
    @Override
    protected RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_pager_view, parent, false);
        return new RecyclerView.ViewHolder(v) {
        };
    }

    @Override
    protected void onBindViewHolder(@NonNull List<RecyclerViewData> items, int position, @NonNull RecyclerView.ViewHolder holder, @NonNull List<Object> payloads) {
        ScrollingPagerIndicator indicator = holder.itemView.findViewById(R.id.pager_indicator);
        ViewPager viewPager = holder.itemView.findViewById(R.id.view_pager);
        viewPager.setAdapter(new PagerAdapter() {
            @Override
            public int getCount() {
                return 0;
            }

            @Override
            public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
                return false;
            }
        });

        indicator.attachToPager(viewPager);
    }

    @Override
    protected void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {
        super.onViewDetachedFromWindow(holder);
// here is my solution
//        ((ScrollingPagerIndicator) holder.itemView.findViewById(R.id.pager_indicator)).detachFromPager();
    }
}
// File: MainActivity.java

public class MainActivity extends AppCompatActivity {

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

        RecyclerView recyclerView = findViewById(R.id.recycler_view);

        List<RecyclerViewData> dataList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            dataList.add(new RecyclerViewData.ItemData());
        }
        dataList.add(10, new RecyclerViewData.ViewPagerData());

        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(new RecyclerViewAdapter(dataList));
    }

}

The solution is to detachFromPager() when the ScrollingPagerIndicator is detached from window.

I have fixed this issue, try version 1.0.5 please. You don't have to call detachFromPager, it will detach from previous pager automatically in attachToPager.

@N-Olifer
Hi, thanks for the update. And i just tested the new version. Now it works good. There's no more exceptions