LoginSignup
3
1

More than 5 years have passed since last update.

Android RecyclerView GridLayoutManager で Footer に Progress を表示しようとしたら ArrayIndexOutOfBoundsException が発生したのでその対応

Posted at

本記事について

Android でグリッド表示の画面で順次ローディングの実装を行った際にArrayIndexOutOfBoundsExceptionが発生したので、その対応について記載します。

実装方法についてはこちらの記事で投稿されている通りです。

TL;DR

  • GridLayoutManager.SpanSizeLookupfun getSpanSize(position: Int): Intメソッドをちゃんと実装しよう

基本的な実装方法

  • RecyclerViewのGridLayoutManagerのコンストラクタでspanCount(1行を幾つに分割するか)を設定します。
  • GridLayoutManager.SpanSizeLookupのgetSpanSizeで1要素のspanSizeを返します。
  • 通常の要素は getSpanSize で 1 を返し、FooterのProgressは getSpanSize で spanCount 返すことで、FooterのProgressのみ1行貫きにすることができます。
  • GridLayoutManager.SpanSizeLookupのインスタンスをGridLayoutManagerに設定します。

なぜ ArrayIndexOutOfBoundsException が発生したか

  • GridLayoutManager.SpanSizeLookupのgetSpanSizeの実装をミスっていました。
  • RecyclerViewの描画処理の中で該当メソッドは3回程呼ばれるのですが、その全てにおいて、適切にspanSizeを返す必要があります。
  • 私が行った実装では3回の内いくつかのタイミングで、適切なspanSizeを返すことができてませんでした。
  • 全てのタイミングで、適切な値を返すことで例外が発生しなくなりました。
  • stacktraceはこうでした。
E/AndroidRuntime: FATAL EXCEPTION: main Process: jp.sample.sampleapp.debug, PID: 11007
java.lang.ArrayIndexOutOfBoundsException: length=4; index=4
    at android.support.v7.widget.GridLayoutManager.getSpaceForSpanRange(GridLayoutManager.java:347)
    at android.support.v7.widget.GridLayoutManager.measureChild(GridLayoutManager.java:723)
    at android.support.v7.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:598)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1408)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:580)
    at android.support.v7.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
    at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3379)
    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3188)
    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3632)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:630)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1799)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:437)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
    at com.android.internal.policy.DecorView.onLayout(DecorView.java:726)
    at android.view.View.layout(View.java:17637)
    at android.view.ViewGroup.layout(ViewGroup.java:5575)
    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2346)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2068)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6337)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
    at android.view.Choreographer.doCallbacks(Choreographer.java:686)
    at android.view.Choreographer.doFrame(Choreographer.java:621)
07-04 17:17:02.391 11007-11007/jp.sample.sampleapp.debug E/AndroidRuntime:     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1