BaseAdapter.notifyDataSetChanged инвертирует порядок элементов - PullRequest
2 голосов
/ 09 февраля 2011

Для навигации в моем приложении Android я использую ListView и создаю и устанавливаю для него BaseAdapter в методе onCreate действия.

BaseAdapter обращается к ArrayList для получения элементов (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;
    }
}

Итак, навигация строится при запуске из кеша. Тем временем я запускаю AsyncTask, которая получает навигационный ArrayList с сервера, а после его изменения сохраняет новую навигацию в кеш:

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();
        }
    }
}

Когда я ничего не делаю в populateData(), ListView не обновляется. Когда я звоню ((BaseAdapter) ListView.getAdapter()).notifyDataSetChanged(), представление обновляется, но порядок инвертируется. Первый элемент - последний, последний - первый и т. Д.

Требуется! Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 09 июня 2011

проблема заключается в функции getView (). через различные вызовы метода объекты View кэшируются, но не связаны с позицией.

с правильными журналами, вы также можете увидеть это поведение как:

 pos1: View1 
 pos2: View2
 pos3: View3
 pos3: View1
 pos2: View2
 pos1: View3

Вот почему список переворачивается. Решение: при каждом вызове getView устанавливайте значения в Value, даже если объект существует. i.e.:

 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);
    } else {
        v = convertView;
    }
    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);

    return v;
}
0 голосов
/ 09 февраля 2011

Вы уверены, что ваша удаленная служба вернула новые данные в правильном порядке?Я бы сделал несколько отладок в этой части, опубликованный код мне подходит.

Также есть обходной путь: атрибут StackFromBottom пользователя ListView:)

...