Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

实现聊天APP列表,onUpFetch ,重复执行的问题? #1458

Closed
DevXue opened this issue Aug 17, 2017 · 32 comments
Closed

实现聊天APP列表,onUpFetch ,重复执行的问题? #1458

DevXue opened this issue Aug 17, 2017 · 32 comments

Comments

@DevXue
Copy link

DevXue commented Aug 17, 2017

我按照demo里的写法,照着谢了, 但是 首次运行 他就不停的执行onUpFetch 直到请求到最后一页 他才停止执行, 为啥啊? 我在回调方法里头 调用了adapter.setUpFetching(false); 而且 在onUpFetch 也调用了setUpFetchEnable(true), 但他就是不按照demo那种效果来执行 不知道为啥!!!

@guominfang
Copy link
Contributor

贴代码?我这边按文档上接入,没问题的,

  1. 打开加载 --> setUpFetchEnable(true)
  2. 设置监听 --> setUpFetchListener(listener)
  3. 加载前设置,正在刷新 --> setUpFetching(true)
  4. 加载完毕, --> setUpFetching(false)
  5. 加载结束 --> setUpFetchEnable(false)

五步

@CymChad
Copy link
Owner

CymChad commented Aug 18, 2017

@897902334 你是否在外部嵌套的sv?

@guominfang
Copy link
Contributor

@CymChad 我去,我也发现了,开启顶部加载更多只要快速滑动到顶部,就会一直执行请求,直到请求完毕,

@DevXue
Copy link
Author

DevXue commented Aug 18, 2017

sa

我是这么写的, 我没有写demo里的 mRecyclerView.postDelayed(new Runnable() {···},难道必须这么写么? 我的布局 外部没有使用 SwipeRefreshLayout 是不是 没有加这个的缘故了!!!!?

@tysheng
Copy link
Contributor

tysheng commented Aug 18, 2017

@897902334 你这个逻辑跟 demo 是有出入的,加延迟是因为数据和视图不一定同步,所以最好要加?

@guominfang 怎么会一直请求呢,你把数据加到末尾还是头部了,加到头部它不会自动滚动到头部,也就不会继续请求了

@BugMen
Copy link

BugMen commented Aug 18, 2017

我怎么掉不出setUpFetchListener这个方法呢?

@guominfang
Copy link
Contributor

@tysheng 会一直加载的情况是这样的:

  1. 调用mAdapter.setStartUpFetchPosition(2); 设置成离顶部还差两个item,就触发onUpFetch()方法来执行加载更多,
    注意: 这时候,如果加载数据还未执行完毕,就已经滑动到最顶部(也就是item=0可见时),如果这时候数据加载完毕,调用mAdapter.addData(0, newsData);添加新数据,会导致界面刷新,然后就一直执行onUpFetch()方法,直到加载完毕

@tysheng
Copy link
Contributor

tysheng commented Aug 19, 2017

@guominfang 添加新数据之后,视图会自动滚动到顶部吗?

@guominfang
Copy link
Contributor

guominfang commented Aug 19, 2017

@tysheng 不会自动滚动到顶部。你不理解我说的,
简单点来说就:首次触发onUpFetch(),当正在获取数据中(比如正在访问网络获取数据),这个时候手动滑动到已经到最顶部
注意条件,正在获取数据中(比如正在访问网络获取数据),已经滑动到最顶部
注意条件,正在获取数据中(比如正在访问网络获取数据),已经滑动到最顶部
注意条件,正在获取数据中(比如正在访问网络获取数据),已经滑动到最顶部
此时,RecyclerView已经在最顶部,
当RecyclerView在最顶时,数据加载完毕后,mAdapter.addData(0, newsData)会刷新整个界面,
因为RecyclerView已经在最顶部了,所以刷新界面时就会一直触发onUpFetch(),

@tysheng
Copy link
Contributor

tysheng commented Aug 23, 2017

@guominfang
setUpFetching 不管用吗?

@guominfang
Copy link
Contributor

@tysheng 心好累,感觉你不能理解,不清楚你是不是没用到这个功能。
setUpFetching()肯定管用啊,
但是,相对来,一次完整的数据加载的流程:
开始加载 : setUpFetching(true);
结束加载 : setUpFetching(false);
这个是完整的流程;

@FrankKwok
Copy link
Contributor

@guominfang@tysheng 是这个功能的开发者。。。

@guominfang
Copy link
Contributor

@FrankKwok @tysheng 额...这样,需要我做个demo,上传吗?

@DevXue
Copy link
Author

DevXue commented Aug 24, 2017

希望作者 解决一下吧, 一个星期了转眼就过去了··· 好惆怅! 谢谢。 @tysheng

@guominfang
Copy link
Contributor

guominfang commented Aug 24, 2017

@tysheng
测试代码:

  1. 刚进入界面加载第一次数据,并且设置加载监听,添加进度头部, 并且默认滑动到底部
  2. 因为加载数据有延时,所以,直接下拉,直到HeaderView可见,停住,等待数据刷新,这样就会一直触发加载更多,直到加载结束;
public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;

    private List<String> mData = new ArrayList<>();
    private SimpleAdapter mAdapter;
    private ProgressBar mProgressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAdapter = new SimpleAdapter(mData);
        mRecyclerView.setAdapter(mAdapter);
        mProgressBar = new ProgressBar(this);
        initData();
        setUpFetch();
    }

    private void initData() {
        for (int i = 0; i < 20; i++) {
            mData.add("初始化数据" + i);
        }
        mAdapter.notifyDataSetChanged();
        mRecyclerView.scrollToPosition(19);//第一次滑动到底部
    }

    private void setUpFetch() {
        mAdapter.setUpFetchEnable(true); //打开设置可加载
        mAdapter.setStartUpFetchPosition(2);
        mAdapter.addHeaderView(mProgressBar); //添加头部
        mAdapter.setUpFetchListener(new BaseQuickAdapter.UpFetchListener() {
            @Override
            public void onUpFetch() {
                Log.e("onUpFetch", "onUpFetch: ");
                mAdapter.setUpFetching(true);
                loadMore();
            }
        });
    }

    private void loadMore() {
        mRecyclerView.postDelayed(new Runnable() {
            @Override
            public void run() {
                loadMoreData();
                mAdapter.setUpFetching(false);
            }
        }, 5000);
    }

    private int page = 1;

    private void loadMoreData() {
        Log.e("loadMoreData", "loadMoreData: ");
        List<String> moreData = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            moreData.add("加载第" + page + "页数据");
        }
        mAdapter.addData(0, moreData);
        page++;
        if (page == 4) {
            mAdapter.setUpFetchEnable(false);
            mAdapter.removeAllHeaderView();
        }
    }

    class SimpleAdapter extends BaseQuickAdapter<String, BaseViewHolder> {

        public SimpleAdapter(@Nullable List<String> data) {
            super(R.layout.item_simple, data);
        }

        @Override
        protected void convert(BaseViewHolder helper, String item) {
            helper.setText(R.id.text_tv, item);
        }
    }

}

item_simple布局就是简单的一个TextView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="40dp"
              android:orientation="vertical">

    <TextView
        android:id="@+id/text_tv"
        android:layout_width="match_parent"
        android:layout_height="40dp"/>
</LinearLayout>

@tysheng
Copy link
Contributor

tysheng commented Aug 24, 2017

@guominfang 我写这个出发点是轻量级,不是跟 load more 这样的,不需要提供头部的加载动画,或者用 原生的 swipe refresh 来代替,像知乎那样

 private void autoUpFetch(int positions) {
        if (!isUpFetchEnable() || isUpFetching()) {
            return;
        }
        if (positions <= mStartUpFetchPosition/*这边添加 header count 试试*/+getHeaderLayoutCount() && mUpFetchListener != null) {
            mUpFetchListener.onUpFetch();
        }
    }

@guominfang
Copy link
Contributor

@tysheng
嗯,我试过,如果不添加HeaderView来显示加载中效果的话,是正常加载的,不会一直执行加载,

private void autoUpFetch(int positions) {
        if (!isUpFetchEnable() || isUpFetching()) {
            return;
        }
        if (positions <= mStartUpFetchPosition/*这边添加 header count 试试*/+getHeaderLayoutCount() && mUpFetchListener != null) {
            mUpFetchListener.onUpFetch();
        }
    }

这一步的处理,只能处理正常的向上滑动,触发的onUpFetch()的时机。处理不了目前的这个问题。

我觉得问题点是在:
因为添加了HeaderView --> positions被占用了 0;
列表数据的 positions -->是从 1开始算了。

当HeaderView显示的时候,调用mAdapter.addData(0, moreData);添加新数据,就相当于是把新数据插入
positions == 1的位置,这样导致了RecyclerView.Adapter()中的onBindViewHolder重新执行,这时候,onBindViewHolder传入的positions ==1,小于了我们mStartUpFetchPosition,所以导致onUpFetch()一直被回调

@tysheng
Copy link
Contributor

tysheng commented Aug 25, 2017 via email

@DevXue
Copy link
Author

DevXue commented Aug 25, 2017

@tysheng 大神, 那到底该怎么写呢 ??? 能不能把demo中的这个功能重新更新一下下呢??? 我还是不懂、

@tysheng
Copy link
Contributor

tysheng commented Aug 25, 2017

@897902334 可以先把 headerview 去掉看看

@DevXue
Copy link
Author

DevXue commented Aug 25, 2017

@tysheng 老铁, 我就没有添加过headerview。 还要去掉么 ?

@tysheng
Copy link
Contributor

tysheng commented Aug 25, 2017

你的代码逻辑看不太懂,一些设置监听的方法怎么在回调函数里。addData(0,data) 那块用 post 延迟一下试试

@guominfang
Copy link
Contributor

@tysheng 其实问题的重点已经不是在 触发onUpFetch()方法上了。

private void autoUpFetch(int positions) {
        if (!isUpFetchEnable() || isUpFetching()) {
            return;
        }
        if (positions <= mStartUpFetchPosition && mUpFetchListener != null) {
            mUpFetchListener.onUpFetch();
        }
    }

而是onBindViewHolder()的执行时机了。

@tysheng
Copy link
Contributor

tysheng commented Aug 25, 2017 via email

@tysheng
Copy link
Contributor

tysheng commented Aug 25, 2017

监听 reyclerview 的滑动也可以做到,只是不『自动』

@guominfang
Copy link
Contributor

@tysheng 嗯,估计目前的实现方式,不能使用headerview,
我这边去掉headerview,是正常的
@897902334

@tysheng
Copy link
Contributor

tysheng commented Aug 25, 2017 via email

@guominfang
Copy link
Contributor

guominfang commented Aug 27, 2017

@tysheng 我试过mAdapter.setStartUpFetchPosition(0);
不过只能加载一次不能再自动加载了,需要先滑动 position = 2以后,再上滑到position == 0,才能执行onUpFetch()。

@CymChad
Copy link
Owner

CymChad commented Aug 29, 2017

@897902334 @guominfang @tysheng 问题解决了没?

@guominfang
Copy link
Contributor

我这边,没事实际的解决办法。不添加HeaderView,就能正常
@897902334 他的问题,就不清楚了。

@CymChad
Copy link
Owner

CymChad commented Aug 31, 2017

恩,看你们反复沟通了很多,应该都聊透了。有问题可以再提。

@CymChad CymChad closed this as completed Aug 31, 2017
@Developmc
Copy link

Developmc commented Jan 9, 2019

mAdapter.addData(0, moreData);

@guominfang 不要直接调这一句,把mAdapter.addData(0, moreData)内的notifyItemRangeInserted(position + getHeaderLayoutCount(), newData.size());
修改为
notifyItemRangeInserted(position, newData.size());(即不要加getHeaderLayoutCount)就可以了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants