记录一次完美解决双瀑布流!!!!
2020-05-09 本文已影响0人
朱_c713
完美解决双瀑布流!!!!——前后的对比建议使用对比软件观看
项目 需求:
- 首页列表中有两个瀑布流
-
服务器无法将两个接口写在同一个接口中。
image.png
项目要求:
- 两个瀑布流自由上拉加载无问题。
- 列表要流畅
解决方案一:首页中采用两个RecyclerView,采用普通写法。
用nestScrollView解决滑动冲突:
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_child_Push"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/space_30"
android:paddingEnd="@dimen/space_30"
android:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_pu_bu"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
结果:瀑布流一起请求完,无上拉加载效果。滑动卡顿。因为view未能得到复用。
原因:这是因为NestedScrollView 本身实现的有ScrollView相关的接口(结合Baskquickadapter)自己内部会测量和计算。Scrollview,所有的子view都会一次性被加载出来。。
解决方案二:第一个Recyclerview作为header或者footer,添加到第二个RecyclerView
结果:作为header和Footer的View,无法一次请求,也么有上拉加载效果。
原因:同样是因为header是一次加载完的原因。
我们采用第一个Recylcerview,作为header添加到第二个RecyclerView中的办法。
但是第一个的下拉刷新还是无法实现。
解决方案三:第二个RecyclerView的Item 作为第一个RecyclerView的 多条目布局中的一种条目处理。
当第一个数据的接口拉到最后一页的时候,请求第二个数据,拼接到前面就像使用第一个数据一样。
具体操作和重构流程:
-
两个adapter统一为一个,第二个的请求httpPager2的成功方法的数据格式发生变化。
-
第二个RecyclerView的LayoutManger与第一个保持一致。
-
在第一个瀑布流加载结束的位置,做衔接处理
-
下拉刷新的位置,重新添加page,并改变状态。
1) 删除一下bottomAdapter相关的方法
bottomAdapter.setLoadMoreView(new LoadingAddDataView());
bottomAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
JumpUtils.jumpToPlayerAct(bottomData.get(position).getVod_id());
}
});
bottomAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
@Override
public void onLoadMoreRequested() {
httpPager2();
}
}, rv_pu_bu);
2)两个数据衔接位置的演变:
原来1
GetTypeVodsBean body = response.body();
mainAdapter.addData(getPushMultipleItems(body));
if (page >= body.getLast_page()) {
mainAdapter.loadMoreEnd(true);
} else {
page++;
mainAdapter.loadMoreComplete();
}
演变2:
GetTypeVodsBean body = response.body();
mainAdapter.addData(getPushMultipleItems(body));
if (page >= body.getLast_page()) {
currentRequest = "httpPager2";
httpPager2();
} else {
page++;
mainAdapter.loadMoreComplete();
}
演变3:
解决第二个瀑布流的第一页一闪而过,看不到的问题。
GetTypeVodsBean body = response.body();
mainAdapter.addData(getPushMultipleItems(body));
if (page == body.getLast_page()) {
mainAdapter.loadMoreComplete();
currentRequest = "httpPager2";
httpPager2();
} else {
page++;
mainAdapter.loadMoreComplete();
}
3) 添加请求变化的标志位,数据变化的时候改变这个。
public String currentRequest = "httpPager";
下拉的时候,根据标志位决定该请求那个;
mainAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
@Override
public void onLoadMoreRequested() {
if ("httpPager".equals(currentRequest)) {
httpPager();
} else {
httpPager2();
}
}
}, rv_child_Push);
新版核心代码——请使用对比软件,观察两个的不同:
核心代码:只记录有差异的代码,属于代码片段
public class ChildRecommendFragment {
@BindView(R.id.sl_Push)
SwipeRefreshLayout sl_Push;
@BindView(R.id.rv_child_Push)
RecyclerView rv_child_Push;
@BindView(R.id.loading)
View loading;
@BindView(R.id.load_err)
View load_err;
/**
* 上拉加载页数
*/
public int pagePullRefresh = 1;
public int page = 1;
public int page2 = 1;
private RecommendAdapter mainAdapter;
private ArrayList<PushMultipleItem> multipleList = new ArrayList<>();
public String currentRequest = "httpPager";
@Override
protected void initView() {
LinearLayoutManager manager = new LinearLayoutManager(mActivity);
rv_child_Push.setLayoutManager(manager);
mainAdapter = new RecommendAdapter(null);
rv_child_Push.setAdapter(mainAdapter);
//上拉加载
mainAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
@Override
public void onLoadMoreRequested() {
if ("httpPager".equals(currentRequest)) {
httpPager();
} else {
httpPager2();
}
}
}, rv_child_Push);
sl_Push.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
pagePullRefresh = getRandomPageRefresh();
page = 1;
page2=1;
currentRequest="httpPager";
httpData();
}
});
load_err.setOnClickListener(view -> {
loading.setVisibility(View.VISIBLE);
load_err.setVisibility(View.GONE);
page = 1;
page2=1;
currentRequest="httpPager";
httpData();
});
}
@Override
protected void initData() {
loading.setVisibility(View.VISIBLE);
httpData();
}
* 请求数据集合
*/
private void httpData() {
String url = ConstantUtils.getUrlConstant().video_type
+ "?type_id=" + getArguments().get("id")
+ "&version=" + AppUtils.getAppVersionCode()
+ "&page=" + pagePullRefresh
+ "&mobiletype=1";
OkGoUtils.getRequest(url, new JsonCallBack<GetTypeDetailBean>(GetTypeDetailBean.class, mActivity) {
@Override
public void onStart(Request<GetTypeDetailBean, ? extends Request> request) {
}
@Override
public void onSuccess(Response<GetTypeDetailBean> response) {
loading.setVisibility(View.GONE);
load_err.setVisibility(View.GONE);
clearList();
sl_Push.setRefreshing(false);
GetTypeDetailBean body = response.body();
multipleList = bornMultipleList(body);
mainAdapter.setNewData(multipleList);
}
@Override
public void onError(Response<GetTypeDetailBean> response) {
loading.setVisibility(View.GONE);
sl_Push.setRefreshing(false);
ToastUtils.showShort("连接服务器失败");
if (mainAdapter.getData().size() == 0) {
load_err.setVisibility(View.VISIBLE);
}
}
});
}
private ArrayList<PushMultipleItem> bornMultipleList(GetTypeDetailBean body) {
ArrayList<PushMultipleItem> multipleList = new ArrayList<>();
GetTypeDetailBean.RenhotBean renhot = body.getRenhot();
VideoBean recentTitleBean = new VideoBean(ConstantUtils.RECENT_ID, ConstantUtils.RECENT_VALUE);
VideoBean hotTitleBean = new VideoBean(ConstantUtils.HITS_ID, ConstantUtils.HITS_VALUE);
multipleList.add(new PushMultipleItem(PushMultipleItem.title, recentTitleBean));
multipleList.add(new PushMultipleItem(PushMultipleItem.item, ConstantUtils.RECENT_KEY, renhot.getRecent()));
multipleList.add(new PushMultipleItem(PushMultipleItem.changer, ConstantUtils.RECENT_KEY, null));
multipleList.add(new PushMultipleItem(PushMultipleItem.title, hotTitleBean));
multipleList.add(new PushMultipleItem(PushMultipleItem.item, ConstantUtils.HITS_KEY, renhot.getHits()));
multipleList.add(new PushMultipleItem(PushMultipleItem.changer, ConstantUtils.HITS_KEY, null));
return multipleList;
}
private void clearList() {
if (multipleList != null && multipleList.size() > 0) {
multipleList.clear();
}
}
/**
* 分页请求
*/
private void httpPager() {
OkGoUtils.getRequest(getUrl(), new JsonCallBack<GetTypeVodsBean>(GetTypeVodsBean.class, mActivity) {
@Override
public void onStart(Request<GetTypeVodsBean, ? extends Request> request) {
}
@Override
public void onSuccess(Response<GetTypeVodsBean> response) {
GetTypeVodsBean body = response.body();
mainAdapter.addData(getPushMultipleItems(body));
if (page == body.getLast_page()) {
mainAdapter.loadMoreComplete();
currentRequest = "httpPager2";
httpPager2();
} else {
page++;
mainAdapter.loadMoreComplete();
}
}
@Override
public void onError(Response<GetTypeVodsBean> response) {
mainAdapter.loadMoreFail();
}
});
}
@NotNull
private String getUrl() {
return ConstantUtils.getUrlConstant().getypevods
+ "?type_id=" + getArguments().get("id")
+ "&type_name=" + ListSharedPreferences.getTypeName((Integer) getArguments().get("id"))
+ "&page=" + page;
}
private void httpPager2() {
String url = ConstantUtils.getUrlConstant().getrecentvod
+ "?type_id=" + getArguments().get("id")
+ "&type_name=" + ListSharedPreferences.getTypeName((Integer) getArguments().get("id"))
+ "&page=" + page2;
OkGoUtils.getRequest(url, new JsonCallBack<VideoBeanBottom>(VideoBeanBottom.class, mActivity) {
@Override
public void onStart(Request<VideoBeanBottom, ? extends Request> request) {
}
@Override
public void onSuccess(Response<VideoBeanBottom> response) {
loading.setVisibility(View.GONE);
VideoBeanBottom body = response.body();
List<VideoBean> data = body.getData();
ArrayList<PushMultipleItem> multipleItems = new ArrayList<>();
if (page2==1){
VideoBean hotTitleBean = new VideoBean(ConstantUtils.FILM_LIBRARY, "我的片库");
multipleList.add(new PushMultipleItem(PushMultipleItem.title, hotTitleBean));
}
multipleItems.add(new PushMultipleItem(PushMultipleItem.item, "片库", data));
mainAdapter.addData(multipleItems);
if (page2 >= 10) {
mainAdapter.loadMoreEnd(false);
} else {
page2++;
mainAdapter.loadMoreComplete();
}
}
@Override
public void onError(Response<VideoBeanBottom> response) {
mainAdapter.loadMoreFail();
}
});
}
@NotNull
private ArrayList<PushMultipleItem> getPushMultipleItems(GetTypeVodsBean body) {
ArrayList<PushMultipleItem> multipleItems = new ArrayList<>();
//遍历Map
Map<String, ArrayList<VideoBean>> vods = body.getVods();
Map<String, ArrayList<SubjectsBean>> beans = body.getSubjects();
if (vods != null && beans != null) {
for (String key : vods.keySet()) {
ArrayList<VideoBean> videoBeans = vods.get(key);
ArrayList<SubjectsBean> zhuanTiBannerBeans = beans.get(key);
if (videoBeans != null && videoBeans.size() > 0) {
VideoBean bean = new VideoBean();
bean.setVod_name(ListSharedPreferences.getTypeName(Integer.parseInt(key)));
bean.setVod_id(Integer.parseInt(key));
multipleItems.add(new PushMultipleItem(PushMultipleItem.title, bean));
multipleItems.add(new PushMultipleItem(PushMultipleItem.banner, zhuanTiBannerBeans));
multipleItems.add(new PushMultipleItem(PushMultipleItem.item, key, videoBeans));
multipleItems.add(new PushMultipleItem(PushMultipleItem.changer, key, null));
}
}
}
return multipleItems;
}
}
老版核心代码——请使用对比软件,观察两个的不同:
public class ChildRecommendFragment {
@BindView(R.id.sl_Push)
SwipeRefreshLayout sl_Push;
@BindView(R.id.rv_pu_bu)
RecyclerView rv_pu_bu;
@BindView(R.id.loading)
View loading;
@BindView(R.id.load_err)
View load_err;
/**
* 上拉加载页数
*/
public int pagePullRefresh = 1;
public int page = 1;
public int page2 = 1;
private RecommendAdapter mainAdapter;
private RecommendAdapter bottomAdapter;
private ArrayList<PushMultipleItem> multipleList = new ArrayList<>();
private ArrayList<VideoBean> bottomData = new ArrayList<>();
@Override
protected void initView() {
View bannerAdLayout = View.inflate(getContext(), R.layout.item_push_head_child, null);
initBanner(bannerAdLayout);
adImage = bannerAdLayout.findViewById(R.id.adImage);
View head_big_recommend = View.inflate(getContext(), R.layout.head_big_recommend, null);
RecyclerView rv_child_Push = head_big_recommend.findViewById(R.id.rv_child_Push);
LinearLayoutManager manager = new LinearLayoutManager(mActivity);
rv_child_Push.setLayoutManager(manager);
mainAdapter = new RecommendAdapter(null);
rv_child_Push.setAdapter(mainAdapter);
LinearLayoutManager manager2 = new LinearLayoutManager(mActivity);
rv_pu_bu.setLayoutManager(manager2);
bottomAdapter = new RecommendAdapter(null);
bottomAdapter.addHeaderView(head_big_recommend);
rv_pu_bu.setAdapter(bottomAdapter);
mainAdapter.addHeaderView(bannerAdLayout);
pianKuHeader = View.inflate(getContext(), R.layout.header_title, null);
mainAdapter.addFooterView(pianKuHeader, ConstantUtils.getSpanCount());
//上拉加载
mainAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
@Override
public void onLoadMoreRequested() {
httpPager();
}
}, rv_child_Push);
bottomAdapter.setLoadMoreView(new LoadingAddDataView());
bottomAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
JumpUtils.jumpToPlayerAct(bottomData.get(position).getVod_id());
}
});
bottomAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
@Override
public void onLoadMoreRequested() {
httpPager2();
}
}, rv_pu_bu);
sl_Push.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
pagePullRefresh = getRandomPageRefresh();
page = 1;
httpData();
}
});
load_err.setOnClickListener(view -> {
loading.setVisibility(View.VISIBLE);
load_err.setVisibility(View.GONE);
page = 1;
httpData();
});
}
@Override
protected void initData() {
loading.setVisibility(View.VISIBLE);
httpData();
page2 = 1;
httpPager2();
}
/**
* 请求数据集合
*/
private void httpData() {
String url = ConstantUtils.getUrlConstant().video_type
+ "?type_id=" + getArguments().get("id")
+ "&version=" + AppUtils.getAppVersionCode()
+ "&page=" + pagePullRefresh
+ "&mobiletype=1";
OkGoUtils.getRequest(url, new JsonCallBack<GetTypeDetailBean>(GetTypeDetailBean.class, mActivity) {
@Override
public void onStart(Request<GetTypeDetailBean, ? extends Request> request) {
}
@Override
public void onSuccess(Response<GetTypeDetailBean> response) {
loading.setVisibility(View.GONE);
load_err.setVisibility(View.GONE);
clearList();
sl_Push.setRefreshing(false);
GetTypeDetailBean body = response.body();
multipleList = bornMultipleList(body);
mainAdapter.setNewData(multipleList);
}
@Override
public void onError(Response<GetTypeDetailBean> response) {
loading.setVisibility(View.GONE);
sl_Push.setRefreshing(false);
ToastUtils.showShort("连接服务器失败");
if (mainAdapter.getData().size() == 0) {
load_err.setVisibility(View.VISIBLE);
}
}
});
}
private String getHotVideoNewUrl(String id) {
return ConstantUtils.getUrlConstant().gethotvodnew
+ "?type_id=" + id
+ "&page=" + MyAppUtils.getRandomPage();
}
private ArrayList<PushMultipleItem> bornMultipleList(GetTypeDetailBean body) {
ArrayList<PushMultipleItem> multipleList = new ArrayList<>();
GetTypeDetailBean.RenhotBean renhot = body.getRenhot();
VideoBean recentTitleBean = new VideoBean(ConstantUtils.RECENT_ID, ConstantUtils.RECENT_VALUE);
VideoBean hotTitleBean = new VideoBean(ConstantUtils.HITS_ID, ConstantUtils.HITS_VALUE);
multipleList.add(new PushMultipleItem(PushMultipleItem.title, recentTitleBean));
multipleList.add(new PushMultipleItem(PushMultipleItem.item, ConstantUtils.RECENT_KEY, renhot.getRecent()));
multipleList.add(new PushMultipleItem(PushMultipleItem.changer, ConstantUtils.RECENT_KEY, null));
multipleList.add(new PushMultipleItem(PushMultipleItem.title, hotTitleBean));
multipleList.add(new PushMultipleItem(PushMultipleItem.item, ConstantUtils.HITS_KEY, renhot.getHits()));
multipleList.add(new PushMultipleItem(PushMultipleItem.changer, ConstantUtils.HITS_KEY, null));
return multipleList;
}
private void clearList() {
if (multipleList != null && multipleList.size() > 0) {
multipleList.clear();
}
}
/**
* 分页请求
*/
private void httpPager() {
OkGoUtils.getRequest(getUrl(), new JsonCallBack<GetTypeVodsBean>(GetTypeVodsBean.class, mActivity) {
@Override
public void onStart(Request<GetTypeVodsBean, ? extends Request> request) {
}
@Override
public void onSuccess(Response<GetTypeVodsBean> response) {
GetTypeVodsBean body = response.body();
mainAdapter.addData(getPushMultipleItems(body));
if (page >= body.getLast_page()) {
mainAdapter.loadMoreEnd(true);
} else {
page++;
mainAdapter.loadMoreComplete();
}
}
@Override
public void onError(Response<GetTypeVodsBean> response) {
mainAdapter.loadMoreFail();
}
});
}
@NotNull
private String getUrl() {
return ConstantUtils.getUrlConstant().getypevods
+ "?type_id=" + getArguments().get("id")
+ "&type_name=" + ListSharedPreferences.getTypeName((Integer) getArguments().get("id"))
+ "&page=" + page;
}
private void httpPager2() {
String url = ConstantUtils.getUrlConstant().getrecentvod
+ "?type_id=" + getArguments().get("id")
+ "&type_name=" + ListSharedPreferences.getTypeName((Integer) getArguments().get("id"))
+ "&page=" + page2;
OkGoUtils.getRequest(url, new JsonCallBack<VideoBeanBottom>(VideoBeanBottom.class, mActivity) {
@Override
public void onStart(Request<VideoBeanBottom, ? extends Request> request) {
}
@Override
public void onSuccess(Response<VideoBeanBottom> response) {
if (pianKuHeader != null) {
pianKuHeader.setVisibility(View.VISIBLE);
}
loading.setVisibility(View.GONE);
VideoBeanBottom body = response.body();
List<VideoBean> data = body.getData();
ArrayList<PushMultipleItem> multipleItems = new ArrayList<>();
multipleItems.add(new PushMultipleItem(PushMultipleItem.item, "片库", data));
bottomAdapter.addData(multipleItems);
if (page2 >= 10) {
bottomAdapter.loadMoreEnd(false);
} else {
page2++;
bottomAdapter.loadMoreComplete();
}
}
@Override
public void onError(Response<VideoBeanBottom> response) {
bottomAdapter.loadMoreFail();
}
});
}
@NotNull
private ArrayList<PushMultipleItem> getPushMultipleItems(GetTypeVodsBean body) {
ArrayList<PushMultipleItem> multipleItems = new ArrayList<>();
//遍历Map
Map<String, ArrayList<VideoBean>> vods = body.getVods();
Map<String, ArrayList<SubjectsBean>> beans = body.getSubjects();
if (vods != null && beans != null) {
for (String key : vods.keySet()) {
ArrayList<VideoBean> videoBeans = vods.get(key);
ArrayList<SubjectsBean> zhuanTiBannerBeans = beans.get(key);
if (videoBeans != null && videoBeans.size() > 0) {
VideoBean bean = new VideoBean();
bean.setVod_name(ListSharedPreferences.getTypeName(Integer.parseInt(key)));
bean.setVod_id(Integer.parseInt(key));
multipleItems.add(new PushMultipleItem(PushMultipleItem.title, bean));
multipleItems.add(new PushMultipleItem(PushMultipleItem.banner, zhuanTiBannerBeans));
multipleItems.add(new PushMultipleItem(PushMultipleItem.item, key, videoBeans));
multipleItems.add(new PushMultipleItem(PushMultipleItem.changer, key, null));
}
}
}
return multipleItems;
}
}
对比效果如图:
下拉刷新部分.png第一个加载到底的是数据衔接部分 统一Adapter后,将第二个adapter换成第一个adapter
大概这也是我能想到的最好的办法了——核心代码用对比软件对比
参考链接:https://www.jianshu.com/p/1add7d5a4ec4
https://www.jianshu.com/p/34d2c5cdb3fb