Continious scrolling in recyclerview by Json reque

2019-07-18 23:06发布

问题:

I want to implement endless scrolling in recyclerview by calling new JSON request with increment of page number and adding those result with the previous results. first request shows 20 results but there are 200+ results left to show.How can i have endless scroll with onLoadMore() function in 'TopratedFragment.java'.Please help with the codes

TopratedFragment.java

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.JsonObjectRequest;
import com.example.mitab.mentor.Movies.Pages.L;
import com.example.mitab.mentor.Movies.Pages.MyApplication;
import com.example.mitab.mentor.Movies.Pages.VolleySingleton;
import com.example.mitab.mentor.Movies.Pages.movie;
import com.example.mitab.mentor.R;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import android.os.Handler;

import static com.example.mitab.mentor.Movies.Pages.Keys.EndpointToprated.*;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link TopratedFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class TopratedFragment extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
    public static final String Top_rated="http://api.themoviedb.org/3/movie/top_rated";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;
    protected Handler handler;
    private VolleySingleton volleySingleton;
    private ImageLoader imageLoader;
    int page=1;
    private RequestQueue requestQueue;
    private ArrayList<movie> listMovies=new ArrayList<>();
    private ArrayList<movie> newlistMovies=new ArrayList<>();
    private SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
    private RecyclerView listMovieHits;
    private AdapterToprated adapterToprated;
    boolean loadingMore = false;
    private int lastVisibleItemId=0;


    public TopratedFragment() {
        // Required empty public constructor
    }

    // TODO: Rename and change types and number of parameters
    public static TopratedFragment newInstance(String param1, String param2) {
        TopratedFragment fragment = new TopratedFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }

        volleySingleton= VolleySingleton.getsInstance();
        requestQueue=volleySingleton.getRequestQueue();

        sendJsonRequest();
    }

    private void sendJsonRequest(){
        JsonObjectRequest request=new JsonObjectRequest(Request.Method.GET, getRequestUrl(page), (String)null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                listMovies=parseJSONResponse(response);
                adapterToprated.setMovieList(listMovies);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        requestQueue.add(request);
    }

    private ArrayList<movie> parseJSONResponse(JSONObject response){
        ArrayList<movie> listMovies=new ArrayList<>();
        if (response==null || response.length()>0){



            try {
                JSONArray arrayMovies=response.getJSONArray(KEY_MOVIES);
                for (int i=0;i<arrayMovies.length();i++){

                    long id=-1;
                    String title="NA";
                    String poster="NA";
                    String release="NA";
                    String overview="NA";
                    String vote="NA";
                    String votecount="NA";

                    JSONObject currentMovie=arrayMovies.getJSONObject(i);

                    //get the id of current movie
                    if (currentMovie.has(KEY_ID)&& !currentMovie.isNull(KEY_ID)){
                        id=currentMovie.getLong(KEY_ID);
                    }

                    if (currentMovie.has(KEY_TITLE)&& !currentMovie.isNull(KEY_TITLE)){
                        title=currentMovie.getString(KEY_TITLE);
                    }

                    if (currentMovie.has(KEY_POSTER_PATH)&& !currentMovie.isNull(KEY_POSTER_PATH)){
                        poster=currentMovie.getString(KEY_POSTER_PATH);
                    }

                    if (currentMovie.has(KEY_RELEASE_DATE)&& !currentMovie.isNull(KEY_RELEASE_DATE)){
                        release=currentMovie.getString(KEY_RELEASE_DATE);
                    }

                    if (currentMovie.has(KEY_OVERVIEW)&& !currentMovie.isNull(KEY_OVERVIEW)){
                        overview=currentMovie.getString(KEY_OVERVIEW);
                    }

                    if (currentMovie.has(KEY_AVERAGE_VOTE)&& !currentMovie.isNull(KEY_AVERAGE_VOTE)){
                        vote=currentMovie.getString(KEY_AVERAGE_VOTE);
                    }

                    if (currentMovie.has(KEY_VOTE_COUNT)&& !currentMovie.isNull(KEY_VOTE_COUNT)){
                        votecount=currentMovie.getString(KEY_VOTE_COUNT);
                    }







                    JSONArray genre=currentMovie.getJSONArray(KEY_GENRE_IDS);

                    if (currentMovie.has(KEY_GENRE_IDS)&& !currentMovie.isNull(KEY_GENRE_IDS)){
                        for (int j=0;j<genre.length();j++){
                            try {
                                String itemInArray=genre.getString(j);

                            }
                            catch (JSONException e){

                            }
                        }
                    }


                    movie movie=new movie();
                    movie.setId(id);
                    movie.setTitle(title);
                    movie.setOverview(overview);
                    movie.setAveragevote(vote);
                    Date date=null;
                    try {
                        date=dateFormat.parse(release);
                    }
                    catch (ParseException e){

                    }

                    movie.setReleasedate(date);
                    movie.setImage(poster);
                    movie.setVotecount(votecount);

                    if (id!=-1 && !title.equals("NA"))
                    {
                        listMovies.add(movie);
                    }


                }



            }
            catch (JSONException e){

            }
        }
        return listMovies;
    }

    public static String getRequestUrl(int page){
        return Top_rated +"?api_key="+ MyApplication.API_KEY + "&page="+page;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.fragment_toprated, container, false);

        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        handler=new Handler();
        listMovieHits=(RecyclerView) view.findViewById(R.id.listMovieHits);
        listMovieHits.setLayoutManager(linearLayoutManager);

        adapterToprated=new AdapterToprated(getActivity());
        listMovieHits.setAdapter(adapterToprated);
        //sendJsonRequest();
        // Add the scroll listener
        listMovieHits.addOnScrollListener(new EndlessRecyclerViewScrollListener(linearLayoutManager) {
            @Override
            public void onLoadMore(int page, int totalItemsCount) {
                loadingMore=true;
                sendJsonRequest();
                int curlsize=adapterToprated.getItemCount();
                listMovies.addAll(newlistMovies);
                adapterToprated.notifyItemRangeChanged(curlsize,listMovies.size()-2);
            }
        });
        // Inflate the layout for this fragment
        return view;
    }



}

AdapterToprated.java

import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.example.mitab.mentor.MainActivity;
import com.example.mitab.mentor.Movies.Pages.L;
import com.example.mitab.mentor.Movies.Pages.VolleySingleton;
import com.example.mitab.mentor.Movies.Pages.movie;
import com.example.mitab.mentor.R;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;


public class AdapterToprated extends RecyclerView.Adapter<AdapterToprated.ViewHolderToprated> {

    private LayoutInflater layoutInflater;
    private VolleySingleton volleySingleton;
    private ImageLoader imageLoader;
    private ArrayList<movie> listMovies=new ArrayList<movie>();
    private SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
    private RecyclerView.OnItemTouchListener onItemTouchListener;
    Context context;



    public AdapterToprated(Context context){
        layoutInflater=LayoutInflater.from(context);
        volleySingleton=VolleySingleton.getsInstance();
        imageLoader=volleySingleton.getImageLoader();
        this.context = context;
    }

    public void setMovieList(ArrayList<movie> listMovies){
        this.listMovies=listMovies;
        notifyItemRangeChanged(0, listMovies.size());
    }
    @Override
    public ViewHolderToprated onCreateViewHolder(ViewGroup parent, int viewType) {
        View view=layoutInflater.inflate(R.layout.individual_toprated, parent, false);
        ViewHolderToprated viewHolderToprated=new ViewHolderToprated(view);
        return viewHolderToprated;
    }

    @Override
    public void onBindViewHolder(final ViewHolderToprated holder, int position) {
        final movie currentMovie=listMovies.get(position);
        holder.movieTitle.setText(currentMovie.getTitle());
        Date movieReleaseDate=currentMovie.getReleasedate();
        if (movieReleaseDate!=null){
            String formattedDate=dateFormat.format(movieReleaseDate);
            holder.movieReleaseDate.setText(formattedDate);
        }else{
            holder.movieReleaseDate.setText("NA");
        }

        holder.movieRating.setText(currentMovie.getAveragevote());
        String urlThumnail=currentMovie.getImage();
        if (!urlThumnail.equals("NA")){
            imageLoader.get(urlThumnail, new ImageLoader.ImageListener() {
                @Override
                public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
                    holder.movieThumbnail.setImageBitmap(response.getBitmap());
                }

                @Override
                public void onErrorResponse(VolleyError error) {

                }
            });
        }
        holder.lnrLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(context,Intentpass.class);
                Bundle extras=new Bundle();
                extras.putString("Title","currentMovie.getTitle()");
                extras.putString("Date","formattedDate");
                extras.putString("Rating","currentMovie.getAveragevote()");
                intent.putExtras(extras);
                context.startActivity(intent);
                //intent.putExtra("details",currentMovie.getTitle());
                //context.startActivity(intent);

            }
        });


    }

    @Override
    public int getItemCount() {
        return listMovies.size();
    }

    static class ViewHolderToprated extends RecyclerView.ViewHolder{

        private ImageView movieThumbnail;
        private TextView movieTitle;
        private TextView movieReleaseDate;
        private TextView movieRating;
        private RelativeLayout lnrLayout;

        public ViewHolderToprated(View itemView) {
            super(itemView);
            movieThumbnail=(ImageView) itemView.findViewById(R.id.movieThumbnail);
            movieTitle=(TextView) itemView.findViewById(R.id.movieTitle);
            movieReleaseDate=(TextView) itemView.findViewById(R.id.movieReleaseDate);
            movieRating=(TextView) itemView.findViewById(R.id.movieRating);
            lnrLayout=(RelativeLayout)itemView.findViewById(R.id.lnLayout);
        }
    }
}

EndlessRecyclerViewScrollListener.java

import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;

public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
    // The minimum amount of items to have below your current scroll position
    // before loading more.
    private int visibleThreshold = 5;
    // The current offset index of data you have loaded
    private int currentPage = 0;
    // The total number of items in the dataset after the last load
    private int previousTotalItemCount = 0;
    // True if we are still waiting for the last set of data to load.
    private boolean loading = true;
    // Sets the starting page index
    private int startingPageIndex = 0;

    RecyclerView.LayoutManager mLayoutManager;

    public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
    }

    public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
    }

    public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
        this.mLayoutManager = layoutManager;
        visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
    }

    public int getLastVisibleItem(int[] lastVisibleItemPositions) {
        int maxSize = 0;
        for (int i = 0; i < lastVisibleItemPositions.length; i++) {
            if (i == 0) {
                maxSize = lastVisibleItemPositions[i];
            }
            else if (lastVisibleItemPositions[i] > maxSize) {
                maxSize = lastVisibleItemPositions[i];
            }
        }
        return maxSize;
    }

    // This happens many times a second during a scroll, so be wary of the code you place here.
    // We are given a few useful parameters to help us work out if we need to load some more data,
    // but first we check if we are waiting for the previous load to finish.
    @Override
    public void onScrolled(RecyclerView view, int dx, int dy) {
        int lastVisibleItemPosition = 0;
        int totalItemCount = mLayoutManager.getItemCount();

        if (mLayoutManager instanceof StaggeredGridLayoutManager) {
            int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
            // get maximum element within the list
            lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
        } else if (mLayoutManager instanceof LinearLayoutManager) {
            lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
        } else if (mLayoutManager instanceof GridLayoutManager) {
            lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
        }

        // If the total item count is zero and the previous isn't, assume the
        // list is invalidated and should be reset back to initial state
        if (totalItemCount < previousTotalItemCount) {
            this.currentPage = this.startingPageIndex;
            this.previousTotalItemCount = totalItemCount;
            if (totalItemCount == 0) {
                this.loading = true;
            }
        }
        // If it’s still loading, we check to see if the dataset count has
        // changed, if so we conclude it has finished loading and update the current page
        // number and total item count.
        if (loading && (totalItemCount > previousTotalItemCount)) {
            loading = false;
            previousTotalItemCount = totalItemCount;
        }

        // If it isn’t currently loading, we check to see if we have breached
        // the visibleThreshold and need to reload more data.
        // If we do need to reload some more data, we execute onLoadMore to fetch the data.
        // threshold should reflect how many total columns there are too
        if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
            currentPage++;
            onLoadMore(currentPage, totalItemCount);
            loading = true;
        }
    }

    // Defines the process for actually loading more data based on page
    public abstract void onLoadMore(int page, int totalItemsCount);

}

回答1:

You only have to add your new data to the last position of list movies and everything will work fine. For this-

Create a new List like ArrayList<movie> newListMovies and add your updated data into it. Now add newListMovies into listMovies and notify to adapter. Just like below-

  ArrayList<movie> newListMovies = new ArrayList<>();

  // your code..

  listMovieHits.addOnScrollListener(new EndlessRecyclerViewScrollListener(linearLayoutManager) {
        @Override
        public void onLoadMore(int page, int totalItemsCount) {
            loadingMore=true;
            sendJsonRequest();

            int currentSize = adapter.getItemCount();
            listMovies.addAll(newListMovies);
            adapter.notifyItemRangeInserted(currentSize, listMovies.size() - 2);
        }
    });

Hope it will help.