RecyclerView onScrolled 方法总是或从不调用
Posted
技术标签:
【中文标题】RecyclerView onScrolled 方法总是或从不调用【英文标题】:RecyclerView onScrolled method always or never called 【发布时间】:2020-09-25 13:16:50 【问题描述】:背景: 我通过添加 addOnScrollListener 函数使用 RecyclerView 实现分页逻辑。我正在使用 MVVM 模式 (https://developer.android.com/jetpack/docs/guide)。我的目标是使用 GridLayoutManager 在 GridLayout 中显示通过 API 调用 TheMovieDB 产生的电影。
面临的问题: 滚动方法总是或从不被调用:
1) 我什至不需要滚动来触发它。
2)当我启动应用程序时它会触发,但是当我滚动它时它根本不会触发
这是我的代码
public void getMoviesLL(String categoria, int pagina, MutableLiveData < Resource < List < Movie >>> moviesData)
Service apiService = Client.getClient().create(Service.class);
Call < MoviesResponse > call;
Log.d(TAG, "CHIAMATA " + pagina);
call = apiService.getTMDB(categoria, Constants.API_KEY, Constants.LINGUA, pagina);
call.enqueue(new Callback < MoviesResponse > ()
@Override
public void onResponse(@NonNull Call < MoviesResponse > call, @NonNull Response < MoviesResponse > response)
if (response.isSuccessful() && response.body() != null)
Resource < List < Movie >> resource = new Resource < >();
if (moviesData.getValue() != null && moviesData.getValue().getData() != null)
List < Movie > currentMovieList = moviesData.getValue().getData();
currentMovieList.remove(currentMovieList.size() - 1);
currentMovieList.addAll(response.body().getResults());
resource.setData(currentMovieList);
else
resource.setData(response.body().getResults());
resource.setTotalResults(response.body().getTotalResults());
resource.setStatusCode(response.code());
resource.setStatusMessage(response.message());
resource.setLoading(false);
Log.d(TAG, "LOADING FALSE");
moviesData.postValue(resource);
else if (response.errorBody() != null)
Resource < List < Movie >> resource = new Resource < >();
resource.setStatusCode(response.code());
try
resource.setStatusMessage(response.errorBody().string() + "- " + response.message());
catch(IOException e)
e.printStackTrace();
moviesData.postValue(resource);
@Override
public void onFailure(@NonNull Call < MoviesResponse > call, @NonNull Throwable t)
Resource < List < Movie >> resource = new Resource < >();
resource.setStatusMessage(t.getMessage());
moviesData.postValue(resource);
);
这是模型
public class Resource<T>
private T data;
private int totalResults;
private int statusCode;
private String statusMessage;
private boolean isLoading;
public Resource()
public Resource(T data, int totalResults, int statusCode, String statusMessage, boolean isLoading)
this.data = data;
this.totalResults = totalResults;
this.statusCode = statusCode;
this.statusMessage = statusMessage;
this.isLoading = isLoading;
public T getData()
return data;
public void setData(T data)
this.data = data;
public int getTotalResults()
return totalResults;
public void setTotalResults(int totalResults)
this.totalResults = totalResults;
public int getStatusCode()
return statusCode;
public void setStatusCode(int statusCode)
this.statusCode = statusCode;
public String getStatusMessage()
return statusMessage;
public void setStatusMessage(String statusMessage)
this.statusMessage = statusMessage;
public boolean isLoading()
return isLoading;
public void setLoading(boolean loading)
isLoading = loading;
@Override
public String toString()
return "Resource" +
"data=" + data +
", totalResults=" + totalResults +
", statusCode=" + statusCode +
", statusMessage='" + statusMessage + '\'' +
", isLoading=" + isLoading +
'';
查看模型类
public class NuoviArriviViewModel extends ViewModel
private static final String TAG = "NuoviArriviViewModel";
private MutableLiveData<Resource<List<Movie>>> film;
int page = 1;
private int currentResults;
private boolean isLoading = false;
public MutableLiveData<Resource<List<Movie>>> getProssimeUscite()
if(film == null)
film = new MutableLiveData<>();
MoviesRepository.getInstance().getMoviesLL("now_playing", page, film);
return film;
public MutableLiveData<Resource<List<Movie>>> getMoreProssimeUscite()
MoviesRepository.getInstance().getMoviesLL("now_playing", page, film);
return film;
public MutableLiveData<Resource<List<Movie>>> getMoviesLiveData()
return film;
public int getPage()
return page;
public void setPage(int page)
this.page = page;
public int getCurrentResults()
return currentResults;
public void setCurrentResults(int currentResults)
this.currentResults = currentResults;
public boolean isLoading()
return isLoading;
public void setLoading(boolean loading)
isLoading = loading;
OnScroll 监听器
prossimeUsciteRV.addOnScrollListener(new RecyclerView.OnScrollListener()
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy)
super.onScrolled(recyclerView, dx, dy);
Log.d(TAG, "entro in onScrolled");
totalItemCount = layoutManager.getItemCount();
lastVisibleItem = layoutManager.findLastVisibleItemPosition();
visibleItemCount = layoutManager.getChildCount();
// Condition to enable the loading of other news while the user scrolls the list
if (totalItemCount == visibleItemCount || (totalItemCount <= (lastVisibleItem + threshold) && dy > 0 && !nuoviArriviViewModel.isLoading()) && nuoviArriviViewModel.getMoviesLiveData().getValue() != null && nuoviArriviViewModel.getCurrentResults() != nuoviArriviViewModel.getMoviesLiveData().getValue().getTotalResults())
Resource < List < Movie >> movieListResource = new Resource < >();
MutableLiveData < Resource < List < Movie >>> movieListMutableLiveData = nuoviArriviViewModel.getMoviesLiveData();
if (movieListMutableLiveData.getValue() != null)
nuoviArriviViewModel.setLoading(true);
List < Movie > currentMovieList = movieListMutableLiveData.getValue().getData();
// It adds a null element to enable the visualization of the loading item (it is managed by the class nuoviArriviAdapter)
currentMovieList.add(null);
movieListResource.setData(currentMovieList);
movieListResource.setStatusMessage(movieListMutableLiveData.getValue().getStatusMessage());
movieListResource.setTotalResults(movieListMutableLiveData.getValue().getTotalResults());
movieListResource.setStatusCode(movieListMutableLiveData.getValue().getStatusCode());
movieListResource.setLoading(true);
movieListMutableLiveData.postValue(movieListResource);
int page = nuoviArriviViewModel.getPage() + 1;
nuoviArriviViewModel.setPage(page);
nuoviArriviViewModel.loadMore();
);
XML 文件
<?xml version="1.0" encoding="utf-8"?>
<GridLayout
android:layout_
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nuovi_arrivi_fragment"
android:layout_
android:background="@color/colorPrimary"
android:orientation="vertical"
tools:context=".ui.nuovi_arrivi.NuoviArriviFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_nuovi_arrivi"
android:layout_
android:layout_
android:orientation="vertical" />
</GridLayout>
【问题讨论】:
【参考方案1】:问题是我将布局包裹在 NestedScrollView 中,因此无法正确触发 onScrolled 事件
【讨论】:
以上是关于RecyclerView onScrolled 方法总是或从不调用的主要内容,如果未能解决你的问题,请参考以下文章
在 RecyclerView/ListView onScroll 上隐藏 ActionBar
Android Recyclerview 监听滑动状态和滑动距离