2009-09-23 162 views
7

我有一个扩展ExpandableListActivity的活动。我使用SimpleCursorTreeAdapter来填充ExpandableListView。 我的布局包含列表视图和空视图。 在应用程序启动时,ExpandableListActivity会自动选择正确的视图来显示。如何更新适配器数据更改时的可扩展列表视图

我的步骤:

  1. 应用程序启动时,没有数据。 (屏幕上的空白视图)
  2. 将一些数据插入到数据库中。
  3. 调用adapter.notifyDataSetChanged();但空的视图仍然在屏幕上,我的列表视图中没有任何项目。

然后我重新启动应用程序:

出现
  • 列表视图。我展开所有组并滚动到底部。
  • 我点击列表中的项目。出现新的活动。
  • 单击返回按钮。所有组都崩溃了,我们在屏幕的顶部。不记住滚动位置和扩展组。
  • 从db中删除所有数据并调用adapter.notifyDataSetChanged();
  • 子视图已经消失,但顶级组仍然可见。
  • 问题:

    1. 我能做些什么,以取代列表视图空的看法?
    2. 我该怎么做才能保存列表视图的组的状态和滚动位置?

    测试在软件开发工具包:1.5r3,1.6r1

    代码:

    public class MainActivity extends ExpandableListActivity { 
    
        public void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
         setContentView(R.layout.main); 
    
         dbHelper = new DBOpenHelper(this); 
    
         rubricsDbAdapter = new RubricsDBAdapter(dbHelper); 
         rubricsDbAdapter.open(); 
    
         itemsDbAdapter = new ItemsDBAdapter(dbHelper); 
         itemsDbAdapter.open(); 
    
         rubricsCursor = rubricsDbAdapter.getAllItemsCursor(); 
         startManagingCursor(rubricsCursor); 
    
         // Cache the ID column index 
         rubricIdColumnIndex = rubricsCursor.getColumnIndexOrThrow(RubricsDBAdapter.KEY_ID); 
    
         // Set up our adapter 
         mAdapter = new MyExpandableListAdapter(rubricsCursor, 
           this, 
           android.R.layout.simple_expandable_list_item_1, 
           android.R.layout.simple_expandable_list_item_1, 
           new String[] {RubricsDBAdapter.KEY_NAME}, 
           new int[] {android.R.id.text1}, 
           new String[] {ItemsDBAdapter.KEY_NAME}, 
           new int[] {android.R.id.text1}); 
    
         setListAdapter(mAdapter); 
        } 
    
        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { 
         Intent i = new Intent(this, ItemViewActivity.class); 
         i.putExtra(ItemsDBAdapter.KEY_ID, id); 
         startActivity(i); 
    
         return super.onChildClick(parent, v, groupPosition, childPosition, id); 
        } 
    
        private void updateMyData() { 
         int i; 
         int k; 
         long rubricId; 
    
         for (i = 1; i <= 5; i++) { 
          rubricId = rubricsDbAdapter.insert("rubric " + i); 
          for (k = 1; k <= 5; k++) { 
           itemsDbAdapter.insert("item " + i + "-" + k, rubricId); 
          } 
         } 
    
         mAdapter.notifyDataSetChanged(); 
        } 
    
        private void deleteMyData() { 
         rubricsDbAdapter.deleteAll(); 
         itemsDbAdapter.deleteAll(); 
    
         mAdapter.notifyDataSetChanged(); 
        } 
    
        public class MyExpandableListAdapter extends SimpleCursorTreeAdapter 
        { 
         public MyExpandableListAdapter(Cursor cursor, Context context, int groupLayout, 
           int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom, 
           int[] childrenTo) { 
          super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childrenFrom, 
            childrenTo); 
         } 
    
         @Override 
         protected Cursor getChildrenCursor(Cursor notebookCursor) { 
          // Given the group, we return a cursor for all the children within that group 
          long id = notebookCursor.getLong(rubricIdColumnIndex); 
    
          Cursor itemsCursor = itemsDbAdapter.getRubricItemsCursor(id); 
          startManagingCursor(itemsCursor); 
          return itemsCursor; 
         } 
    
        } 
    } 
    
    +0

    请向我们展示MyExpandableListAdapter的实现。 – Matthias 2009-09-24 12:18:22

    +0

    实施就在这里。向下滚动到代码的底部。 此外,我意识到,我需要手动重新查询我的rubrics光标。所以正确的代码将是: rubricsCursor.requery(); mAdapter.notifyDataSetChanged(); 但第二个问题仍然让我担心。 – 2009-09-24 16:40:05

    +0

    我无法解释这个代码块今天对我有多大帮助。我不知道没有它我会做什么。太感谢了! – dfetter88 2010-08-10 20:11:49

    回答

    4

    因此,答案是:

    1. 呼叫cursor.requery()调用适配器的notifyDataSetChanged前() 方法。
    2. 在活动的onPause()方法中保存组状态并在onResume()方法中恢复。
    2

    回复:问题#2 ...

    为什么你不能简单地调用View.invalidateViews()和View.requestLayout()的顺序?

    如果您已将适配器设置为视图,那么您不需要重新查询,对吗?通过使视图无效并请求布局,您不会失去任何视图状态。

    例如,在您的“onResume”方法中,通过调用类似“lv.invalidateViews()”的方法使列表视图失效。接下来,调用“lv.requestLayout()”。

    您的“onCreate”方法仍应负责设置适配器并将适配器链接到视图。要链接适配器,考虑使用“lv.setListAdapter()”而不是前者,这样就不会搞乱屏幕上的其他视图。