android - 为什么SwipeRefreshLayout的setRefreshing()方法,只有在Handle中才能起作用?

查看:296
本文介绍了android - 为什么SwipeRefreshLayout的setRefreshing()方法,只有在Handle中才能起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

比如我想用SwipeRefreshLayout在界面第一次加载进来时先自动刷新一次。

private SwipeRefreshLayout mRefreshLayout;
mRefreshLayout.setRefreshing(true);

这样不起作用,显示不出加载条。
但是交给handler就可以?

private SwipeRefreshLayout mRefreshLayout;
mHandler.post(new Runnable() {
    @Override
    public void run() {
        mRefreshLayout.setRefreshing(true);
    }
});

解决方案

先转载知乎一个答案,这里解释了为什么在onCreate中调用setRefreshing无效:
作者:小波
链接:https://www.zhihu.com/question/35422150/answer/62784161
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


public void setRefreshing(boolean refreshing) {
if (refreshing && mRefreshing != refreshing) {
// scale and show
mRefreshing = refreshing;
int endTarget = 0;
if (!mUsingCustomStart) {
endTarget = (int) (mSpinnerFinalOffset + mOriginalOffsetTop);
} else {
endTarget = (int) mSpinnerFinalOffset;
}
setTargetOffsetTopAndBottom(endTarget - mCurrentTargetOffsetTop,
true /* requires update */);
mNotify = false;
startScaleUpAnimation(mRefreshListener);
} else {
setRefreshing(refreshing, false /* notify */);
}
} 
在onCreate里或onCreateView里调用setRefreshing,这个时候关键变量mOriginalOffsetTop并没有获取正确的值。下拉效果动画过程中没有显示到正确的坐标,我们看看这个值是什么时候获取的,上代码
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mTarget == null) {
ensureTarget();
}
if (mTarget == null) {
return;
}
mTarget.measure(MeasureSpec.makeMeasureSpec(
getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY));
mCircleView.measure(MeasureSpec.makeMeasureSpec(mCircleWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mCircleHeight, MeasureSpec.EXACTLY));
if (!mUsingCustomStart && !mOriginalOffsetCalculated) {
mOriginalOffsetCalculated = true;
mCurrentTargetOffsetTop = mOriginalOffsetTop = -mCircleView.getMeasuredHeight();
}

mCircleViewIndex = -1;
// Get the index of the circleview.
for (int index = 0; index < getChildCount(); index++) {
if (getChildAt(index) == mCircleView) {
mCircleViewIndex = index;
break;
}
}
} 
如代码所见,是在onMeasure里获取的,根据CircleView的高度来赋值的。

所以要解决的方法是让mOriginalOffsetTop能在setRefreshing前正确赋值。比较笨的方法是在onCreate里或onCreateView手动赋值,不推荐。
正确做法是在onMeasure触发后再调用setRefreshing。
代码如下:
root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
mRefreshLayout.setRefreshing(true);
loadData(true);
}
}); 

既然是因为在我们调用setRefresh时view的初始化还未执行完毕,那么最简单的办法就是用post加入队列,随便写了个demo,上代码:

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener{
    SwipeRefreshLayout refreshLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        refreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_layout);
        refreshLayout.setOnRefreshListener(this);
        refreshLayout.post(new Runnable() {
            @Override
            public void run() {
                refreshLayout.setRefreshing(true);
                onRefresh();
            }
        });
    }
    @Override
    public void onRefresh(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(3000);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        refreshLayout.setRefreshing(false);
                    }
                });
            }
        }).start();
    }
}

需要注意的是,setRefreshing只是展示动画,想要自动刷新必须手动调用onRefresh;手动调用onRefresh必须在post的runnable中,位于setRefreshing之后,否则若onRefresh中任务执行过快,就会出现无法取消refresh动画的情况。

这篇关于android - 为什么SwipeRefreshLayout的setRefreshing()方法,只有在Handle中才能起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆