RecyclerViewPagination Endless Infinite Scrolling

2019-09-13 10:51发布

问题:

I am trying to implement Endless Infinite Scrolling with RecyclerView, but I am only getting all records and even not getting any progress while trying to scroll at bottom.

this is News_Fragment

public class News_Fragment extends Fragment {

private List<News> newsList = new ArrayList<>();

private TextView textView;
private RecyclerView recyclerView;
private NewsAdapter newAdapter;
private ProgressBar mProgressBar;

protected Handler handler;

public News news;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_news_, container, false);

    loadData();

    handler = new Handler();

    recyclerView = (RecyclerView) rootView.findViewById(R.id.News_recycler_view);

    textView = (TextView)rootView.findViewById(R.id.empty_view);

    mProgressBar = (ProgressBar) rootView.findViewById(R.id.progressBar);
    //recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

    recyclerView.setHasFixedSize(true);

    final LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
    recyclerView.setItemAnimator(new DefaultItemAnimator());

    recyclerView.setAdapter(newAdapter);
    newAdapter = new NewsAdapter(newsList,recyclerView);

    if(newsList.isEmpty()){
        recyclerView.setVisibility(View.GONE);
        textView.setVisibility(View.VISIBLE);
    }else {
        recyclerView.setVisibility(View.VISIBLE);
        textView.setVisibility(View.GONE);
    }

    newAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
        @Override
        public void onLoadMore() {
            //add null , so the adapter will check view_type and show progress bar at bottom
            newsList.add(null);
            newAdapter.notifyItemInserted(newsList.size() - 1);
            handler.postDelayed(new Runnable(){
                @Override
                public void run() {
                    //remove progress item
                    newsList.remove(newsList.size() - 1);
                    newAdapter.notifyItemRemoved(newsList.size());

                    //add items  one bye one
                    int start = newsList.size();
                    int end = start + 5;
                    for (int i = start + 1;i <= end ; i++) {

                        newsList.add(new News("skip"+start,"limit"+end));
                        newAdapter.notifyItemInserted(newsList.size());
                    }
                        newAdapter.setLoaded();

                }
            },2000);
        }
    });
    JSONObject jsonObject = new JSONObject();

    try {
        jsonObject.put("skip",0);
        jsonObject.put("limit",50);
    } catch (JSONException e) {
        e.printStackTrace();
    }

    new NewsTask() {
        @Override
        protected void onPostExecute(APIResponse apiResponse) {
            if (apiResponse != null && apiResponse.data != null & apiResponse.data.size() > 0) {
                newsList = apiResponse.data;
                //newAdapter.notifyDataSetChanged();
                newAdapter = new NewsAdapter(newsList,recyclerView);
                recyclerView.setAdapter(newAdapter);
            }
            Log.i("resp", "onPostExecute");
            //Hide progressbar
            mProgressBar.setVisibility(View.GONE);
        }
    }.execute(jsonObject);
    mProgressBar.setVisibility(View.VISIBLE);
    return rootView;
}
//load initial data
private void loadData(){
    int start = newsList.size();
    int end = start + 5;
    for (int i = 1;i<=10;i++){

        News news = new News("skip"+i,"limit"+i);
        newsList.add(0,news);

    }
}

this is NewsTask

public class NewsTask  extends  AsyncTask<JSONObject, Integer, APIResponse>{
ProgressDialog dialog;
OkHttpClient client = new OkHttpClient();
Gson gson = new Gson();
private ProgressBar mProgressBar;
Context context;

@Override
protected APIResponse doInBackground(JSONObject... params) {
   //  http://bitstobyte.in/api/news
    // strat 0
    // end 10
    JSONObject jsonObject  = params[0];

    try {
        String skip = jsonObject.getString("skip");
        String limit = jsonObject.getString("limit");
        String url = "http://bitstobyte.in/api/news?query={%22skip%22:"+skip+",%22limit%22:"+limit+"}";


        Request request = new Request.Builder().url(url).build();
        Response response = client.newCall(request).execute();
        if(!response.isSuccessful()){
            Log.v("answer","failed"+response.code());
            throw new IOException("UnExpected code"+response);
        }
        String strResponse = response.body().string();
        Log.d("News_Response",strResponse);

        MainResponse mainResponse = gson.fromJson(strResponse,MainResponse.class);
        // deserialze and return.
        return mainResponse.msg;
    }catch (IOException e) {
        Log.e("searchTask",e.toString());
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return null;
}

}

this is NewsAdapter

public class NewsAdapter extends RecyclerView.Adapter {
private final int VIEW_ITEM = 1;
private final int VIEW_PROG = 0;

private List<News> newsList;
private Context context;

// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
private boolean loading;
private OnLoadMoreListener onLoadMoreListener;

public NewsAdapter(List<News> newsList , RecyclerView recyclerView){
    this.newsList = newsList;
    this.context = context;

    if(recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
        final  LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                    // End has been reached
                    // Do something
                    if (onLoadMoreListener != null) {
                        onLoadMoreListener.onLoadMore();
                    }
                    loading = true;
                }
            }
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                // When went to the end of the list, load more posts
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {

                    if (linearLayoutManager.findLastVisibleItemPosition() >= linearLayoutManager.getItemCount() - 1) {
                        // Grow List
                    }
                }
            }
        });
    }
}
@Override
public int getItemViewType(int position){
    return newsList.get(position) instanceof News ? VIEW_ITEM : VIEW_PROG;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
    RecyclerView.ViewHolder vh;
    if (viewType == VIEW_ITEM) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_list_row, parent, false);
        vh = new MyViewHolder(v);
    } else {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.progress_item, parent, false);

        vh = new ProgressViewHolder(v);
    }
    return vh;
}

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView title;
    public ImageView image,nextArrowimage;
    public TextView desc;
    private News news;

    public MyViewHolder(View view) {
        super(view);
        title = (TextView) view.findViewById(R.id.News_title);
        image = (ImageView) view.findViewById(R.id.News_imageView);
        nextArrowimage = (ImageView)view.findViewById(R.id.news_NextArrow);
        desc = (TextView) view.findViewById(R.id.News_desc);

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                    String title = news.getTitle();
                    String desc = news.getDesc();
                    String image = "http://bitstobyte.in/upload/"+news.getImage();

                    Intent intent = new Intent(context, News_Activity.class);
                    intent.putExtra("title", title);
                    intent.putExtra("desc",desc);
                    intent.putExtra("imageUrl", image);
                    context.startActivity(intent);

                    Toast.makeText(v.getContext(), "OnClick :" + news.getTitle() + " \n "+news.getImage(),Toast.LENGTH_SHORT).show();
            }
        });

    }
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder,int position){
    if (holder instanceof MyViewHolder) {

        final News single_news= (News) newsList.get(position);

        ((MyViewHolder) holder).title.setText(single_news.getTitle());

        ((MyViewHolder) holder).desc.setText(single_news.getDesc());

        ((MyViewHolder) holder).nextArrowimage.setImageResource(R.drawable.nextblackbutton);

        context = ((MyViewHolder) holder).image.getContext();

        Picasso.with(context).load("http://bitstobyte.in/upload/"+single_news.getImage()).placeholder(R.drawable.ic_favorite_white_24dp).error(R.drawable.ic_map_24dp).resize(100,100).into(((MyViewHolder) holder).image);

        ((MyViewHolder) holder).news= single_news;

    } else {
        ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
    }
}
public void setLoaded() {
    loading = false;
}
@Override
public int getItemCount() {
    return newsList.size();
}

public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
    this.onLoadMoreListener = onLoadMoreListener;
}

public static class ProgressViewHolder extends RecyclerView.ViewHolder {
    public ProgressBar progressBar;

    public ProgressViewHolder(View v) {
        super(v);
        progressBar = (ProgressBar) v.findViewById(R.id.progressBar1);
    }
}

}

this is Json data

{
"status": "ok",
"msg": {
    "current": 58,
    "total": 58,
    "data": [{
        "title": "dfdsfsdf",
        "machineId": "1bc99f0a-f138-428b-9b54-5531e4c8fc3f",
        "image": "55a88fbfbc54f41570840e11.jpg",
        "partnerId": "558be1a2e1d33656b06ddbd7",
        "_id": "55a88fbfbc54f41570840e11",
        "desc": "fsfsdfdsfdsf"
    }, {
        "title": "one more test",
        "machineId": "1bc99f0a-f138-428b-9b54-5531e4c8fc3f",
        "image": "55a8901abc54f41570840e12.jpg",
        "partnerId": "558be1a2e1d33656b06ddbd7",
        "_id": "55a8901abc54f41570840e12",
        "desc": "good.."
    },

回答1:

Change getViewType like this if you want get progress bar at the end of list while calling API

@Override
public int getItemViewType(int position){
    return (position >= newsList.size()) ? VIEW_PROG : VIEW_ITEM ;
}

And Add one to size to show progress

 @Override
    public int getItemCount() {
        return newsList.size() + 1;
    }

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder,int position){
    if (newsList.get(position)!=null && getItemViewType(position)==VIEW_ITEM ) {

        final News single_news= (News) newsList.get(position);

        ((MyViewHolder) holder).title.setText(single_news.getTitle());

        ((MyViewHolder) holder).desc.setText(single_news.getDesc());

        ((MyViewHolder) holder).nextArrowimage.setImageResource(R.drawable.nextblackbutton);

        context = ((MyViewHolder) holder).image.getContext();

        Picasso.with(context).load("http://bitstobyte.in/upload/"+single_news.getImage()).placeholder(R.drawable.ic_favorite_white_24dp).error(R.drawable.ic_map_24dp).resize(100,100).into(((MyViewHolder) holder).image);

        ((MyViewHolder) holder).news= single_news;

    } else {
        ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
    }
}