PullToRefreshScrollView踩坑经历以及源码分析
2016-09-05 15:38
525 查看
目前下拉刷新已经满大街都是,在自己的应用如果不使用这个模式的话,出门都不好意思和人家打招呼
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/tongue.gif)
,该文章结合自己使用PullToRefreshScrollView过程中所遇到的问题,简单探讨下针对于github
上的这个开源项目的使用心得,具体的使用方法不做探究。
首先描述下自己使用PullToRefreshScrollView所遇到的BUG现象吧:在ScrollView下拉刷新时去服务端获取数据并进行展示,获取数据的过程采用线程池管理线程(具体优点儿不做解释),进行到该步发现一个奇妙的问题,发现一下拉刷新APP就闪退了,查看Log错误显示ThreadPoolExecutor队列满了RejectedExecutionException,怀疑我的ThreadPoolExecutor容量不够大,虽扩大至20,再次测试依然闪退,并没有什么乱用,仍然是队列已满错误。之后层层源码追看,发现了端倪,onPullDownToRefresh该方法一直不断的在调用,所以导致ThreadPoolExecutor里面的任务一直变多,导致容量急剧增加,进而闪退。把自己的解决过程记录下来献给遇到同样问题的童鞋。
→代表调用的意思
当用户下拉刷新并松开手指时会调用PullToRefreshBase.java的onTouchEvent的case MotionEvent.ACTION_UP→PullToRefreshBase.java的final void setState(State state, final boolean... params)其PullToRefreshBase.java的中state=MANUAL_REFRESHING,params=[true]→PullToRefreshBase.java的protected
void onRefreshing(final boolean doScroll) 其中doScroll=true→PullToRefreshBase.java的protected final void smoothScrollTo(int scrollValue, OnSmoothScrollFinishedListener listener)→PullToRefreshBase.java的private final void smoothScrollTo(int newScrollValue, long
duration, long delayMillis,OnSmoothScrollFinishedListener listener)→PullToRefreshBase.java的public SmoothScrollRunnable(int fromY, int toY, long duration, OnSmoothScrollFinishedListener listener)实例化一个线程→PullToRefreshBase.java的post(mCurrentSmoothScrollRunnable);运行SmoothScrollRunnable线程从SmoothScrollRunnable内部源码
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/tongue.gif)
,该文章结合自己使用PullToRefreshScrollView过程中所遇到的问题,简单探讨下针对于github
上的这个开源项目的使用心得,具体的使用方法不做探究。
首先描述下自己使用PullToRefreshScrollView所遇到的BUG现象吧:在ScrollView下拉刷新时去服务端获取数据并进行展示,获取数据的过程采用线程池管理线程(具体优点儿不做解释),进行到该步发现一个奇妙的问题,发现一下拉刷新APP就闪退了,查看Log错误显示ThreadPoolExecutor队列满了RejectedExecutionException,怀疑我的ThreadPoolExecutor容量不够大,虽扩大至20,再次测试依然闪退,并没有什么乱用,仍然是队列已满错误。之后层层源码追看,发现了端倪,onPullDownToRefresh该方法一直不断的在调用,所以导致ThreadPoolExecutor里面的任务一直变多,导致容量急剧增加,进而闪退。把自己的解决过程记录下来献给遇到同样问题的童鞋。
→代表调用的意思
当用户下拉刷新并松开手指时会调用PullToRefreshBase.java的onTouchEvent的case MotionEvent.ACTION_UP→PullToRefreshBase.java的final void setState(State state, final boolean... params)其PullToRefreshBase.java的中state=MANUAL_REFRESHING,params=[true]→PullToRefreshBase.java的protected
void onRefreshing(final boolean doScroll) 其中doScroll=true→PullToRefreshBase.java的protected final void smoothScrollTo(int scrollValue, OnSmoothScrollFinishedListener listener)→PullToRefreshBase.java的private final void smoothScrollTo(int newScrollValue, long
duration, long delayMillis,OnSmoothScrollFinishedListener listener)→PullToRefreshBase.java的public SmoothScrollRunnable(int fromY, int toY, long duration, OnSmoothScrollFinishedListener listener)实例化一个线程→PullToRefreshBase.java的post(mCurrentSmoothScrollRunnable);运行SmoothScrollRunnable线程从SmoothScrollRunnable内部源码
final class SmoothScrollRunnable implements Runnable { private final Interpolator mInterpolator; private final int mScrollToY; private final int mScrollFromY; private final long mDuration; private OnSmoothScrollFinishedListener mListener; private boolean mContinueRunning = true; private long mStartTime = -1; private int mCurrentY = -1; public SmoothScrollRunnable(int fromY, int toY, long duration, OnSmoothScrollFinishedListener listener) { Log.i("TTT", " SmoothScrollRunnable 实例化"); mScrollFromY = fromY; mScrollToY = toY; mInterpolator = mScrollAnimationInterpolator; mDuration = duration; mListener = listener; } @Override public void run() { /** * Only set mStartTime if this is the first time we're starting, * else actually calculate the Y delta */ if (mStartTime == -1) { mStartTime = System.currentTimeMillis(); Log.i("TTT", " mStartTime=" + mStartTime); } else { /** * We do do all calculations in long to reduce software float * calculations. We use 1000 as it gives us good accuracy and * small rounding errors */ long normalizedTime = (1000 * (System.currentTimeMillis() - mStartTime)) / mDuration; normalizedTime = Math.max(Math.min(normalizedTime, 10 4000 00), 0); final int deltaY = Math.round((mScrollFromY - mScrollToY) * mInterpolator.getInterpolation(normalizedTime / 1000f)); mCurrentY = mScrollFromY - deltaY; setHeaderScroll(mCurrentY); Log.i("TTT", " normalizedTime=" + normalizedTime + ", mContinueRunning=" + mContinueRunning + ",mScrollToY=" + mScrollToY + ",mCurrentY=" + mCurrentY); } // If we're not at the target Y, keep going... if (mContinueRunning && mScrollToY != mCurrentY) { ViewCompat.postOnAnimation(PullToRefreshBase.this, this); } else { if (null != mListener) { Log.i("TTT", "mListener.onSmoothScrollFinished(),isSmoothScrollFinished=" + isSmoothScrollFinished); mListener.onSmoothScrollFinished(); } } } public void stop() { Log.i("TTT", " stop()"); mContinueRunning = false; removeCallbacks(this); } }首先将HeaderView采用postOnAnimation慢慢的隐藏掉,直到HeaderView隐藏掉之后mScrollToY == mCurrentY然后调用mListener.onSmoothScrollFinished(),该方法最终调用onPullDownToRefresh方法,如果onPullDownToRefresh里面开启一个线程去服务端获取数据,因为获取数据和SmoothScrollRunnable不在一个线程中,那么此时SmoothScrollRunnable获得时间片它的run方法会不断的运行,因此mListener.onSmoothScrollFinished()会不断的运行,所以会导致不停地向ThreadPoolExecutor提交任务,所以ThreadPoolExecutor容量会瞬间变满导致异常。因此考虑在SmoothScrollRunnable当中增加一个标志位,标志我当次已经在初始化中,具体代码如下,红色是新增的逻辑。
final class SmoothScrollRunnable implements Runnable { private final Interpolator mInterpolator; private final int mScrollToY; private final int mScrollFromY; private final long mDuration; private OnSmoothScrollFinishedListener mListener; private boolean mContinueRunning = true; private long mStartTime = -1; private int mCurrentY = -1; <span style="color:#FF0000;">private boolean isSmoothScrollFinished = false;</span> public SmoothScrollRunnable(int fromY, int toY, long duration, OnSmoothScrollFinishedListener listener) { Log.i("TTT", " SmoothScrollRunnable 实例化"); mScrollFromY = fromY; mScrollToY = toY; mInterpolator = mScrollAnimationInterpolator; mDuration = duration; mListener = listener; } @Override public void run() { /** * Only set mStartTime if this is the first time we're starting, * else actually calculate the Y delta */ if (mStartTime == -1) { mStartTime = System.currentTimeMillis(); Log.i("TTT", " mStartTime=" + mStartTime); } else { /** * We do do all calculations in long to reduce software float * calculations. We use 1000 as it gives us good accuracy and * small rounding errors */ long normalizedTime = (1000 * (System.currentTimeMillis() - mStartTime)) / mDuration; normalizedTime = Math.max(Math.min(normalizedTime, 1000), 0); final int deltaY = Math.round((mScrollFromY - mScrollToY) * mInterpolator.getInterpolation(normalizedTime / 1000f)); mCurrentY = mScrollFromY - deltaY; setHeaderScroll(mCurrentY); Log.i("TTT", " normalizedTime=" + normalizedTime + ", mContinueRunning=" + mContinueRunning + ",mScrollToY=" + mScrollToY + ",mCurrentY=" + mCurrentY); } // If we're not at the target Y, keep going... if (mContinueRunning && mScrollToY != mCurrentY) { ViewCompat.postOnAnimation(PullToRefreshBase.this, this); } else { if (null != mListener) { Log.i("TTT", "mListener.onSmoothScrollFinished(),isSmoothScrollFinished=" + isSmoothScrollFinished); <span style="color:#FF0000;">if (!isSmoothScrollFinished)</span> <span style="color:#FF0000;">{</span> mListener.onSmoothScrollFinished(); <span style="color:#FF0000;">}</span> <span style="color:#FF0000;">isSmoothScrollFinished = true;</span> } } } public void stop() { Log.i("TTT", " stop()"); mContinueRunning = false; <span style="color:#FF0000;">isSmoothScrollFinished = true;</span> removeCallbacks(this); } }如有不正还望留言改正
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/tongue.gif)
相关文章推荐
- PullToRefreshScrollView刷新轮播图和ListView以及上拉下拉、网络获取图片并提示
- Android PullToRefresh 分析之四、扩展RecyclerView
- PullToRefreshScrollView结合StickyHeaderGridView
- PullToRefreshScrollView+GridView,实现向下滑动中隐藏自定义Action布局
- Android ScrollView+ViewPager+PullToRefreshListView
- 使用pulltorefreshscrollview 嵌套 listview viewpager的配置方式
- 当PullToRefreshScrollView里面嵌套ListView
- 针对自定义组件上拉刷新下拉加载更多PullToRefreshView的分析(一)
- 开源项目PullToRefresh详解(三)——PullToRefreshScrollView
- android-scrollToTop回到顶部-兼容PullTorefreshScrollview
- PullToRefreshScrollView 嵌套 ViewPager 冲突导致界面不显示的问题
- PullToRefreshScrollView包含复杂组合控件时的页面定位问题
- PullToRefreshScrollView的scrollTo方法的使用
- PullToRefreshView的样式以及一些问题
- 下拉刷新之ScrollView--PullToRefreshScrollView
- 使用开源的PullToRefreshScrollView scrollTo和scrollby遇到的问题
- 使用开源的PullToRefreshScrollView scrollTo和scrollby遇到的问题
- PullToRefreshScrollView隐藏刷新布局(使刷新布局不显示)
- android-Ultra-Pull-To-Refresh源码分析
- 当PullToRefreshScrollView里面嵌套ListView