【问题标题】:Data has changed but notifyDataSetChanged not working数据已更改,但 notifyDataSetChanged 不起作用
【发布时间】:2017-02-06 14:05:31
【问题描述】:

我正在尝试构建一个音乐播放器。 我有一个名为 MusicData 的类,它提供播放列表数据和另一个用于播放列表片段的类,因为我使用的是 viewpager。 播放列表片段使用自定义 expandableListAdapter 类加载数据。

现在的问题是这样的。当用户点击一首歌曲时,它应该被添加到最近播放的播放列表中,这应该反映在播放列表片段中。 基础数据确实发生了变化,因为当我单击播放列表中的第一首歌曲时,它确实播放相同,但包含歌曲标题的视图没有变化

因此,问题本质上是视图不反映基础数据。我试图将 notifyDataSetChanged 方法放在播放列表片段类中,但它不起作用。该怎么办?

这是播放列表片段类的代码

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.playlist, container, false);
    expandableListView = (ExpandableListView)v.findViewById(R.id.expandableListViewPlaylist);
    Log.e(TAG,"1");
    expandableListTitle = new ArrayList<>(MusicData.getExpandableListDetailPlayList().keySet());
    expandableListAdapter = new CustomExpandableListAdapter(this.getContext(), expandableListTitle, MusicData.getExpandableListDetailPlayList());
    expandableListView.setAdapter(expandableListAdapter);
    expandableListAdapter.notifyDataSetChanged();
    .......

这是 MusicData 类的代码

public static LinkedHashMap<String, ArrayList<Song>> getExpandableListDetailPlayList(){return expandableListDetailPlayList;}

这是适配器

public class CustomExpandableListAdapter extends BaseExpandableListAdapter {

private Context context;
private ArrayList<String> expandableListTitle;
private LinkedHashMap<String, ArrayList<Song>> expandableListDetail;
private String TAG = "AdapterClass";
public CustomExpandableListAdapter(Context context, ArrayList<String> expandableListTitle,
                                   LinkedHashMap<String, ArrayList<Song>> expandableListDetail) {
    this.context = context;
    this.expandableListTitle = expandableListTitle;
    this.expandableListDetail = expandableListDetail;

}

@Override
public Object getChild(int listPosition, int expandedListPosition) {
    return this.expandableListDetail.get(this.expandableListTitle.get(listPosition))
            .get(expandedListPosition);
}

@Override
public long getChildId(int listPosition, int expandedListPosition) {
    return expandedListPosition;
}
......    

播放列表的数据在 MainActivity 类中更改。那么如何以及在哪里调用 notifyDataSetChanged() 方法呢?

【问题讨论】:

  • 请分享处理用户点击的代码部分并相应地将该歌曲添加到列表中
  • 在哪里调用 notifyDataSetChanged() 方法?在您的数据发生变化后

标签: android android-fragments expandablelistadapter audio-player notifydatasetchanged android-music-player


【解决方案1】:

notifyDataSetChanged() 用于通知适配器数据已更改。您在适配器/视图设置/创建中使用它,这没有任何意义。您应该做的以及您可能缺少的是将所选歌曲添加到适配器的数据中,然后调用notifyDataSetChanged()方法

编辑:来自 OP

我试图实现一个监听器,但无法让它工作,因为消息必须从主要活动发送到片段,在我看来没有办法做到这一点。

无论如何,所以我按照建议尝试了 EventBus,但即使这样 notifyDataSetChanged 方法也不起作用,notifyDataSetInvalidated 也不起作用。

最终我不得不在适配器类中编写另一个函数来清除视图并设置新数据。我从播放列表片段中调用了这个函数。这是代码

    public void refresh(ArrayList<String> expandableListTitle,
                    LinkedHashMap<String, ArrayList<Song>> expandableListDetail){
    this.expandableListDetail.clear();
    this.expandableListTitle.clear();
    this.expandableListDetail.putAll(expandableListDetail);
    this.expandableListTitle.addAll(expandableListTitle);
    this.notifyDataSetChanged();
    }

我再次进行了一些实验,看看如果删除了 notify 方法会发生什么,并且看到如果展开组视图,视图没有得到更新。当组视图被折叠并再次展开时,它得到了更新。所以这里的 notify 方法确实有效,但只有在清除视图之后。 当我没有清除视图时,通知方法不起作用。

课程 在调用 notify 方法之前,始终清除视图并注入新数据。也许在其他一些 Android api 上,您不需要清除视图等等,但我认为任何人都不应该冒险。我在 Android api 19 上进行了测试。

【讨论】:

  • 看到问题是主活动中的数据发生了变化。片段类仅用于查看目的和设置适配器。因此我怎么知道何时调用通知方法?据我所知,我可能应该实现 dataSetObserver 但我不知道该怎么做
  • 您可以使用事件总线或接口在活动和片段之间进行通信。这两种方法都将为您提供一种方法来告诉片段从活动developer.android.com/training/basics/fragments/…github.com/greenrobot/EventBus 中执行某些操作
  • 感谢您推荐 eventbus。这有助于@howdoidothis
  • 不错的选择!我认为这是在组件之间建立通信的更好方式,因为你可以用它做比接口更多的事情,而且它更干净。我很高兴能帮上忙
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
相关资源
最近更新 更多