我正在使用带有自定义列表适配器的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);
}
}
我的错误在哪里?
答案 0 :(得分:9)
您当前的适配器更新代码将无法正常工作,因为您没有更新对数据的正确引用,即适配器实际所基于的数据。当您调用refreshList
时,您创建该线程来解析xml并将结果分配给feed
变量,但是您的适配器有自己对初始数据(_feed
)的引用,这是不受之前作业的影响,因此在notifyDataSetChanged()
通话时,它仍会看到旧数据并且什么都不做。
解决方案是更新适配器的_feed
引用以指向新的已解析结果集,然后在适配器上调用notifyDataSetChanged()
。
答案 1 :(得分:0)
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();
而且你可以使用它来代替刷新按钮。这可以帮助你。 pulltorefresh