【问题标题】:BaseAdapter.notifyDataSetChanged inverts order of elementsBaseAdapter.notifyDataSetChanged 反转元素的顺序
【发布时间】:2011-02-09 11:10:49
【问题描述】:

对于我的 Android 应用程序中的导航,我使用 ListView 并在 Activity 的 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() 时,视图已更新,但顺序颠倒了。第一项是最后一项,最后一项是第一项,依此类推。

需要持有!提前致谢。

【问题讨论】:

    标签: android adapter android-asynctask


    【解决方案1】:

    问题在于 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;
    }
    

    【讨论】:

    • 完美答案。我不熟悉 convertView,但同时我明白它的用途。谢谢。
    【解决方案2】:

    您确定您的远程服务返回正确排序的新数据吗?我会围绕那部分进行一些调试,发布的代码对我来说似乎没问题。

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

    【讨论】:

    • 我非常确定,远程服务可以正确地传送数据。当我手动触发 AsyncTask 时,每次都会颠倒顺序(自上而下、自下而上、自上而下……)。现在,我找到了一种解决方法,每次在populateData() 中设置一个新适配器:ListView.setAdapter(new NavigationAdapter(this))
    猜你喜欢
    • 2010-12-13
    • 2011-12-18
    • 2020-06-30
    • 1970-01-01
    • 2021-12-01
    • 2013-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多