以下是一个使用Android分页库、无限滚动RecyclerView和Retrofit的示例解决方案:
dependencies {
// Android分页库
implementation "androidx.paging:paging-runtime:2.1.2"
// Retrofit
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
// RecyclerView
implementation "androidx.recyclerview:recyclerview:1.2.0"
}
public class Movie {
private String title;
private String posterUrl;
// 构造函数、getter和setter方法省略
}
public interface MovieApi {
@GET("movies")
Call> getMovies(@Query("page") int page, @Query("limit") int limit);
}
public class MoviePagingSource extends PagingSource {
private MovieApi movieApi;
public MoviePagingSource(MovieApi movieApi) {
this.movieApi = movieApi;
}
@Override
public suspend LoadResult load(
LoadParams params
) {
try {
int page = params.getKey() ?: 1;
List movies = movieApi.getMovies(page, params.getLoadSize()).execute().body();
return LoadResult.Page(
data = movies,
prevKey = if (page == 1) null else page - 1,
nextKey = if (movies.isEmpty()) null else page + 1
);
} catch (IOException e) {
return LoadResult.Error(e);
}
}
}
public class MovieViewModel extends ViewModel {
private Pager pager;
public LiveData> movies;
public MovieViewModel() {
MovieApi movieApi = Retrofit.Builder()
.baseUrl("https://example.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(MovieApi.class);
pager = new Pager<>(
new PagingConfig(pageSize = 20),
() -> new MoviePagingSource(movieApi)
);
movies = pager.flow.asLiveData();
}
}
public class MovieActivity extends AppCompatActivity {
private MovieAdapter movieAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
movieAdapter = new MovieAdapter();
movieAdapter.addLoadStateListener(loadStates -> {
if (loadStates.getRefresh() instanceof LoadState.Loading) {
// 显示加载中状态
} else if (loadStates.getRefresh() instanceof LoadState.Error) {
// 显示加载错误状态
}
});
recyclerView.setAdapter(movieAdapter);
MovieViewModel movieViewModel = ViewModelProvider(this).get(MovieViewModel.class);
movieViewModel.movies.observe(this, pagingData -> {
movieAdapter.submitData(getLifecycle(), pagingData);
});
}
}
public class MovieAdapter extends PagingDataAdapter {
protected MovieAdapter() {
super(DIFF_CALLBACK);
}
@NonNull
@Override
public MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie, parent, false);
return new MovieViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MovieViewHolder holder, int position) {
Movie movie = getItem(position);
if (movie != null) {
holder.bind(movie);
}
}
static class MovieViewHolder extends RecyclerView.ViewHolder {