在listView中点击例如“美女图片”后打开一个largeActivity;
largeActivity中有一个viewPager实现左右滑动浏览大图;
在largeActivity打开的时候会通过okHttp从服务器请求一组5张图片链接,图片通过glide加载在viewPager中实现左右滑动浏览;
因为每次网络请求只能返回5张图片链接,所以我在监听每次滑动viewPager的时候判断当前 postion小于存储图片链接的imageList.size() -1的时候,也就是每次滑动到倒数第二张的时候去网络请求下一组图片的链接;
然后通过add将新请求到的图片链接添加进imageList,然后再执行一次
pagerAdapter.notifyDataSetChanged()来实现viewPager继续滑动浏览新请求到的图片。
现在问题是如果用户以正常速度滑动viewPager来浏览每张图片的时候是没有任何问题的,但是如果用户飞速滑动viewPager的进行浏览的时候就会出现在某一次请求新数据后就会出现APP崩溃的情况;错误信息在两部不同的手机上报错不一样,但是都是在相同的情况下崩溃。Google遍都没有找到解决办法
华为荣耀报错如下:
通过华为手机的报错在网上找到通过设置 android:hardwareAccelerated="false"
来关闭硬件加速的办法,但是通过测试在快速滑动时还是会导致APP崩溃自动重启的情况
乐视max2报错如下:
03-21 05:42:44.071 18730-18730/com.abcd.reader.abcdreader E/InputEventReceiver: Exception dispatching input event.
03-21 05:42:44.071 18730-18730/com.abcd.reader.abcdreader E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
03-21 05:42:44.084 18730-18730/com.abcd.reader.abcdreader E/MessageQueue-JNI: java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 25, found: 30 Pager id: com.abcd.reader.abcdreader:id/vp_pager Pager class: class android.support.v4.view.ViewPager Problematic adapter: class com.abcd.reader.abcdreader.adapter.FollowDetailViewPagerAdapter
通过乐视手机的报错怀疑是当新请求的数据add进imageList后,但是还没来得及执行notifyDataSetChanged,刚好在这时用户在滑动viewPager的时候导致的;为了验证猜测我修改了在当前 postion小于存储图片链接的imageList.size() -2的时候,也就是每次滑动到倒数第三张的时候去网络请求下一组图片的链接;给imageList.add和notifyDataSetChanged预留了充分的执行时间,这时候再次测试问题消失,华为手机和乐视手机均没有再出现APP崩溃重启的情况
但是我这个服务器请求回来的数据是不固定的,有时候可能每次返回5条,有时候10条,有时候只有1条,所以我现在的解决办法并不能彻底解决
烦请老师们给予指点一二,万分感谢!
PHPz2017-04-18 09:18:18
스레드 안전 문제일 것이라고 감히 추정합니다. 새 데이터를 얻을 때 post
메서드, 즉 viewPager.post()
를 사용하여 다음과 같이 수정해 볼 수 있습니다. > notifyDataSetChanged
작업으로 이동하세요. 아직 직접 확인은 안해봤는데 안되면 알려주시면 확인해보겠습니다. post
PHPz2017-04-18 09:18:18
당분간은 구체적인 오류 원인을 찾는 데 도움을 드릴 수 없습니다. RecycleView를 사용하여 동일한 효과를 얻으실 수 있는 또 다른 구현 방법을 알려드리겠습니다.
黄舟2017-04-18 09:18:18
제가 잘못 이해한 것인지 모르겠지만 Images.size()-1은 마지막에서 두 번째가 아닌 마지막 이미지입니다
어댑터의 getItem에 서버에서 항목을 가져오는 논리를 작성하는 것이 좋습니다. 으아악
阿神2017-04-18 09:18:18
전략이 잘못되었습니다. 왜 매번 이미지 URL이 5개만 반환되나요? 트래픽을 절약하기 위해서인가요? 가장 큰 낭비는 처음에 모든 URL을 얻은 다음 이미지 캐싱을 직접 제어해야 하는 3방향 핸드셰이크 생성 프로세스입니다.
매번 두 번째 사진으로 가서 다시 요청하시면 트러블 걱정 안하셔도 됩니다...
伊谢尔伦2017-04-18 09:18:18
질문을 보면 주체는 viewpager 슬라이딩 청취 방식으로 네트워크 요청을 하고 있습니다.
사용자가 viewpager를 좌우로 빠르게 슬라이드하면 콜백이 여러 번 실행될 가능성이 높습니다.
이전 네트워크 요청이 아직 진행 중이며 다음 요청이 중단됩니다.
이러한 경우 플래그를 추가할 수 있습니다. 현재 요청이 진행 중인 경우 올바른 콜백이나 오류 콜백이 수신될 때까지 새 네트워크 요청이 생성되지 않습니다.
반품 수량 고정 문제의 경우, 사진 5장을 요청했는데 서버가 3장만 반환한다면 서버가 사진을 모두 줬다는 의미이므로 네트워크 요청을 실행하면 안 됩니다.