BaseAdapter.notifyDataSetChanged反转元素的顺序

时间:2011-02-09 11:10:49

标签: android adapter android-asynctask

对于Android应用中的导航,我使用的是ListView,并在活动的onCreate方法中为其创建并设置BaseAdapter。

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 个答案:

答案 0 :(得分:2)

问题在于getView()函数。 通过对方法的不同调用,View对象被缓存,但不与位置耦合。

使用正确的日志,您还可以将此行为视为:

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

这就是为什么列表被颠倒了。 解决方案:在每次调用getView时,即使对象存在,也要在Value中设置值。即:

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

答案 1 :(得分:0)

您确定远程服务是否正确订购了新数据?我会围绕那部分做一些调试,发布的代码对我来说似乎没问题。

此外,还有一个解决方法:用户ListView的StackFromBottom属性:)