Android:使用带有自定义适配器的notifyDataSetChanged()刷新ListFragment无效

Android:使用带有自定义适配器的notifyDataSetChanged()刷新ListFragment无效,android,listview,android-fragments,android-listfragment,notifydatasetchanged,Android,Listview,Android Fragments,Android Listfragment,Notifydatasetchanged,我正在使用带有自定义列表适配器的ListFragment,我想通过单击ActionBar中的图标来刷新列表。不幸的是,它不起作用,我不知道为什么 我的ItemListFragment: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("debug","Hallo in ItemListFragment"); //s

我正在使用带有自定义列表适配器的ListFragment,我想通过单击ActionBar中的图标来刷新列表。不幸的是,它不起作用,我不知道为什么

我的ItemListFragment:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.d("debug","Hallo in ItemListFragment");

    //show ActionBar
    setHasOptionsMenu(true);

    //get reference to activity
    myApp = getActivity().getApplication();

    //check if intent from ItemListActivity is null
    Bundle be = getActivity().getIntent().getExtras();
    if (be == null){
        //if null read local feed
        feed = ReadFeed(fileName);
        Log.d("debug", "Lese Feed lokal :"+feed);
    }else{
        //else get extras from the intent
        feed = (RSSFeed) getActivity().getIntent().getExtras().get("feed");
        Log.d("debug", "Intent von ItemListActivity an ItemListFragment vorhanden");
    }

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) {
    //inflate the fragment with the custom detail fragment
    View view = inflater.inflate(R.layout.feed_list, null);
    return view;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    //get listview from layout
    lv = getListView();
    lv.setVerticalFadingEdgeEnabled(true);

    // Set custom list adapter to the ListView        
    adapter = new CustomListAdapter(getActivity(), feed);
    lv.setAdapter(adapter);

}

//Inflate ActionBar
@Override
public void onCreateOptionsMenu(Menu optionsMenu, MenuInflater inflater) {
    inflater.inflate(R.menu.main, optionsMenu);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    // Restore the previously serialized activated item position.
    if (savedInstanceState != null
            && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
        setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
    }
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // Activities containing this fragment must implement its callbacks.
    if (!(activity instanceof Callbacks)) {
        throw new IllegalStateException("Activity must implement fragment's callbacks.");
    }

    mCallbacks = (Callbacks) activity;
}

@Override
public void onDetach() {
    super.onDetach();

    // Reset the active callbacks interface to the dummy implementation.
    mCallbacks = sCallbacks;
}

@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
    super.onListItemClick(listView, view, position, id);

    // Notify the active callbacks interface (the activity, if the
    // fragment is attached to one) that an item has been selected.
    if (mCallbacks != null) {
        Log.d("debug","Callback in ItemListFragment mit Position: "+position+"und Feed: "+feed);
        mCallbacks.onItemSelected(position, feed);
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    if (mActivatedPosition != ListView.INVALID_POSITION) {
        // Serialize and persist the activated item position.
        outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
    }
}

/**
 * Turns on activate-on-click mode. When this mode is on, list items will be
 * given the 'activated' state when touched.
 */
public void setActivateOnItemClick(boolean activateOnItemClick) {
    // When setting CHOICE_MODE_SINGLE, ListView will automatically
    // give items the 'activated' state when touched.
    getListView().setChoiceMode(activateOnItemClick
            ? ListView.CHOICE_MODE_SINGLE
                    : ListView.CHOICE_MODE_NONE);
}

private void setActivatedPosition(int position) {
    if (position == ListView.INVALID_POSITION) {
        getListView().setItemChecked(mActivatedPosition, false);
    } else {
        getListView().setItemChecked(position, true);
    }

    mActivatedPosition = position;
}

//OnClick auf ActionBar
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        return true;
    case R.id.refresh_option:
        refreshList(item);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

//Click on refresh in ActionBar -> Refresh the List
public void refreshList(final MenuItem item) {
    /* Attach a rotating ImageView to the refresh item as an ActionView */
    LayoutInflater inflater = (LayoutInflater) getActivity().getApplication()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    ImageView iv = (ImageView) inflater.inflate(R.layout.action_refresh,
            null);

    Animation rotation = AnimationUtils.loadAnimation(getActivity(),
            R.anim.refresh_rotate);
    rotation.setRepeatCount(Animation.INFINITE);
    iv.startAnimation(rotation);

    item.setActionView(iv);

    // trigger feed refresh:
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            DOMParser tmpDOMParser = new DOMParser();
            feed = tmpDOMParser.parseXml("http://www.example.de/feed");

            Log.d("debug", "Refresh Liste mit Feed: "+feed);

            ItemListFragment.this.getActivity().runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    if (feed != null && feed.getItemCount() > 0) {
                        Log.d("debug", "Aktualisiere Liste");
                        adapter.notifyDataSetChanged();
                        item.getActionView().clearAnimation();
                        item.setActionView(null);
                    }
                }
            });
        }
    });
    thread.start();
}

@Override
public void onDestroy() {
    super.onDestroy();
    //TODO Datenverbrauch dadurch geringer?
    //adapter.imageLoader.clearCache();
    adapter.notifyDataSetChanged();
}   
My CustomListAdapter.java

public class CustomListAdapter extends BaseAdapter  {

    private LayoutInflater layoutInflater;
    public ImageLoader imageLoader;
    public RSSFeed _feed;

    public CustomListAdapter(Activity activity, RSSFeed feed) {

        _feed = feed;

        layoutInflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());
    }

    @Override
    public int getCount() {
        // Set the total list item count
        return _feed.getItemCount();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // Inflate the item layout and set the views
        View listItem = convertView;
        int pos = position;
        if (listItem == null) {
            listItem = layoutInflater.inflate(R.layout.list_item, null);
        }

        // Initialize the views in the layout
        ImageView iv = (ImageView) listItem.findViewById(R.id.thumb);
        TextView tvTitle = (TextView) listItem.findViewById(R.id.title);
        TextView tvDate = (TextView) listItem.findViewById(R.id.date);
        TextView tvDesc = (TextView) listItem.findViewById(R.id.description);

        // Set the views in the layout
        imageLoader.DisplayImage(_feed.getItem(pos).getImage(), iv);
        tvTitle.setText(_feed.getItem(pos).getTitle());
        tvDate.setText(_feed.getItem(pos).getDate());
        tvDesc.setText(_feed.getItem(pos).getShortDescription());

        return listItem;
    }
}
这是我尝试刷新列表的部分:

        @Override
        public void run() {
            if (feed != null && feed.getItemCount() > 0) {
                Log.d("debug", "Aktualisiere Liste");
                adapter.notifyDataSetChanged();
                item.getActionView().clearAnimation();
                item.setActionView(null);
            }
        }

我的错误在哪里?

适配器的当前更新代码将不起作用,因为您没有更新对数据的正确引用,而数据是适配器实际基于的数据。调用
refreshList
时,您将创建该线程来解析xml并将结果分配给
feed
变量,但是适配器有自己对初始数据(
\u feed
)的引用,该引用不受前一次分配的影响,因此在
notifyDataSetChanged()时
call它仍会看到旧数据,并且不会执行任何操作

解决方案是更新适配器的
\u提要
引用,以指向新的解析结果集,然后在适配器上调用
notifyDataSetChanged()

        Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        DOMParser tmpDOMParser = new DOMParser();
        feed = tmpDOMParser.parseXml("http://www.example.de/feed");

        Log.d("debug", "Refresh Liste mit Feed: "+feed);

        ItemListFragment.this.getActivity().runOnUiThread(new Runnable() {

            @Override
            public void run() {
                if (feed != null && feed.getItemCount() > 0) {
                    Log.d("debug", "Aktualisiere Liste");
    // Set custom list adapter to the ListView        
  adapter = new CustomListAdapter(getActivity(), feed);
      lv.setAdapter(adapter);
                     adapter.notifyDataSetChanged();
                    item.getActionView().clearAnimation();
                    item.setActionView(null);
                }
            }
        });
    }
});
thread.start();
你也可以用这个代替刷新按钮。这对你很有帮助。

不要认为这是相关的,但您不需要执行
lv.setAdapter(adapter)订阅源刷新。另外,您是否检查过这段代码是否运行到其完成状态?我在ActionBar中的动画停止,因此我认为代码在您再次解析xml的线程中运行完全,并将其分配给
feed
变量,然后调用
notifyDataSetChanged()
但这不会更新适配器,因为您不会更新适配器持有的实际数据引用(因此它仍然会看到旧的数据列表)。因此,当您需要更新适配器时,在调用
notifyDataSetChanged()
之前,首先更新适配器的
\u feed
变量,以指向新解析的
feed
(您可以在适配器中添加setter方法,将
feed
分配给
\u feed
(并在更新线程中调用它).你救了我一天!你能写一个新的评论,这样我就可以把它标记为解决方案吗!这会起作用的..毫无疑问,但每次你到底部时,它都会把你带到列表视图的顶部..这会导致非常糟糕的用户体验…因此这不是解决方案如果你在做setA,NotifyDataSangeetched有什么用一次又一次地改变。