2

앱 막대 축소의 완료를 감지하기 위해 addOnOffsetChangedListener이라고했습니다. 청취자의 onOffsetChanged에서 나는 붕괴의 순간을 잡아서 처리했습니다. 그런 다음 오프셋 변경 내용을 듣지 않아야합니다.AppBarLayout : OffOffsetChangedListener를 제거하는 방법

여기서 대부분의 예는 onOffsetChanged 내부에서 removeOnOffsetChangedListener(this)이라고합니다. 그러나 AppBarLayout.java을보고 나는 참조 :

private void dispatchOffsetUpdates(int offset) { // Iterate backwards through the list so that most recently added listeners // get the first chance to decide if (mListeners != null) { for (int i = 0, z = mListeners.size(); i < z; i++) { final OnOffsetChangedListener listener = mListeners.get(i); if (listener != null) { listener.onOffsetChanged(this, offset); } } } }

그래서 removeOnOffsetChangedListener(this)를 호출 둘 이상 설치 리스너가 존재하는 경우, 자연적으로 IndexOutOfBoundsException 발생합니다.

내가 놓친 것이 있습니까? 안전 오프셋 업데이트 수신을 '탈퇴'할 방법이 있습니까?

답변

1

실제로 흥미로운 사실은 코드가 실제로 댓글에 나온 내용을 수행하면 문제가되지 않는다는 것입니다. 어쨌든 RunnableremoveOnOffsetChangedListener()으로 전화를 걸고 AppBarLayoutonOffsetChanged()으로 게시하여 삭제하는 것을 연기 할 수 있습니다. 예를 들어

는 :

AppBarLayout.OnOffsetChangedListener listener = new AppBarLayout.OnOffsetChangedListener() { 
    @Override 
    public void onOffsetChanged(final AppBarLayout abl, int offset) { 
     abl.post(new Runnable() { 
       @Override 
       public void run() { 
        abl.removeOnOffsetChangedListener(listener); 
       } 
      } 
     ); 
    } 
}; 
+0

그것은 솔루션입니다, 감사합니다! 하지만 "실제로 코드에서 주석이 말하는대로 코드를 작성하면 문제가되지 않습니다" 예를 들어 사이클에 들어가기 전에 목록에 두 개의 항목이 있으면 첫 번째 항목을 제거한 후 두 번째 패스에서'mListeners.get (1) '을 호출하는 동안 해당 코드가 100B를 발생시킵니다. 이터레이터를 사용하면 더 잘할 수 있습니다. – Alexey

+0

역순으로 가면 (즉, i = mListeners.size() - 1'에서 시작하고'i'를 감소 시켰을 때) 요소를 지우면'List'가 줄어들지 만 그렇지 않은 인덱스에는 충돌하지 않습니다 '0'이 될 것이므로 존재하지 않습니다. 그들은 그것을 바꾸려고 의도 한 것 같지만, 어리둥절한 것 같습니다. 나쁜 병합 또는 뭔가. 댓글이 불완전하게 들립니다. –

관련 문제