【问题标题】:Android - list returns to top after updateAndroid - 更新后列表返回顶部
【发布时间】:2010-09-07 16:40:18
【问题描述】:

我有一个通过 Handler postDelayed() 方法每 2 秒刷新一次的列表。

每 2 秒运行一次 AsyncTask,它发出一个 HTTP GET 请求,将 JSON 转换为对象列表,然后设置 ListAdapter:

 MyListAdapter adapter = new MyListAdapter(someObjects);
 setListAdapter(adapter);

我的问题是每次任务完成时(大约每两秒一次)我的列表都会跳回顶部,即使我已经向下滚动到列表的中间或底部。这对最终用户来说会很烦人,所以我需要在后台更新列表,就像它正在做的那样,但是列表的当前视图在 AsyncTask 完成时不会跳回顶部。

我可以包含更多需要的代码。我对android开发有点陌生,所以我不确定什么对其他人有帮助。

其他信息

根据 hacksteak25 的建议,我能够尝试从适配器中删除所有数据,然后一次将其添加回一个对象。这不是最终解决方案,因为这可能仍会导致屏幕跳跃,但我试图将其用作我如何在某个时候合并数据的概念证明。

我的问题是我调用了以下代码:

 MyListAdapter adapter = (MyListAdapter)getListAdapter();
 adapter.clear();
 for(MyObject myObject : myObjects)
 {
  adapter.add(myObject);
 }

在第一次调用“add(myObject)”之后,MyListAdapter 的 getView() 方法将被调用。此时自定义适配器的私有内部 ArrayList 为空,要么是因为我在 onCreate() 中设置了没有 myObjects 的适配器,要么是因为我在适配器上调用了 clear(),我不确定。无论哪种方式,这都会导致 getView 失败,因为 ArrayList 中没有要从中获取视图的对象。

getView() 看起来像这样:

public View getView(int position, View convertView, ViewGroup parent)
{
 ViewHolder holder;
 LayoutInflater mInflater = getLayoutInflater();

 if (convertView == null)
 {
  convertView = mInflater.inflate(R.layout.myObject, null);

  holder = new ViewHolder();
  holder.someProperty = (TextView)convertView.findViewById(R.id.someProperty);
  holder.someOtherProperty = (TextView)convertView.findViewById(R.id.someOtherProperty);
  holder.someOtherOtherProperty = (TextView)convertView.findViewById(R.id.someOtherOtherProperty);

  convertView.setTag(holder);
 }
 else
 {
  holder = (ViewHolder)convertView.getTag();
 }

 // Bind the data efficiently with the holder.
 holder.someProperty.setText( mObjects.get(position).getSomeProperty());
 ...

最后一行是导致 IndexOutOfBoundsException 的行。

我应该如何处理这种情况,我可以在其中获取我想要的数据而不会导致列表跳转?

【问题讨论】:

    标签: android user-interface listview android-asynctask android-arrayadapter


    【解决方案1】:

    我认为首选的方法是更新适配器本身而不是替换它。也许您可以编写一个方法,使用适配器insert()remove() 方法合并新旧数据。我认为这应该保持你的立场。

    补充信息:

    我使用以下作为基本结构。也许有帮助。

    
    public class PlaylistAdapter extends ArrayAdapter<Playlist> {
    
        private ArrayList<Playlist> items;
    
        public PlaylistAdapter(Context context, int textViewResourceId, ArrayList<Playlist> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }
    
    }
    

    【讨论】:

    • 在尝试合并数据之前,我尝试查看是否可以轻松完成此操作。但是,此代码: MyListAdapter 适配器 = (MyListAdapter)getListAdapter();适配器.clear(); for(对象对象:对象){适配器。添加(对象); } 在 java.util.AbstractList.add 处导致 java.lang.UnsupportedOperationException 这很奇怪,因为 MyListAdapter 扩展了 ArrayAdapter,它应该具有可用的 add 方法。
    • “java.util.AbstractList.add 处的 java.lang.UnsupportedOperationException”:如何初始化超类?当我将适配器数据设置为数组(例如 MyObject[] 类型)时,我遇到了同样的问题。尝试使用列表(例如 ArrayList 类型)。数组无法调整大小,但列表可以。那应该可以解决您的 UnsupportedOperationException。
    • 我尝试将我的实现从使用 MyObject[] 更改为 ArrayList。这需要进行一些重构,因为我使用的是扩展 ArrayAdapter 的自定义 ListAdapter。在构造函数中,我使用 ArrayList.toArray() 来满足超级构造函数,因为我找不到 ArrayAdapter 的合适替代品。无论哪种情况,我的应用程序都会运行,但现在根本没有显示数据。我可以展示哪些代码会有所帮助?
    • 将 toArray()-value 传递给超级构造函数会导致同样的问题。数组大小不可更改。
    • 我在答案中添加了一些代码。也许它有帮助。你的班级看起来怎么样?
    猜你喜欢
    • 1970-01-01
    • 2021-01-19
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多