我有一个回收站,里面有卡片视图,我从REST服务获取信息,我正在尝试实现无限滚动,假设用户每次向下滚动时都会看到10张卡片视图,直到没有更多卡片视图展示,我该如何实现?
我见过几个例子,但没有一个真正帮助我如何做到这一点。我甚至不知道我需要放在adapter.class或我的Fragment.class中,因为我不明白如何实现它,如果有人能告诉我实现无限卷轴的正确方法会很棒我的代码......
提前致谢。
MainAdapter.class
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> implements View.OnClickListener
{
private ArrayList<Business> businessList;
private Activity activity;
private int layoutMolde,idb;
public MainAdapter(Activity activity, ArrayList<Business> list, int layout)
{
this.activity = activity;
this.businessList = list;
layoutMolde = layout;
}
@Override
public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_row, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.mTitle.setText(businessList.get(position).getBusiness_name());
holder.number_rating.setText(businessList.get(position).getRating().toString());
Glide.with(activity).load(businessList.get(position).getLogo_url_string()).into(holder.mImg);
}
@Override
public int getItemCount() {
return businessList.size();
}
@Override
public void onClick(View v)
{
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTitle;
public ImageView mImg;
public ImageView logo;
public RatingBar main_rating;
public TextView number_rating;
public ViewHolder( View itemView)
{
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.nom_business_main);
number_rating = (TextView) itemView.findViewById(R.id.number_rating);
mImg = (ImageView) itemView.findViewById(R.id.img_main);
main_rating=(RatingBar) itemView.findViewById(R.id.rating_main);
main_rating.setRating((float)1);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
Intent in = new Intent(v.getContext(), BusinessPremium.class);
int position = getAdapterPosition();
idb = businessList.get(position).getId();
in.putExtra("no", idb);
v.getContext().startActivity(in);
}
});
}
}
}
FeedsFragment.class
public class FeedsFragment extends Fragment
{
private ArrayList<Business> arrayBusiness,arrayBasics;
private Gson gson;
private static final Type BUSINESS_TYPE = new TypeToken<ArrayList<Business>>() {}.getType();
private RecyclerView.LayoutManager mLayoutManager;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View android = inflater.inflate(R.layout.fragment_feeds, container, false);
if (!internetConnectionCheck(FeedsFragment.this.getActivity()))
{
Toast.makeText(getApplicationContext(), "Error de Conexión", Toast.LENGTH_LONG).show();
}
new RequestBase(getActivity()) {
@Override
public JsonObject onHttpOk(JsonObject response) throws JSONException {
JsonObject objeto, pagination_details = null, details, premium_img;
JsonArray data;
if (getActivity() == null)
return response;
if (response.get("pagination") == null)
{
objeto = response;
} else {
objeto = response;
pagination_details = response.get("pagination").getAsJsonObject();
data = objeto.get("data").getAsJsonArray();
gson = new Gson();
arrayBusiness = gson.fromJson(data, BUSINESS_TYPE);
Log.d("size", String.valueOf(arrayBusiness.size()));
FeedsFragment.this.getActivity().runOnUiThread(new Runnable()
{
@Override
public void run()
{
RecyclerView recycler = (RecyclerView) FeedsFragment.this.getActivity().findViewById(R.id.recycler_main);
MainAdapter adapter = new MainAdapter(getActivity(), arrayBusiness, R.layout.main_row);
recycler.setNestedScrollingEnabled(false);
mLayoutManager = new GridLayoutManager(FeedsFragment.this.getActivity(), 2);
recycler.setLayoutManager(mLayoutManager);
recycler.setAdapter(adapter);
GifTextView loading = (GifTextView)FeedsFragment.this.getActivity().findViewById(R.id.loading);
TextView loadingText = (TextView)FeedsFragment.this.getActivity().findViewById(R.id.loadingText);
loading.setVisibility(View.GONE);
loadingText.setVisibility(View.GONE);
}
});
}
if (pagination_details.isJsonNull()) {
Log.d("Paginacion", pagination_details.toString());
}
return objeto;
}
@Override
public void onHttpCreate(JsonObject response) throws JSONException
{
}
@Override
public void onHttpUnprocessableEntity(JsonObject response) throws JSONException
{
this.cancel(true);
final String error = response.get("errors").toString();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getActivity().getApplicationContext(), error, Toast.LENGTH_LONG).show();
}
});
}
}.execute("businesses/premiums", "GET");
return android;
}
}
答案 0 :(得分:1)
你可以使用Android中的SwipeRefreshLayout刷新刷新,并在on refresh override方法中调用你的api
注意:将您的API调用请求放入方法中,并在您的SwipeRefreshLayout的onRefresh方法中调用该方法
答案 1 :(得分:1)
在编写RecyclerView.Adapter时,无论如何,您需要提供返回正确数量的项目(可能很大)的getItemCount
方法。 RecyclerView将主动调用此适配器的onBindViewHolder
(持有者,位置)方法。您所需要的只是提供与此职位相关的检索数据的功能。如果您的列表小于屏幕,略大于屏幕或Integer.MAX_VALUE大小,则没有任何区别。 RecyclerView将注意不要获取/分配太多额外的项目。
你 不 需要实现滚动侦听器或以其他方式显式处理滚动。
唯一棘手的部分是您可能需要采取长时间的操作,如服务器调用来获取一些项目。然后在第一次调用时返回未初始化的holder(空视图),并开始在后台线程中获取所需的行。如果有,请致电notifyDataSetChanged
或notifyItemRangeChanged
,RecyclerView会自行更新。
出于性能原因,我强烈建议更新固定大小的块内容,而不是每显示一行发送单独的服务器请求。对于某些公共服务器(如Google图书),这显然是一项要求,因为它们具有每个请求的配额限制。
如果您需要查看有关如何实现此功能的完整源代码,则会有open source project here in GitHub。
答案 2 :(得分:0)
您可以在Recyclerview中添加scrollListener
。
检查类似的答案here
主要的SO帖子here
在哪里,scrollListener
将检查您在recyclerview中的确切位置,并根据某些逻辑(您可以灵活地编写)进行第二次调用!
答案 3 :(得分:0)
创建一个名为&#34的静态布尔变量; ready&#34;并将其初始化为false。
在onLoadMore方法中添加if ready条件,如下所示。
public boolean onLoadMore(int page, int totalItemsCount) {
if (ready) {
//load more from API
}
return false;
}
当item的位置为last时,在onBindViewHolder中设置为true。
答案 4 :(得分:0)
这是我的一位同事介绍的一种方式。我们一起工作,我没有任何问题地成功实施了它。我想回馈有这个问题的任何人。
在您的适配器中,您需要将计数设置为无限大小,然后当您想要某个项目的位置时,在需要该位置时应使用val loopPos = position % dataSource.size
。让我们看看如何在recyclerView适配器中完成此操作,但也可以将其应用于FragmentStatePagerAdapter。
class InfiniteLoopingHorizontalRecyclerViewAdapter(var dataSource: ArrayList<String>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflatedView: View = LayoutInflater.from(parent.context)
.inflate(R.layout.your_finite_layout, parent, false)
return ItemHolder(inflatedView)
}
override fun getItemCount(): Int {
return Integer.MAX_VALUE //***** this should be high enough - wink wink ******
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
//****** this is critical here when you need the position use the loopPos ****/
val loopPos = position % dataSource.size
(holder as? ItemHolder)?.bind(dataSource[loopPos], loopPos)
}
inner class ItemHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(myString: String, position: Int) = with(itemView) {
myTextView.setText(myString)
}
}
}
它如何工作:
让我们说您的dataSource大小为50,但您的排名为51,表示以下内容:51%50。这将给您排名1的位置,再说一次您的位置是57,而dataSource的大小仍然是50。这意味着您的位置是7。要明确一点,只要您需要无限影响,就可以使用该位置的模块dataSource大小。
ps: 让我们抓狂,说我们滚动到位置11323232323214,然后这意味着11323232323214%50 = 14,因此它将在您的数据源中使用位置14。然后,您可以将您的recyclerview封装在SnapHelper class
中,以消除影响