在基本适配器中滚动后,TextView 值变回以前的值
TextView value changes back to previous value after scroll in base adapter
我一直在研究这个问题,但找不到解决方案。关于我的自定义列表视图的所有内容似乎都正常运行。当我单击 holder.feedUpVoteButton
时,文本会正确更改 +=1
。但是,当我向下滚动并向上滚动时,文本值将恢复为单击之前的值。
我拒绝使用 notifyDatasetChanged
因为我不会添加任何内容或从列表中删除任何内容。
public class CustomFeedListViewAdapter extends BaseAdapter{
CustomFeedListViewAdapter customFeedListViewAdapter;
Date createdAt, currentDate; int num;
static HashMap<String, String> oneData = new HashMap<String, String>();
HashMap<String, String> iFeed = new HashMap<>();
private String likesString;
String upVoteClicked, downVoteClicked;
HashMap<String, String> mFeed = new HashMap<>();
List<ParseObject> mObjects;
private ParseObject parseObFeed;
CustomFeedListViewAdapter(Context context, ArrayList<HashMap<String, String>> data) {
super();
this.mContext = context;
GlobalFeedTab.arrayFeedList = data;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return GlobalFeedTab.arrayFeedList.size();
}
@Override
public Object getItem(int i) {
return GlobalFeedTab.arrayFeedList.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
likes = new int[GlobalFeedTab.arrayFeedList.size()];
countryNames = new int[GlobalFeedTab.arrayFeedList.size()];
dateNames = new String[GlobalFeedTab.arrayFeedList.size()];
final ViewHolder holder;
if (view == null) {
position = i;
view = inflater.inflate(R.layout.feed_list_row, viewGroup, false);
holder = new ViewHolder();
holder.feedNumOfLikes = (TextView) view.findViewById(R.id.feedNumofLikes);
holder.feedUpVoteButton = (Button) view.findViewById(R.id.feedUpVoteButton);
} else {
position = i;
holder = (ViewHolder) view.getTag();
}
mFeed = GlobalFeedTab.arrayFeedList.get(position);
holder.feedNumOfLikes.setText(mFeed.get("likes"));
likesString = mFeed.get("likes");
likes[position] = Integer.valueOf(likesString);
holder.feedUpVoteButton.setTag(position);
ParseQuery<ParseObject> query2 = new ParseQuery<ParseObject>("FeedItem");
query2.setLimit(250);
query2.addDescendingOrder("createdAt");
query2.findInBackground(new FindCallback<ParseObject>() {
@Override
public void done(final List<ParseObject> objects, ParseException e) {
if (e == null) {
for ( final ParseObject object : objects) {
holder.feedUpVoteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = (Integer) v.getTag();
parseObFeed = objects.get(pos);
username = parseObFeed.getString("username");
createdAt = parseObFeed.getDate("createdAt");
likes[pos] += 1;
parseObFeed.put("likes", likes[pos]);
holder.feedNumOfLikes.setText(String.valueOf(parseObFeed.getInt("likes")));
parseObFeed.put(ParseUser.getCurrentUser().getUsername() + "upvoteClicked", true);
parseObFeed.saveInBackground();
}
});
}
});
return view;
}
private class ViewHolder {
ImageView feedProfilePic;
TextView feedUsername;
TextView feedNumOfLikes;
TextView feedFeedItem;
TextView feedDate;
TextView feedNumofReplies;
Button feedUpVoteButton;
Button feedDownVoteButton;
Button feedCommentButton;
ListView feedListView;
}
}
实际上这就是整个 theory.When 你递增一个 value.You 必须递增列表中你从那里获取 data.Because 的值当你向下滚动时,上面的行将 lost.When 你向上滚动,列表将从列表中再次加载 values.So 你所要做的就是增加列表中的值,即 GlobalFeedTab.arrayFeedList
link 是为了进一步的细节,对于任何寻找更多细节的人
当你写这行时
likes[pos] += 1;
您还必须增加您的 arraylist(mFeed) 中的值,然后编写 notifyDataSetChanged();
每次 getView
被调用,你重新制作
likes = new int[GlobalFeedTab.arrayFeedList.size()];
这不会在您滚动时保存,您单击的行离开并重新进入显示。持有者可以持有这个整数值。
private class ViewHolder {
int likes;
TextView feedNumOfLikes;
}
并相应更新
holder.feedUpVoteButton
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.feedNumOfLikes.setText(String.valueOf(++holder.likes));
但是,您还需要更新解析对象。
parseObFeed.put("likes", holder.likes);
parseObFeed.saveInBackground();
// notifyDataSetChanged(); // Up to you. Might not work without
I refuse to use notifyDatasetChanged
because I am not adding anything or removing anything from the list.
不过,您正在修改 数据。调用它将使您的适配器数据与存储在 Parse Server 中的数据一致。
编辑
这变得很复杂,因为您要让每个 "row" 都有一些 "nested" 与之关联的对象列表。我想您可以将整个列表存储在容器中。
private class ViewHolder {
// Java variables to hold onto
int likes;
List<ParseObject> feedItems = new ArrayList<ParseObject>();
// Android views to bind those values to
TextView feedNumOfLikes;
}
在适配器内部时,您调用 Parse 以获取适配器中每个项目的次级列表,但您只需将其存储在容器中。当 query2 returns 时,不要用它做任何其他事情。
你真正的问题是不清楚 query2
甚至返回了什么。当然,这是一些数据列表,但您真的想在列表中显示列表吗?此外,适配器的每个项目都从 Parse 查询完全相同的数据。我认为您需要一个过滤器...然后,您的 position
变量在 GlobalFeedTab.arrayFeedList
和 List<ParseObject>
之间不对应,因为它们是不同的列表。
这里只是我可以指出的一些评论。
else {
holder = (ViewHolder) view.getTag();
}
// You don't need 'position', it is just the 'i' value...
mFeed = GlobalFeedTab.arrayFeedList.get(i);
// This is stored in the Activity, I guess?
likesString = mFeed.get("likes");
holder.feedNumOfLikes.setText(likesString);
holder.feedUpVoteButton.setTag(i);
ParseQuery<ParseObject> query2 = new ParseQuery<ParseObject>("FeedItem");
// This is getting some related "FeedItem" for the current row
// Just store the info, don't do anything with it yet
query2.findInBackground(new FindCallback<ParseObject>() {
@Override
public void done(final List<ParseObject> objects, ParseException e) {
if (e == null) {
holder.feedItems.clear();
holder.feedItems.addAll(objects);
notifyDataSetChanged();
}
}
};
// Here, you can setup the button for the current row
holder.feedUpVoteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = (Integer) v.getTag();
// This is wrong... 'pos' is the position of the adapter! Not the index of List<ParseObject> results from earlier
// And this is a very clear ArrayIndexOutOfBounds error...
// The adapter could be shorter/longer than the holder.feedItems
parseObFeed = holder.feedItems.get(pos);
// !! TODO: Figure out which parseObFeed you actually want to use here
username = parseObFeed.getString("username");
createdAt = parseObFeed.getDate("createdAt");
holder.likes++;
parseObFeed.put("likes", holder.likes);
// This is the value that "resets" when you scroll.
// parseObFeed has not yet been saved, so when you scroll, the data isn't changed.
holder.feedNumOfLikes
.setText(String.valueOf(parseObFeed.getInt("likes")));
// Not really sure what this does - You can store an array of likes rather than one field per username
parseObFeed.put(ParseUser.getCurrentUser().getUsername() + "upvoteClicked", true);
parseObFeed.saveInBackground();
notifyDataSetChanged();
}
});
}
我不记得 saveInBackground 是否有回调,但这可能需要调查
经过不断的试错。我终于想出了如何在滚动后更改文本视图。我的问题是我得到了错误的 ParseObject
值。我的主 activity 包含一个 ParseQuery
并且我从 Hashmap();
得到 likes
但是,由于某种原因我无法直接传递 likes 的值所以我传递了ParseObject 本身。因此,在我的 BaseAdapter
Class 中不需要查询。然后,我在 GetView();
中实现了这些代码行来回答我原来的问题:
holder.upvote[position] = holder.parseObList[position].getBoolean(ParseUser.getCurrentUser().getUsername() + "upvoteClicked");
holder.downvote[position] = holder.parseObList[position].getBoolean(ParseUser.getCurrentUser().getUsername() + "downvoteClicked");
if(holder.upvote[position] ){
holder.feedUpVoteButton.setBackgroundResource(R.drawable.arrowclicked);
holder.feedNumOfLikes.setText(String.valueOf(holder.likes[position]));
}
else if(!holder.upvote[position]){
holder.feedUpVoteButton.setBackgroundResource(R.drawable.arrowunclicked);
holder.feedNumOfLikes.setText(String.valueOf(holder.likes[position]));
}
if(holder.downvote[position]){
holder.feedDownVoteButton.setBackgroundResource(R.drawable.arrowclicked);
}
else if(!holder.downvote[position]){
holder.feedDownVoteButton.setBackgroundResource(R.drawable.arrowunclicked);
}
我一直在研究这个问题,但找不到解决方案。关于我的自定义列表视图的所有内容似乎都正常运行。当我单击 holder.feedUpVoteButton
时,文本会正确更改 +=1
。但是,当我向下滚动并向上滚动时,文本值将恢复为单击之前的值。
我拒绝使用 notifyDatasetChanged
因为我不会添加任何内容或从列表中删除任何内容。
public class CustomFeedListViewAdapter extends BaseAdapter{
CustomFeedListViewAdapter customFeedListViewAdapter;
Date createdAt, currentDate; int num;
static HashMap<String, String> oneData = new HashMap<String, String>();
HashMap<String, String> iFeed = new HashMap<>();
private String likesString;
String upVoteClicked, downVoteClicked;
HashMap<String, String> mFeed = new HashMap<>();
List<ParseObject> mObjects;
private ParseObject parseObFeed;
CustomFeedListViewAdapter(Context context, ArrayList<HashMap<String, String>> data) {
super();
this.mContext = context;
GlobalFeedTab.arrayFeedList = data;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return GlobalFeedTab.arrayFeedList.size();
}
@Override
public Object getItem(int i) {
return GlobalFeedTab.arrayFeedList.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
likes = new int[GlobalFeedTab.arrayFeedList.size()];
countryNames = new int[GlobalFeedTab.arrayFeedList.size()];
dateNames = new String[GlobalFeedTab.arrayFeedList.size()];
final ViewHolder holder;
if (view == null) {
position = i;
view = inflater.inflate(R.layout.feed_list_row, viewGroup, false);
holder = new ViewHolder();
holder.feedNumOfLikes = (TextView) view.findViewById(R.id.feedNumofLikes);
holder.feedUpVoteButton = (Button) view.findViewById(R.id.feedUpVoteButton);
} else {
position = i;
holder = (ViewHolder) view.getTag();
}
mFeed = GlobalFeedTab.arrayFeedList.get(position);
holder.feedNumOfLikes.setText(mFeed.get("likes"));
likesString = mFeed.get("likes");
likes[position] = Integer.valueOf(likesString);
holder.feedUpVoteButton.setTag(position);
ParseQuery<ParseObject> query2 = new ParseQuery<ParseObject>("FeedItem");
query2.setLimit(250);
query2.addDescendingOrder("createdAt");
query2.findInBackground(new FindCallback<ParseObject>() {
@Override
public void done(final List<ParseObject> objects, ParseException e) {
if (e == null) {
for ( final ParseObject object : objects) {
holder.feedUpVoteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = (Integer) v.getTag();
parseObFeed = objects.get(pos);
username = parseObFeed.getString("username");
createdAt = parseObFeed.getDate("createdAt");
likes[pos] += 1;
parseObFeed.put("likes", likes[pos]);
holder.feedNumOfLikes.setText(String.valueOf(parseObFeed.getInt("likes")));
parseObFeed.put(ParseUser.getCurrentUser().getUsername() + "upvoteClicked", true);
parseObFeed.saveInBackground();
}
});
}
});
return view;
}
private class ViewHolder {
ImageView feedProfilePic;
TextView feedUsername;
TextView feedNumOfLikes;
TextView feedFeedItem;
TextView feedDate;
TextView feedNumofReplies;
Button feedUpVoteButton;
Button feedDownVoteButton;
Button feedCommentButton;
ListView feedListView;
}
}
实际上这就是整个 theory.When 你递增一个 value.You 必须递增列表中你从那里获取 data.Because 的值当你向下滚动时,上面的行将 lost.When 你向上滚动,列表将从列表中再次加载 values.So 你所要做的就是增加列表中的值,即 GlobalFeedTab.arrayFeedList
likes[pos] += 1;
您还必须增加您的 arraylist(mFeed) 中的值,然后编写 notifyDataSetChanged();
每次 getView
被调用,你重新制作
likes = new int[GlobalFeedTab.arrayFeedList.size()];
这不会在您滚动时保存,您单击的行离开并重新进入显示。持有者可以持有这个整数值。
private class ViewHolder {
int likes;
TextView feedNumOfLikes;
}
并相应更新
holder.feedUpVoteButton
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.feedNumOfLikes.setText(String.valueOf(++holder.likes));
但是,您还需要更新解析对象。
parseObFeed.put("likes", holder.likes);
parseObFeed.saveInBackground();
// notifyDataSetChanged(); // Up to you. Might not work without
I refuse to use
notifyDatasetChanged
because I am not adding anything or removing anything from the list.
不过,您正在修改 数据。调用它将使您的适配器数据与存储在 Parse Server 中的数据一致。
编辑
这变得很复杂,因为您要让每个 "row" 都有一些 "nested" 与之关联的对象列表。我想您可以将整个列表存储在容器中。
private class ViewHolder {
// Java variables to hold onto
int likes;
List<ParseObject> feedItems = new ArrayList<ParseObject>();
// Android views to bind those values to
TextView feedNumOfLikes;
}
在适配器内部时,您调用 Parse 以获取适配器中每个项目的次级列表,但您只需将其存储在容器中。当 query2 returns 时,不要用它做任何其他事情。
你真正的问题是不清楚 query2
甚至返回了什么。当然,这是一些数据列表,但您真的想在列表中显示列表吗?此外,适配器的每个项目都从 Parse 查询完全相同的数据。我认为您需要一个过滤器...然后,您的 position
变量在 GlobalFeedTab.arrayFeedList
和 List<ParseObject>
之间不对应,因为它们是不同的列表。
这里只是我可以指出的一些评论。
else {
holder = (ViewHolder) view.getTag();
}
// You don't need 'position', it is just the 'i' value...
mFeed = GlobalFeedTab.arrayFeedList.get(i);
// This is stored in the Activity, I guess?
likesString = mFeed.get("likes");
holder.feedNumOfLikes.setText(likesString);
holder.feedUpVoteButton.setTag(i);
ParseQuery<ParseObject> query2 = new ParseQuery<ParseObject>("FeedItem");
// This is getting some related "FeedItem" for the current row
// Just store the info, don't do anything with it yet
query2.findInBackground(new FindCallback<ParseObject>() {
@Override
public void done(final List<ParseObject> objects, ParseException e) {
if (e == null) {
holder.feedItems.clear();
holder.feedItems.addAll(objects);
notifyDataSetChanged();
}
}
};
// Here, you can setup the button for the current row
holder.feedUpVoteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = (Integer) v.getTag();
// This is wrong... 'pos' is the position of the adapter! Not the index of List<ParseObject> results from earlier
// And this is a very clear ArrayIndexOutOfBounds error...
// The adapter could be shorter/longer than the holder.feedItems
parseObFeed = holder.feedItems.get(pos);
// !! TODO: Figure out which parseObFeed you actually want to use here
username = parseObFeed.getString("username");
createdAt = parseObFeed.getDate("createdAt");
holder.likes++;
parseObFeed.put("likes", holder.likes);
// This is the value that "resets" when you scroll.
// parseObFeed has not yet been saved, so when you scroll, the data isn't changed.
holder.feedNumOfLikes
.setText(String.valueOf(parseObFeed.getInt("likes")));
// Not really sure what this does - You can store an array of likes rather than one field per username
parseObFeed.put(ParseUser.getCurrentUser().getUsername() + "upvoteClicked", true);
parseObFeed.saveInBackground();
notifyDataSetChanged();
}
});
}
我不记得 saveInBackground 是否有回调,但这可能需要调查
经过不断的试错。我终于想出了如何在滚动后更改文本视图。我的问题是我得到了错误的 ParseObject
值。我的主 activity 包含一个 ParseQuery
并且我从 Hashmap();
得到 likes
但是,由于某种原因我无法直接传递 likes 的值所以我传递了ParseObject 本身。因此,在我的 BaseAdapter
Class 中不需要查询。然后,我在 GetView();
中实现了这些代码行来回答我原来的问题:
holder.upvote[position] = holder.parseObList[position].getBoolean(ParseUser.getCurrentUser().getUsername() + "upvoteClicked");
holder.downvote[position] = holder.parseObList[position].getBoolean(ParseUser.getCurrentUser().getUsername() + "downvoteClicked");
if(holder.upvote[position] ){
holder.feedUpVoteButton.setBackgroundResource(R.drawable.arrowclicked);
holder.feedNumOfLikes.setText(String.valueOf(holder.likes[position]));
}
else if(!holder.upvote[position]){
holder.feedUpVoteButton.setBackgroundResource(R.drawable.arrowunclicked);
holder.feedNumOfLikes.setText(String.valueOf(holder.likes[position]));
}
if(holder.downvote[position]){
holder.feedDownVoteButton.setBackgroundResource(R.drawable.arrowclicked);
}
else if(!holder.downvote[position]){
holder.feedDownVoteButton.setBackgroundResource(R.drawable.arrowunclicked);
}