1

我伸出的ExpandableListView创建自己的列表视图和适配器回调的实现方式是:ExpandableListView回调不同步

@Override 
public int getGroupCount() { 
    return m_FilteredSites.getSize(); 
} 

@Override 
public Object getGroup(int i) { 
    return m_FilteredSites.get(i); 
} 

@Override 
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { 
    SiteEntity site = (SiteEntity) getGroup(groupPosition); 
    //more code .... 
} 

的问题是,在调用getGroupCount和getGroupView之间的m_FilteredSites集合可以改变(由于在我的情况下使用过滤器)。 有没有一种方法来强制执行同步或任何其他方法,以保持呼叫之间的数据一致?

回答

1

现在问题已修复。 问题是我改变了工作线程而不是UI线程的m_FilteredSites集合。 Filter类有2个回调函数: 1. performFiltering - 在工作线程上执行。 2. publishResults - 在UI线程上执行。

最初我计算过滤器,但也修改performFiltering方法m_FilteredSites。 解决的办法是将实际将m_FilteredSites集合更改为publishResults方法的代码。

0

您可以同步自己的代码来访问它,而不是按顺序的同时,e.g:

ExpandableListView elv; 

synchronized(elv) { 
    // Do whatever with elv that requires exclusive thread access 
} 
+0

我看不到如何同步我的代码会有所帮助。我不控制流量 - 这是系统回调。例如,系统将调用getGroupCount并获得数字3(同步块终止)。 2.现在我在另一个同步块中更改数据,项目数变为0. 3.现在系统调用带编号2的getGroupView,因为它仍认为项目数为3. boom。 – galbarm 2013-02-28 09:11:41

1

你不应该改变的 setAdapter() 外的内部数据。相反,您可以构建新的适配器,然后使用该方法更改它,并且一切都会好起来的。

此视频为ListView,但它也可以与ExpandableListViewGoogle I/O 2010 - The world of ListView。如果你有时间,我认为值得一看。


编辑

我很抱歉,我不记得在那里我学到这一点。我刚刚重新观看了上面的视频,但无法找到那一刻。我认为notifyDataSetChanged()是在列表中的项目数据发生变化时使用的,而不是列表本身。现在,如果我没记错的话,你应该这样做:

public class SampleAdapter extends BaseExpandableListAdapter { 

    private List<List<String>> mData; 

    public void updateData(List<List<String>> data) { 
     mData = data; 
     notifyDataSetChanged(); 
    } 
} 

我的意思是你不应该改变的mData(如add()remove() ...)项目。建立新列表并将其分配到mData(如上面的代码)会更好。

如果您有content provider,您可以使用CursorTreeAdapter,它会自动为您管理数据集。我强烈建议使用内容提供商。

+0

你的回答听起来很合理。但是,适配器中的notifyDataSetChanged方法是否表明,在不重新创建适配器的情况下更改适配器的内部数据是“正常”? – galbarm 2013-02-28 09:31:16

+0

@galbarm对于原始答案,我很抱歉,我编辑了它... – 2013-02-28 11:28:47