2017-03-04 56 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