【发布时间】:2015-11-11 16:49:50
【问题描述】:
我创建了一个无休止的列表来处理来自 API 的分页,我以 JSON 格式获取下一页数据并将其解析为我的活动。但是,我的适配器没有更新新项目。我已经调用了 notifyDataSetChanged 并且它没有更新。知道我做错了什么吗?下面是我的代码:
private void loadData(final boolean firstLoad) {
mDataFactory.getPostFeed(mThreads.getId(), mCurrentPage, new PostFeedDataFactory.PostFeedDataFactoryCallback() {
@Override
public void onPostDataReceived(PostResponse response) {
mData = response;
if (mData.getItems() != null) {
for (int i = 0; i < mData.getItems().size(); i++) {
Posts singlePost = response.getItems().get(i);
postList.add(singlePost);
}
if (firstLoad) {
mIsLoading = false;
mData.getItems().clear();
mData.getItems().addAll(postList);
mEmoticonDataFactory.getEmoticonFeed(new EmoticonFeedDataFactory.EmoticonFeedDataFactoryCallback() {
@Override
public void onEmoticonDataReceived(EmoticonResponse response) {
mEmoticon = response;
populateUIWithData();
}
@Override
public void onEmoticonDataFailed(Exception exception) {
}
});
} else {
mIsLoading = false;
refreshPosts(postList);
}
if (mData.getItems().size() > 0) {
if (Integer.valueOf(mData.getTotalPosts()) >= response.getItems().size()) {
mCurrentPage++;
} else {
mIsLastPage = true;
}
}
}
}
@Override
public void onPostDataFailed(Exception exception) {
}
});
}
private void populateUIWithData() {
mThreadText = (TextView) findViewById(R.id.threadText);
if (mThreads != null) {
if (mThreads.getName() != null) {
mThreadText.setText(mThreads.getName());
}
}
if (mAdapter == null){
mAdapter = new PostAdapter(this, mData, mEmoticon);
mRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.setData(postList);
mAdapter.notifyDataSetChanged();
}
mRecyclerView.addOnScrollListener(paginationListener);
}
private RecyclerView.OnScrollListener paginationListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();
if (!mIsLoading && !mIsLastPage) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount) {
loadMoreItems();
}
}
}
};
private void loadMoreItems() {
mIsLoading = true;
loadData(false);
}
private void refreshPosts(ArrayList<Posts> newObjects) {
postList.addAll(newObjects);
populateUIWithData();
}
另外,这是我的适配器
PostAdapter.java
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Posts posts = mPost.getItem(position);
emoticons = mEmoticon.getItems();
String message = null;
String emoMessage = null;
if (posts.getPost() != null) {
if (posts.getPost().getMessage() != null) {
message = posts.getPost().getMessage();
emoMessage = message;
if (emoticons != null) {
for(Emoticons emoticon : this.emoticons) {
if (message.contains(emoticon.getEmoticon().getCode())) {
emoMessage = message.replaceAll(Constants.EMO_REGEX, emoticon.getEmoticon().getUrl());
}
}
}
}
if (posts.getPost().getUsername() != null) {
holder.mAuthorTextView.setText("Posted by: " + posts.getPost().getUsername());
}
if (posts.getPost().getHighlighting().equals("op")) {
holder.mPostTextView.setTypeface(Typeface.DEFAULT_BOLD);
}
}
holder.mPostTextView.setText(Html.fromHtml(emoMessage, new Html.ImageGetter() {
@Override
public Drawable getDrawable(String source) {
Drawable d = null;
try {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
URL url = new URL(source);
InputStream is = url.openStream();
Bitmap b = BitmapFactory.decodeStream(is);
d = new BitmapDrawable(Resources.getSystem(), b);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
} catch (IOException e) {
e.printStackTrace();
}
return d;
}
}, new Html.TagHandler() {
@Override
public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
if(tag.equalsIgnoreCase("strike") || tag.equals("s")) {
processStrike(opening, output);
}
}
private void processStrike(boolean opening, Editable output) {
int len = output.length();
if(opening) {
output.setSpan(new StrikethroughSpan(), len, len, Spannable.SPAN_MARK_MARK);
} else {
Object obj = getLast(output, StrikethroughSpan.class);
int where = output.getSpanStart(obj);
output.removeSpan(obj);
if (where != len) {
output.setSpan(new StrikethroughSpan(), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
private Object getLast(Editable text, Class kind) {
Object[] objs = text.getSpans(0, text.length(), kind);
if (objs.length == 0) {
return null;
} else {
for(int i = objs.length;i>0;i--) {
if(text.getSpanFlags(objs[i-1]) == Spannable.SPAN_MARK_MARK) {
return objs[i-1];
}
}
return null;
}
}
}));
}
@Override
public int getItemCount() {
return mPost.getItems().size();
}
public void setData(ArrayList<Posts> array) {
ArrayList<Posts> postList = this.mPost.getItems();
postList = array;
}
【问题讨论】:
-
我在我的智能手机上,所以无法掌握您的所有代码,但是您是否考虑过 RecycleView 扩展之一,例如 SuperRecycleView 或 UltimateRecycleView?它们具有内置功能,可以在用户滚动时加载更多结果
-
不,我不知道他们甚至存在。我尝试了 EndlessRecyclerAdapter 并将我的适配器连接到它,但这似乎也不起作用@cYrixmorten
-
我建议您将代码 sn-p 精简为一个最小、完整且可验证的示例 (stackoverflow.com/help/mcve) - 这将有助于专注于相关部分
-
@AdamMichalik 啊,好吧,我一回到我的机器上就会这样做。感谢您的提示
-
好的,再次查看您的代码并有一些 cmets 1)
mIsLoading永远不会设置为 false 2) 我不相信((visibleItemCount + firstVisibleItemPosition) >= totalItemCount)是您的情况的有效条件,只是想要您确保它在您期望的时候被调用 3) 不确定这个,但是refreshPosts将帖子添加到mData,这是一个由您的 Activity 持有的列表 .. 我使用的 RecyclerAdapters 在内部保存数据,所以我有点担心它是否能够检测到mData的变化。第一次加载直接将数据交给populateUIWithData()
标签: android pagination android-recyclerview