我正在构建一个简单的IMDB应用程序,除了一个小细节,我差不多完成了。 API(http://www.omdbapi.com/)一次只提供10部电影,用户可以指定他们想要的“页面”。我想检索所有条目。我的代码看起来像这样:
//This populates the list
private void populateList(String title) {
myAPI.getSearchResults(title, page).enqueue(new Callback<Movies>() {
@Override
public void onResponse(Call<Movies> call, Response<Movies> response) {
movies = response.body().getSearch();
recyclerView.setAdapter(new ItemAdapter(movies));
recyclerView.addOnItemTouchListener(
new ItemClickableListener(getActivity(), new ItemClickableListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
String id = movies.get(position).getImdbID();
showDetails(id, view);
}
}));
}
@Override
public void onFailure(Call<Movies> call, Throwable t) {
Log.d(TAG, "Error: " + t);
}
});
}
在我的界面中:
//For populating the list
@GET("?")
Call<Movies> getSearchResults(@Query("s") String title, @Query("page") int pages);
有一种方法可以知道总共有多少条目,但查询必须至少运行一次才能检索该信息。我尝试用“do ... while”循环修复它,然后将每个连续批次的电影添加到列表中,然后只填充RecyclerView但它不起作用(它会在没有显示内容的情况下离开循环)。也许我忽略了一些东西,这是正确答案,但即便如此 - 难道没有更优雅的方法吗?
答案 0 :(得分:1)
我认为您需要EndlessRecyclerView才能检索10到10页。使用以下代码:
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mAdapter = new MyAdapter(getActivity(), this);
scrollListener = new EndlessRecyclerOnScrollListener((LinearLayoutManager) mRecyclerView.getLayoutManager()) {
@Override
public void onLoadMore(int page) {
callWebservice(page);
}
};
mRecyclerView.addOnScrollListener(scrollListener);
mRecyclerView.setAdapter(mAdapter);
完成callWebservice
后,将项目添加到列表中:
@Override
public void onResponse(Call<List<ShortVideoModel>> call, Response<List<ShortVideoModel>> response) {
mAdapter.addItems(response.body());
}
答案 1 :(得分:0)
我最终查看了EndlessRecyclerView,它的工作方式几乎完美,但我遇到了一些问题,所以我在这里发布代码。它保持堆叠监听器和适配器,所以我交换它们。每次插入数据时它也会不断向上滚动,所以我强迫它停留但是它有点紧张。
public class SearchFragment extends Fragment {
final String TAG = "LOG.SearchFragment";
final String baseUrl = "http://www.omdbapi.com/";
Button searchButton;
EditText searchField;
RecyclerView recyclerView;
LinearLayoutManager llm;
String title = "";
int page = 1;
List<Search> movies;
Gson gson;
Retrofit retrofit;
MyAPI myAPI;
ItemClickableListener listener;
EndlessRecyclerOnScrollListener scrollListener;
int firstItem;
float topOffset;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "Starting SearchFragment...");
return inflater.inflate(R.layout.search_fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//Preparing RecyclerView
recyclerView = (RecyclerView) getActivity().findViewById(R.id.recycler_view);
llm = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(llm);
setOnScrollManager();
//List for the movies
movies = new ArrayList<>();
//UI
searchField = (EditText) getActivity().findViewById(R.id.search_field);
searchButton = (Button) getActivity().findViewById(R.id.search_button);
searchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!searchField.getText().toString().equals("")) {
gson = new GsonBuilder().create();
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
myAPI = retrofit.create(MyAPI.class);
title = searchField.getText().toString();
movies.clear();
page=1;
setOnScrollManager();
fetchMovies(title, page);
}
}
});
}
private void setOnScrollManager() {
if (scrollListener!=null) recyclerView.removeOnScrollListener(scrollListener);
scrollListener = new EndlessRecyclerOnScrollListener((LinearLayoutManager) recyclerView.getLayoutManager()) {
//This happens when user scrolls to bottom
@Override
public void onLoadMore(int newPage) {
Log.d(TAG, "OnLoadMore "+newPage);
//Preparing the scroll
firstItem = llm.findFirstVisibleItemPosition();
View firstItemView = llm.findViewByPosition(firstItem);
topOffset = firstItemView.getTop();
//Getting new page
page=newPage;
fetchMovies(title, page);
}
};
recyclerView.addOnScrollListener(scrollListener);
}
//This populates the list
private void fetchMovies(String title, int page) {
Log.d(TAG, "Getting "+title+", page "+page);
myAPI.getSearchResults(title, page).enqueue(new Callback<Movies>() {
@Override
public void onResponse(Call<Movies> call, Response<Movies> response) {
if (movies.size()==0) Toast.makeText(getActivity(), "No movies found", Toast.LENGTH_SHORT).show();
movies.addAll(response.body().getSearch());
//We swap the adatper's content when user scrolls down and loads more data
recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
recyclerView.swapAdapter(new ItemAdapter(movies), true);
//Scrolling
Log.d(TAG, "Scrolling to "+firstItem);
llm.scrollToPositionWithOffset(firstItem, (int) topOffset);
//We avoid stacking up listeners
if (listener!=null) recyclerView.removeOnItemTouchListener(listener);
listener = new ItemClickableListener(getActivity(), new ItemClickableListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
String id = movies.get(position).getImdbID();
showDetails(id, view);
}
});
recyclerView.addOnItemTouchListener(listener);
}
@Override
public void onFailure(Call<Movies> call, Throwable t) {
Log.d(TAG, "Error: " + t);
}
});
}
//This gets the movie details
private void showDetails(String id, final View view){
myAPI.getDetails(id).enqueue(new Callback<MovieDetails>() {
@Override
public void onResponse(Call<MovieDetails> call, Response<MovieDetails> response) {
showPopup(response.body(), view);
}
@Override
public void onFailure(Call<MovieDetails> call, Throwable t) {
Log.d(TAG, "Error: " + t);
}
});
}
//This displays the movie details
private void showPopup(MovieDetails details, View anchorView) {
View popupView = getActivity().getLayoutInflater().inflate(R.layout.popup_layout, null);
PopupWindow popupWindow = new PopupWindow(popupView,
RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT);
TextView title = (TextView) popupView.findViewById(R.id.movie_detail_title);
TextView year = (TextView) popupView.findViewById(R.id.movie_detail_year);
TextView rating = (TextView) popupView.findViewById(R.id.movie_detail_rating);
TextView director = (TextView) popupView.findViewById(R.id.movie_detail_director);
TextView stars = (TextView) popupView.findViewById(R.id.movie_detail_stars);
TextView desc = (TextView) popupView.findViewById(R.id.movie_detail_desc);
title.setText(details.getTitle());
title.setTextColor(Color.parseColor("#ffffff"));
year.setText(details.getYear());
year.setTextColor(Color.parseColor("#ffffff"));
rating.setText(details.getImdbRating()+"/10");
rating.setTextColor(Color.parseColor("#ffffff"));
director.setText("Dir: "+details.getDirector());
director.setTextColor(Color.parseColor("#ffffff"));
stars.setText("Stars: "+details.getActors());
stars.setTextColor(Color.parseColor("#ffffff"));
desc.setText(details.getPlot());
desc.setTextColor(Color.parseColor("#ffffff"));
UrlValidator urlValidator = new UrlValidator();
if (urlValidator.isValid(details.getPoster())) {
ImageView poster = (ImageView) popupView.findViewById(R.id.movie_detail_poster);
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(details.getPoster(), poster);
}
// If the PopupWindow should be focusable
popupWindow.setFocusable(true);
// If you need the PopupWindow to dismiss when when touched outside
popupWindow.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#CC000000")));
int location[] = new int[2];
// Get the View's(the one that was clicked in the Fragment) location
anchorView.getLocationOnScreen(location);
// Using location, the PopupWindow will be displayed right under anchorView
popupWindow.showAtLocation(anchorView, Gravity.NO_GRAVITY,
location[0], location[1] + anchorView.getHeight());
}
}