2017-03-04 80 views
0

我从TMDB获取数据并将其显示在回收站视图中。我想使用无限滚动回收视图,所以我看到一些教程并实施它。问题是,在第一次加载之后,在滚动前5个元素之后,整个数据将被新数据刷新。我该如何解决?Recycler查看无限滚动不能正常工作

EndlessRecyclerViewScrollListener.java

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 = 15; 
// The current offset index of data you have loaded 
private int currentPage = 1; 
// 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 = 1; 

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 GridLayoutManager) { 
     lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition(); 
    } else if (mLayoutManager instanceof LinearLayoutManager) { 
     lastVisibleItemPosition = ((LinearLayoutManager) 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, view); 
     loading = true; 
    } 
} 

// Call this method whenever performing new searches 
public void resetState() { 
    this.currentPage = this.startingPageIndex; 
    this.previousTotalItemCount = 0; 
    this.loading = true; 
} 

// Defines the process for actually loading more data based on page 
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);/ The minimum amount of items to have below your current scroll position 
// before loading more. 
private int visibleThreshold = 15; 
// The current offset index of data you have loaded 
private int currentPage = 1; 
// 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 = 1; 

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 GridLayoutManager) { 
     lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition(); 
    } else if (mLayoutManager instanceof LinearLayoutManager) { 
     lastVisibleItemPosition = ((LinearLayoutManager) 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, view); 
     loading = true; 
    } 
} 

// Call this method whenever performing new searches 
public void resetState() { 
    this.currentPage = this.startingPageIndex; 
    this.previousTotalItemCount = 0; 
    this.loading = true; 
} 

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

MainActivity.java

public class MainActivity extends AppCompatActivity implemens ConnectivityReceiver.ConnectivityReceiverListener { 

private static final String API_KEY = "***************"; 
private static final String TAG = "MainActivity"; 
private int page = 1; 
private TextView no_data_tv; 
private RecyclerView mainMoviesView; 
private View noInternetLayout; 
private ProgressBar progressBar; 
private EndlessRecyclerViewScrollListener scrollListener; 
private LinearLayoutManager llm; 
List<Movies> movies; 


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

    no_data_tv = (TextView) findViewById(R.id.text_no_data); 

    movies = new ArrayList<>(); 

    llm = new LinearLayoutManager(this); 
    mainMoviesView = (RecyclerView) findViewById(R.id.main_recycler_view); 
    mainMoviesView.setLayoutManager(llm); 

    // This is the layout which is displayed if there is no internet connection. It is currently set to View.INVISIBLE 
    noInternetLayout = findViewById(R.id.no_internet_layout); 
    noInternetLayout.setVisibility(View.INVISIBLE); 

    progressBar = (ProgressBar) findViewById(R.id.loading_main_activity); 


    if(checkConnetion()) 
    { 
     getDataFromServer(page); 
     progressBar.setVisibility(View.INVISIBLE); 
    }else 
    { 
     noInternetLayout.setVisibility(View.VISIBLE); 
     progressBar.setVisibility(View.INVISIBLE); 
    } 

    scrollListener = new EndlessRecyclerViewScrollListener(llm) { 
     @Override 
     public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { 
      getDataFromServer(page); 
      Log.v(TAG,"Page loaded is"+page); 
     } 
    }; 
    mainMoviesView.addOnScrollListener(scrollListener); 
} 

private boolean checkConnetion() { 
    return ConnectivityReceiver.isConnected(); 
} 

private void getDataFromServer(int page) 
{ 
    // These are the retrofit codes to get the data from TMDB API 
    ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class); 

    Call<Response> call = apiService.getPopularMovies(API_KEY , page); 


    call.enqueue(new Callback<Response>() { 
     @Override 
     public void onResponse(Call<Response> call, retrofit2.Response<Response> response) { 
      List<Movies> movies = response.body().getMovies(); 
      progressBar.setVisibility(View.INVISIBLE); 
      if(movies.size() == 0) 
      { 
       no_data_tv.setVisibility(View.VISIBLE); 
      }else{ 
       mainMoviesView.setAdapter(new MoviesAdapter(movies,MainActivity.this)); 
      } 
     } 

     @Override 
     public void onFailure(Call<Response> call, Throwable t) { 
      Log.e(TAG,t.toString()); 
     } 
    }); 


} 



@Override 
protected void onResume() { 
    super.onResume(); 
    // register connection status listener 
    MyApplication.getInstance().setConnectivityListener(this); 

} 

@Override 
public void onNetworkConnectionChanged(boolean isConnected) { 
    if(isConnected) 
    { 
     getDataFromServer(page); 

    }else{ 
     progressBar.setVisibility(View.INVISIBLE); 
     noInternetLayout.setVisibility(View.VISIBLE); 
    } 
}} 

我在哪里出了错?

回答

1

哥们, 你每次赋予新的价值你打电话,
看这句话 -

List<Movies> movies = response.body().getMovies(); 

您必须添加元素融入到数据集,

movies.addAll(response.body().getMovies()); 
0

这条线一直用新数据初始化您的视图

mainMoviesView.setAdapter(new MoviesAdapter(movies,MainActivity.this)); 

它会在onCreate(),onCreateView()或其他初始化方法。

MoviesAdapter moviesAdapter = new MoviesAdapter(movies,MainActivity.this); 
mainMoviesView.setAdapter(moviesAdepter); 

然后你的新呼叫入队。

call.enqueue(new Callback<Response>() { 
    @Override 
    public void onResponse(Call<Response> call, retrofit2.Response<Response> response) { 
     movies.addAll(response.body().getMovies()); // this line updated your movies list. 
     progressBar.setVisibility(View.INVISIBLE); 
     if(movies.size() == 0) 
     { 
      no_data_tv.setVisibility(View.VISIBLE); 
     }else{ 
      moviesAdapter.notifyDataSetChanged(); // this new line. 
     } 
    } 

    @Override 
    public void onFailure(Call<Response> call, Throwable t) { 
     Log.e(TAG,t.toString()); 
    } 
}); 
+0

这将工作,但由于列表电影是在我们设置适配器的初始点为空,不会返回空点异常吗? –

+0

setAdapter总是在初始化方法中。它可以onCreate,onCreateView,甚至onResume()。 setAdapter()总是初始化你的适配器。你可以在你的适配器上检查onCreateView()中的空元素。 – Kaloglu

+0

@SriramR没有它不会,因为你将初始化列表 列表 model = new ArrayList <>(); – MadScientist