Android:使用带有自定义适配器的 notifyDataSetChanged() 刷新 ListFragment 不起作用

标签 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");

    //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();
}   

我的 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 变量,但是您的适配器有其自己对初始数据的引用(_feed) 不受先前分配的影响,因此在调用 notifyDataSetChanged() 时,它仍会看到旧数据并且什么都不做。

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

关于Android:使用带有自定义适配器的 notifyDataSetChanged() 刷新 ListFragment 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20012491/

相关文章:

java - 没有键的 JSON 数组的 POJO [Long, Double]

json - 使用 Rest Api 的 Xamarin 中的 ListView

java - Android 自定义 View 中的数据绑定(bind)

android - 是否可以将持久 Bottom Sheet 作为 fragment ?

android - 如何获取有用的崩溃日志信息 Android Cocos2dx C++

android - 使用 GoogleApiClient 静默登录以检索 token

Android: fragment 中的Http请求

java - onClickListener 中的 ArrayAdapter 不起作用

ios - 当显示在 FlatList 顶部时,OnPress 后背景颜色变为黑色

android - 将数据从当前 fragment 传回前一个 fragment