Reputation: 2468
I am using on scroll to load more data and show them in list view but my ListView
first shows already loaded data then adds the newly added data to ListView
I have used for reference this and many others but unable to solve the issue
Here is my activity class
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_all);
ButterKnife.bind(this);
Users = Users.getCurrentUser(this);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
UIUtility.setStatusColor(this);
Intent intent = getIntent();
try {
entityData = new JSONArray(intent.getStringExtra(EXTRA_DATA));
} catch (JSONException e) {
e.printStackTrace();
}
viewAllCategory = intent.getIntExtra(EXTRA_CATEGORY, 0);
viewAllEntityType = intent.getIntExtra(EXTRA_TYPE, 0);
latitude = intent.getDoubleExtra(EXTRA_LATITUDE, 0);
longitude = intent.getDoubleExtra(EXTRA_LONGITUDE, 0);
setTitle(TITLES[viewAllCategory]);
if (viewAllEntityType == Constants.SMBEntityType.TYPE_USER) {
List<Users> users = Utility.convertJsonArrayToUsers(entityData);
adapterUser = new ViewAllUserAdapter(this, users);
lvEntity.setAdapter(adapterUser);
} else {
List<Book> books = Utility.convertJsonArrayToBook(entityData);
adapterBook = new ViewAllBookAdapter(this, books);
lvEntity.setAdapter(adapterBook);
}
lvEntity.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (!stopLoadingMore) {
if (totalItemCount == firstVisibleItem + visibleItemCount && !isLoading) {
isLoading = true;
showLoading();
loadMoreData();
}
}
}
});
}
private void loadMoreData() {
String loadMoreUrl = buildLoadMoreUrl();
ShareMyBookHttpClient client = new ShareMyBookHttpClient();
client.get(loadMoreUrl, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
hideLoading();
if (responseBody != null) {
start = start+20;
try {
JSONObject jo = new JSONObject(new String(responseBody));
if (!jo.getBoolean(Constants.JsonKeys.ERROR)) {
JSONArray data = jo.getJSONArray(Constants.JsonKeys.DATA);
if (data.length() == 0) {
stopLoadingMore = true;
return;
}
if (data.length() < 20) {
stopLoadingMore = true;
}
for (int i = 0; i < data.length(); i++) {
entityData.put(data.getJSONObject(i));
}
if (viewAllEntityType == Constants.SMBEntityType.TYPE_USER) {
List<Users> users = Utility.convertJsonArrayToUsers(entityData);
adapterUser.mergeArray(users);
} else {
List<Book> books = Utility.convertJsonArrayToBook(entityData);
adapterBook.mergeArray(books);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
hideLoading();
}
});
}
private String buildLoadMoreUrl() {
switch (viewAllCategory) {
default:
case ViewAllCategory.CATEGORY_USER:
return Constants.createUrlToGetViewAllUsers(Users.getId(), latitude, longitude, Users.getAuthToken(), start, LIMIT);
case ViewAllCategory.CATEGORY_MY_BOOKS:
return Constants.createUrlToGetViewAllMyBooks(Users.getId(), Users.getAuthToken(), start, LIMIT);
}
}
private void showLoading() {
sbLoading = Snackbar.make(coolMain, R.string.view_all_loading, Snackbar.LENGTH_INDEFINITE);
sbLoading.show();
}
private void hideLoading() {
isLoading = false;
if (sbLoading != null) {
sbLoading.dismiss();
}
}
and following is my AdapterClasss
public class ViewAllUserAdapter extends BaseAdapter {
private List<Users> users;
private Context context;
public ViewAllUserAdapter(Context context, List<Users> usersData) {
this.context = context;
users = usersData;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row=convertView;
UserVH holder=null;
if(row==null) {
LayoutInflater inflater = LayoutInflater.from(context);
row= inflater.inflate(R.layout.list_item_view_all_user, parent, false);
holder = new UserVH(row, position);
Users user = users.get(position);
UIUtility.setUserProfileUsingPicasso(context, user.getProfileImageUrlSmall(), holder.ivUserImage);
holder.tvName.setText(user.getName());
if (user.getDistance() == -1) {
holder.tvDistance.setText("");
} else {
holder.tvDistance.setText(context.getString(R.string.distance_notation, user.getDistance()));
}
row.setTag(holder);
}
else {
holder=(UserVH)row.getTag();Users user = users.get(position);
UIUtility.setUserProfileUsingPicasso(context, user.getProfileImageUrlSmall(), holder.ivUserImage);
holder.tvName.setText(user.getName());
if (user.getDistance() == -1) {
holder.tvDistance.setText("");
} else {
holder.tvDistance.setText(context.getString(R.string.distance_notation, user.getDistance()));
}
}
return row;
}
@Override
public int getCount() {
return users == null ? 0 : users.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
public void mergeArray(List<Users> additionalUsers) {
Log.e("users", String.valueOf(additionalUsers.size()));
if (additionalUsers != null) {
for (int i = 0; i < additionalUsers.size(); i++) {
if(!(users.contains(additionalUsers.get(i)))) {
users.add(additionalUsers.get(i));
}
}
}
notifyDataSetChanged();
}
public class UserVH extends View {
@Bind(R.id.item_vau_iv_user_image)
ImageView ivUserImage;
@Bind(R.id.item_vau_tv_name)
TextView tvName;
@Bind(R.id.item_vau_tv_distance)
TextView tvDistance;
private int position;
public UserVH(View view, final int position) {
super(context);
this.position = position;
ButterKnife.bind(this, view);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
UIUtility.openUserDetailActivity(context, users.get(position));
}
});
}
}
}
Upvotes: 2
Views: 419
Reputation: 1984
As you already referred this link, Exactly the same issue is happening with you, You should have correct implementation for holder class in getView method.
Update your getView() method as per below :
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row=convertView;
UserVH holder=null;
if(row==null) {
LayoutInflater inflater = LayoutInflater.from(context);
row= inflater.inflate(R.layout.list_item_view_all_user, parent, false);
holder = new UserVH(row, position);
row.setTag(holder);
}
else {
holder=(UserVH)row.getTag();
}
Users user = users.get(position);
UIUtility.setUserProfileUsingPicasso(context, user.getProfileImageUrlSmall(), holder.ivUserImage);
holder.tvName.setText(user.getName());
if (user.getDistance() == -1) {
holder.tvDistance.setText("");
} else {
holder.tvDistance.setText(context.getString(R.string.distance_notation, user.getDistance()));
}
return row;
}
And update your getItemId and getItem methods as per below :
@Override
public Object getItem(int position) {
return users.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
EDIT : clear the list additional users before adding the new objects
public void mergeArray(List<Users> additionalUsers) {
Log.e("users", String.valueOf(additionalUsers.size()));
if (additionalUsers != null) {
// Following line to be added
additonalusers.clear();
for (int i = 0; i < additionalUsers.size(); i++) {
if(!(users.contains(additionalUsers.get(i)))) {
users.add(additionalUsers.get(i));
}
}
}
notifyDataSetChanged();
}
Upvotes: 1
Reputation: 8853
Your implementation of following methods is incorrect.
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
Change them as below
@Override
public Object getItem(int position) {
return users.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
Upvotes: 1