Обновить текущий фрагмент (данные ListView), оставшиеся в одной активности

Вызывая Fragment из Activity , я показываю ListView с двумя Buttons . Когда я нажимаю на menu_item (т.е. Show Online), я обновляю данные и, таким образом, ListView . Теперь мне нужно отразить обновленные данные. Как я могу обновить Fragment после того, как я нажму «Показать онлайн». До сих пор я использовал следующий код:

 Intent intent = getIntent(); Intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); finish(); startActivity(intent); 

Но это перезапустит всю Activity . Мне просто нужно обновить текущий Fragment .

Введите описание изображения здесьВведите описание изображения здесь

Отредактировано: добавлен код

КЛАСС АКТИВНОСТИ

  public class ContactListActivity extends ActionBarActivity { ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final ActionBar actionBar = getActionBar(); MenuButtonUtil.enableMenuButton(this); FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); MyContactsFragment contactListFragment = new MyContactsFragment (); fragmentTransaction.replace(android.R.id.content, contactListFragment); fragmentTransaction.commit(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.show_online) { ContentValues values = new ContentValues(); String where = "((" + ContactsContentProvider.PHONE_ID + " NOTNULL) AND ((" + ContactsContentProvider.PHONE_ID+ " = 17486 )OR (" + ContactsContentProvider.PHONE_ID+ " = 17494 )))"; values.put(ContactsContentProvider.STATUS, true); this.getContentResolver().update(ContactsContentProvider.CONTENT_URI, values, where, null); listView = (ListView) this.findViewById(android.R.id.list); ((BaseAdapter) listView.getAdapter()).notifyDataSetChanged(); return true; } return super.onOptionsItemSelected(item); } } 

Фрагмент

 public class MyContactsFragment extends ListFragment{ Button allContactsBtn; Button neeoContactsBtn; ListView listView; CustomAdapterForAllContacts adapterForAllContacts; CustomAdapterForNeeoContacts adapterForNeeoContacts; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); final ActionBar actionBar = getActivity().getActionBar(); MenuButtonUtil.enableMenuButton(getActivity()); adapterForNeeoContacts = new CustomAdapterForNeeoContacts(); adapterForAllContacts = new CustomAdapterForAllContacts(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { View view = inflater.inflate(R.layout.contactsfragment, container,false); allContactsBtn = (Button) view.findViewById(R.id.allContactsButton); neeoContactsBtn = (Button) view.findViewById(R.id.neeoContactsButton); listView = (ListView) view.findViewById(android.R.id.list); // ==================== Neeo Contacts ============================ neeoContactsBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listView.setAdapter(adapterForNeeoContacts); } }); // ====================== All Contacts ============================= allContactsBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listView.setAdapter(adapterForAllContacts); } }); return view; } 

Адаптер :

 private class CustomAdapterForAllContacts extends BaseAdapter { public CustomAdapterForAllContacts(){ } List<Contact> contactsList = getAllContacts(); @Override public int getCount() { // TODO Auto-generated method stub return contactsList.size(); } @Override public Contact getItem(int arg0) { // TODO Auto-generated method stub return contactsList.get(arg0); } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } @Override public View getView(int position, View view, ViewGroup viewGroup) { if(view==null) { LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.list_item, viewGroup,false); } TextView contName = (TextView)view.findViewById(R.id.nameText); TextView contNumber = (TextView)view.findViewById(R.id.numberText); ImageView image = (ImageView)view.findViewById(R.id.contact_image); Contact contact = contactsList.get(position); String status = contact.getStatus(); if(contact.getStatus().equals("1")){ image.setBackgroundResource(com.example.mycontentprovider.R.drawable.person_empty_online); }else{ image.setBackgroundResource(com.example.mycontentprovider.R.drawable.person_empty_offline); } contName.setText(contact.getName()); contNumber.setText(contact.getPhoneNumber()); return view; } public Contact getContactPosition(int position) { return contactsList.get(position); } public List<Contact> getAllContacts(){ List<Contact> contactList = new ArrayList<Contact>(); String URL = "content://com.example.provider.Contacts/contacts"; Uri baseUri1 = Uri.parse(URL); String[] select = {ContactsContentProvider.PHONE_ID, ContactsContentProvider.STATUS}; String where = "((" + ContactsContentProvider.NEEO_USER + " NOTNULL) AND (" + ContactsContentProvider.NEEO_USER+ " = 1 )AND (" + ContactsContentProvider.STATUS+ " = 1 ))"; Cursor cursor = getActivity().getContentResolver().query(baseUri1, select, where, null, "pid"); for(cursor.moveToFirst(); cursor.moveToNext(); cursor.isAfterLast()) { Log.w("Filtered IDS",""+ cursor.getString(cursor.getColumnIndex(ContactsContentProvider.PHONE_ID))+ ""+ cursor.getString(cursor.getColumnIndex(ContactsContentProvider.STATUS))); } Uri baseUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; String[] projection = new String[] { ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; String selection = "((" + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " != ' ' ))"; String[] selectionArgs = null; String sortOrder = ContactsContract.CommonDataKinds.Phone._ID + " COLLATE LOCALIZED ASC"; Cursor mCursor= getActivity().getContentResolver().query(baseUri, projection, selection, selectionArgs, sortOrder); // Joinging Both Cursors CursorJoiner joiner = new CursorJoiner(cursor, new String[] {ContactsContentProvider.PHONE_ID} , mCursor, new String[] {ContactsContract.CommonDataKinds.Phone._ID}); for (CursorJoiner.Result joinerResult : joiner) { Contact cont = new Contact(); Log.e("Result", joinerResult.toString()); switch (joinerResult) { case LEFT: // handle case where a row in cursorA is unique break; case RIGHT: // handle case where a row in cursorB is unique cont.setID(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID))); cont.setName(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))); cont.setPhoneNumber(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); cont.setStatus("0"); contactList.add(cont); break; case BOTH: // handle case where a row with the same key is in both cursors cont.setID(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID))); cont.setName(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))); cont.setPhoneNumber(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); cont.setStatus(cursor.getString(cursor.getColumnIndex(ContactsContentProvider.STATUS))); contactList.add(cont); break; } } mCursor.close(); cursor.close(); return contactList; } } 

У вас есть несколько вариантов решения этой проблемы в зависимости от того, как именно вы реализовали свой ListView и Adapter .

  1. notifyDataSetChanged()
  2. Сброс Adapter

Обновление с notifyDataSetChanged ()

Это лучшее решение, но вам нужно изменить List использует Adapter для этого. Например, если вы используете ArrayAdapter следующим образом:

 String[] dataSource = new String[] { "A", "B", "C", ... }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, R.layout.example, dataSource); 

Как вы можете видеть, String[] является источником данных для нашего Adapter . Мы можем изменить такой массив, но эти изменения не будут сразу отражаться в ListView :

 dataSource[0] = "some new String value"; 

Только после того, как мы вызываем notifyDataSetChanged() будет обновлен ListView :

 adapter.notifyDataSetChanged(); 

Из документации :

Public void notifyDataSetChanged ()

Сообщает заинтересованным наблюдателям, что базовые данные были изменены, и любой вид, отражающий набор данных, должен обновиться.

Но НЕ путайте notifyDataSetChanged() с notifyDataSetInvalidated() , потому что notifyDataSetInvalidated() делает что-то совершенно другое и просто испортит ваш ListView .

Из документации :

Public void notifyDataSetInvalidated ()

Сообщает прилагаемым наблюдателям, что базовые данные больше не действительны или недоступны. После этого этот адаптер перестает быть действительным и не должен сообщать о дальнейших изменениях в наборе данных.


Обновление путем сброса Adapter

Это довольно прямолинейно. Каждый раз, когда вы устанавливаете новый Adapter ListView будет обновлять себя. Если вы не можете использовать notifyDataSetChanged() по какой-то причине, тогда вам нужно сделать это так. Просто создайте новый Adapter каждый раз, когда вы хотите обновить ListView :

 ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, R.layout.example, newData); 

И используйте setAdapter() чтобы установить его в ListView :

 listView.setAdapter(adapter); 

Это всегда будет обновлять ListView но есть несколько проблем с этим решением. Прежде всего, каждый раз, когда вы обновляете ListView таким образом, он будет прокручивать назад, что может быть очень неприятно, когда есть частые обновления или когда в ListView много контента.


РЕДАКТИРОВАТЬ:

В коде есть несколько вещей, которые не совсем оптимальны. Прежде всего, ваш Adapter не должен содержать код для загрузки контактов. Он просто не принадлежит, единственная ответственность Adapter заключается в том, что он создает Views из данного источника данных. Поэтому сначала вы должны переместить метод getAllContacts() вне Adapter . Я предлагаю вам создать статический вспомогательный метод для этого, я взял на себя смелость изменить ваш код соответственно:

 public class ContactsHelper { public static List<Contact> getAllContacts(Context context) { List<Contact> contactList = new ArrayList<Contact>(); String URL = "content://com.example.provider.Contacts/contacts"; Uri baseUri1 = Uri.parse(URL); String[] select = {ContactsContentProvider.PHONE_ID, ContactsContentProvider.STATUS}; String where = "((" + ContactsContentProvider.NEEO_USER + " NOTNULL) AND (" + ContactsContentProvider.NEEO_USER + " = 1 )AND (" + ContactsContentProvider.STATUS + " = 1 ))"; Cursor cursor = context.getContentResolver().query(baseUri1, select, where, null, "pid"); for (cursor.moveToFirst(); cursor.moveToNext(); cursor.isAfterLast()) { Log.w("Filtered IDS", "" + cursor.getString(cursor.getColumnIndex(ContactsContentProvider.PHONE_ID)) + "" + cursor.getString(cursor.getColumnIndex(ContactsContentProvider.STATUS))); } Uri baseUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; String[] projection = new String[]{ ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; String selection = "((" + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " != ' ' ))"; String[] selectionArgs = null; String sortOrder = ContactsContract.CommonDataKinds.Phone._ID + " COLLATE LOCALIZED ASC"; Cursor mCursor = context.getContentResolver().query(baseUri, projection, selection, selectionArgs, sortOrder); // Joinging Both Cursors CursorJoiner joiner = new CursorJoiner(cursor, new String[]{ContactsContentProvider.PHONE_ID}, mCursor, new String[]{ContactsContract.CommonDataKinds.Phone._ID}); for (CursorJoiner.Result joinerResult : joiner) { Contact cont = new Contact(); Log.e("Result", joinerResult.toString()); switch (joinerResult) { case LEFT: // handle case where a row in cursorA is unique break; case RIGHT: // handle case where a row in cursorB is unique cont.setID(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID))); cont.setName(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))); cont.setPhoneNumber(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); cont.setStatus("0"); contactList.add(cont); break; case BOTH: // handle case where a row with the same key is in both cursors cont.setID(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID))); cont.setName(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))); cont.setPhoneNumber(mCursor.getString(mCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); cont.setStatus(cursor.getString(cursor.getColumnIndex(ContactsContentProvider.STATUS))); contactList.add(cont); break; } } mCursor.close(); cursor.close(); return contactList; } } 

С помощью этого кода вы можете получить все контакты следующим образом:

 List<Contact> contacts = ContactsHelper.getAllContacts(getActivity()); 

После этого мы должны изменить ваш Adapter так, чтобы notifyDateSetChanged() будет работать:

 private class CustomAdapterForAllContacts extends BaseAdapter { private final List<Contact> contactsList; private final LayoutInflater inflater; public CustomAdapterForAllContacts(Context context, List<Contact> contacts) { this.inflater = LayoutInflater.from(context); this.contactsList = contacts; } @Override public int getCount() { return contactsList.size(); } @Override public Contact getItem(int position) { return contactsList.get(position); } @Override public long getItemId(int position) { return position; } // We expose the List so we can modify it from outside public List<Contact> contacts() { return this.contactsList; } private class SimpleViewHolder { private final SparseArray<View> viewArray = new SparseArray<View>(); private final View convertView; public SimpleViewHolder(View convertView) { this.convertView = convertView; } public View get(int id) { View view = this.viewArray.get(id, null); if(view == null) { view = this.convertView.findViewById(id); this.viewArray.put(id, view); } return view; } } @Override public View getView(int position, View convertView, ViewGroup viewGroup) { // By implementing the view holder pattern you only need to perform // findViewById() once. This will improve the performance of `ListView` // and reduce lag. SimpleViewHolder viewHolder; if (convertView == null) { convertView = this.inflater.inflate(R.layout.list_item, viewGroup, false); viewHolder = new SimpleViewHolder(convertView); convertView.setTag(viewHolder); } viewHolder = (SimpleViewHolder) convertView.getTag(); TextView contName = (TextView) viewHolder.get(R.id.nameText); TextView contNumber = (TextView) viewHolder.get(R.id.numberText); ImageView image = (ImageView) viewHolder.get(R.id.contact_image); Contact contact = getItem(position); String status = contact.getStatus(); if (contact.getStatus().equals("1")) { image.setBackgroundResource(com.example.mycontentprovider.R.drawable.person_empty_online); } else { image.setBackgroundResource(com.example.mycontentprovider.R.drawable.person_empty_offline); } contName.setText(contact.getName()); contNumber.setText(contact.getPhoneNumber()); return view; } } 

Я изменил несколько вещей в этом Adapter . Прежде всего List Contacts теперь окончательный, и я добавил метод contacts() чтобы открыть List чтобы мы могли изменять данные в Adapter снаружи. Я также использовал шаблон держателя вида, чтобы ваш ListView прокручивался быстрее и плавнее!

Надеюсь, я ничего не забыл, но это должны быть все необходимые изменения. Вы можете использовать новый Adapter следующим образом:

 List<Contact> contacts = ContactsHelper.getAllContacts(getActivity()); CustomAdapterForAllContacts adapter = new CustomAdapterForAllContacts(getActivity(), contacts); listView.setAdapter(adapter); 

Если вы хотите позже обновить ListView вам необходимо изменить List внутри Adapter следующим образом:

 List<Contact> newData = ContactsHelper.getAllContacts(getActivity()); adapter.contacts().clear(); adapter.contacts().addAll(newData); adapter.notifyDataSetChanged(); 

Надеюсь, я смогу вам помочь, и если у вас возникнут вопросы, пожалуйста, не стесняйтесь спрашивать!

Если вы находитесь внутри фрагмента, вы можете сделать

 // code for fetching the data // ... // ... ((BaseAdapter) yourlistview.getAdapter()).notifyDataSetChanged(); 
Intereting Posts