프로그래밍/Android

[안드로이드] java.lang.IllegalStateException: An instance of OnFlingListener already set 해결

Lou Park 2023. 1. 26. 23:24

문제 발생

@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT)
internal class PagerSnapHelperCarousel @JvmOverloads constructor(
    context: Context
) : Carousel(context) {
    init {
        if (onFlingListener == null) {
            PagerSnapHelper().attachToRecyclerView(this)
        }
    }
}

Epoxy의 Custom Carousel로 SnapHelper를 붙이는 도중 OnFlingListener가 이미 등록되어있다는 오류가 발생했다. 당연하게도 이유는 RecyclerVIewOnFlingListener가 이미 등록되어 있어서다.

java.lang.IllegalStateException: An instance of OnFlingListener already set.
    at androidx.recyclerview.widget.SnapHelper.setupCallbacks(SnapHelper.java:113)
    at androidx.recyclerview.widget.SnapHelper.attachToRecyclerView(SnapHelper.java:101)
    at com.xxxx.PagerSnapHelperCarousel.<init>(PagerSnapHelperCarousel.kt:13)
    at com.xxxx.PagerSnapHelperCarouselModel_.buildView(PagerSnapHelperCarouselModel_.java:97)
    at com.xxxx.PagerSnapHelperCarouselModel_.buildView(PagerSnapHelperCarouselModel_.java:32)
    at com.airbnb.epoxy.BaseEpoxyAdapter.onCreateViewHolder(BaseEpoxyAdapter.java:100)
    at com.airbnb.epoxy.BaseEpoxyAdapter.onCreateViewHolder(BaseEpoxyAdapter.java:20)
    at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7719)
    at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6804)
    at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6688)
    at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6684)
    at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2349)
    at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1649)
    at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1609)
    at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:686)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4604)
    at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4307)
    at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:2065)
    at androidx.recyclerview.widget.RecyclerView$1.run(RecyclerView.java:438)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1108)
    at android.view.Choreographer.doCallbacks(Choreographer.java:866)
    at android.view.Choreographer.doFrame(Choreographer.java:792)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1092)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:226)
    at android.os.Looper.loop(Looper.java:313)
    at android.app.ActivityThread.main(ActivityThread.java:8751)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

 

해결 방법

현재 RecyclerViewonFlingListenernull인지 체크 후, null일때만 SnapHelper를 등록해주면된다. 혹은 직접 없애버려도 될 것이다.

if (onFlingListener == null) {
    PagerSnapHelper().attachToRecyclerView(this) // this = recyclerview
}

 

이유는?

attachToRecyclerView()에서 OnFlightListener를 등록하고 있고, 정확히 해당 에러를 뱉는 부분에서 동일한 검사를 시행하고 있기때문이다.

public void attachToRecyclerView(@Nullable RecyclerView recyclerView)
        throws IllegalStateException {
    // ...
    if (mRecyclerView != null) {
        setupCallbacks();
        // ...
    }
}

/**
 * Called when an instance of a {@link RecyclerView} is attached.
 */
private void setupCallbacks() throws IllegalStateException {
    if (mRecyclerView.getOnFlingListener() != null) {
        throw new IllegalStateException("An instance of OnFlingListener already set.");
    }
    // ...
    mRecyclerView.setOnFlingListener(this);
}