اندرويد:تحديث ليستفراغمنت باستخدام نوتيفيداتاسيتشانجيد () مع محول مخصص لا يعمل
سؤال
أنا باستخدام ليستفراغمنت مع محول قائمة مخصصة وأريد تحديث القائمة بنقرة على أيقونة في أكتيونبار.للأسف لا يعمل وليس لدي أي فكرة عن السبب.
قائمة العناصر الخاصة بي:
@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();
}
بلدي كوستومليستادابتر.جافا
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
, ، إنشاء هذا الموضوع لتحليل شمل وتعيين النتائج إلى feed
متغير ، ولكن المحول الخاص بك لديه إشارة خاصة به إلى البيانات الأولية(_feed
) التي لا تتأثر بالمهمة السابقة حتى في لحظة notifyDataSetChanged()
نسميها سوف لا تزال ترى البيانات القديمة ولن تفعل شيئا.
الحل هو تحديث _feed
مرجع المحول للإشارة إلى المجموعة الجديدة من النتائج التي تم تحليلها ثم الاتصال notifyDataSetChanged()
على المحول.
نصائح أخرى
وأيضا بدلا من زر التحديث، يمكنك استخدام هذا. هذا يساعدك. pulltorefresh