For the navigation in my Android app I am using a ListView and create and set a BaseAdapter for it in the onCreate method of the activity.
The BaseAdapter accesses an ArrayList to retrieve elements (cache.getNavigation()):
public class NavigationAdapter extends BaseAdapter {
Context mContext;
public NavigationAdapter(Context c) {
mContext = c;
}
@Override
public int getCount() {
return cache.getNavigation() != null ? cache.getNavigation().size()
: 0;
}
@Override
public Object getItem(int position) {
return cache.getNavigation() != null ? cache.getNavigation().get(
position) : 0;
}
@Override
public long getItemId(int position) {
return cache.getNavigation() != null ? cache.getNavigation().get(
position).getId() : 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v;
if (convertView == null) {
LayoutInflater li = getLayoutInflater();
v = li.inflate(R.layout.list_nav_icon, null);
TextView tv = (TextView) v.findViewById(R.id.list_nav_text);
tv.setText(((TemplateInstanceDto) getItem(position))
.getName());
ImageView icon = (ImageView) v
.findViewById(R.id.list_nav_icon);
byte[] binary = ((TemplateInstanceDto) getItem(position))
.getIcon();
Bitmap bm = BitmapFactory.decodeByteArray(binary, 0,
binary.length);
icon.setImageBitmap(bm);
ImageView arrow = (ImageView) v
.findViewById(R.id.list_nav_arrow);
arrow.setImageResource(R.drawable.arrow);
} else {
v = convertView;
}
return v;
}
}
So the navigation is built on startup from the cache.
Meanwhile I start an AsyncTask that retrieves the navigation ArrayList from a server and when it has changed it saves the new navigation into the cache:
private class RemoteTask extends
AsyncTask<Long, Integer, List<TemplateInstanceDto>> {
protected List<TemplateInstanceDto> doInBackground(Long... ids) {
try {
RemoteTemplateInstanceService service = (RemoteTemplateInstanceService) ServiceFactory
.getService(RemoteTemplateInstanceService.class,
getClassLoader());
List<TemplateInstanceDto> templates = service
.findByAccountId(ids[0]);
return templates;
} catch (Exception e) {
return null;
}
}
protected void onPostExecute(List<TemplateInstanceDto> result) {
if (result != null && result.size() > 0) {
cache.saveNavigation(result);
populateData();
} else {
Toast text = Toast.makeText(ListNavigationActivity.this,
"Server communication failed.", 3);
text.show();
}
}
}
When I do nothing more in populateData(), the ListView doesn´t update. When I call ((BaseAdapter) ListView.getAdapter()).notifyDataSetChanged() the View is updated, but the order is inverted. The first item is the last and the last is the first and so on.
Held needed! Thanks in advance.
the problem lies with getView() function.
through different calls of the method, the View objects are cached, though not coupled with the position.
with proper logs, you can also see this behavior as:
thats why the list is getting inverted.
Solution: on each call of getView, set values in Value even if the object exists. i.e.: