刷新同一活动中剩余的当前片段(ListView 数据)
Posted
技术标签:
【中文标题】刷新同一活动中剩余的当前片段(ListView 数据)【英文标题】:Refresh Current Fragment (ListView Data) remaining in the same activity 【发布时间】:2014-08-30 06:13:24 【问题描述】:从Activity
调用Fragment
,我将显示一个ListView
和两个Buttons
。当我单击menu_item
(即在线显示)时,我正在更新数据,因此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;
【问题讨论】:
使用ListFragment
用于那个...
然后呢?有关刷新 Fragment 的 ListFragment 的任何具体内容。
在那个适配器上 .notifyDataSetChanged()
在 Activity Resume()
或任何地方...它会更新您的ListFragment
...
你能告诉我你创建Adapter
的代码吗?并查看我的答案以了解为什么 notifyDataSetChanged()
在您的情况下不起作用。总结:你需要改变Adapter
的数据源,之后调用notifyDataSetChanged()
会刷新ListView
。
尝试使用滑动刷新到您的应用程序。看到这个***.com/questions/41469040/fragment-refresh/…
【参考方案1】:
根据您实现ListView
和Adapter
的具体方式,您有多种选择来解决此问题。
-
致电
notifyDataSetChanged()
通过重置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();
来自documentation:
public void notifyDataSetChanged ()
通知附加的观察者基础数据已被 发生变化,任何反映数据集的视图都应自行刷新。
但是不要将notifyDataSetChanged()
与notifyDataSetInvalidated()
混淆,因为notifyDataSetInvalidated()
做的事情完全不同,只会弄乱你的ListView
。
来自documentation:
public void notifyDataSetInvalidated ()
通知附加的观察者基础数据不再是 有效或可用。一旦调用此适配器不再有效,并且 不应报告进一步的数据集更改。
通过重置Adapter
进行更新
这很简单。每次设置新的Adapter
时,ListView
都会自行更新。如果由于某种原因您不能使用notifyDataSetChanged()
,那么您必须这样做。每次您想更新您的ListView
时,只需创建一个新的Adapter
:
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
中更改了多项内容。首先,Contacts
的 List
现在是最终的,我添加了一个方法contacts()
来公开List
,这样我们就可以从外部修改Adapter
中的数据。我还实现了视图持有者模式,以便您的 ListView
滚动更快更流畅!
我希望我没有忘记任何东西,但这应该是您需要的所有更改。您可以像这样使用新的Adapter
:
List<Contact> contacts = ContactsHelper.getAllContacts(getActivity());
CustomAdapterForAllContacts adapter = new CustomAdapterForAllContacts(getActivity(), contacts);
listView.setAdapter(adapter);
如果你想稍后更新ListView
,你需要像这样修改Adapter
里面的List
:
List<Contact> newData = ContactsHelper.getAllContacts(getActivity());
adapter.contacts().clear();
adapter.contacts().addAll(newData);
adapter.notifyDataSetChanged();
希望能帮到你,如果还有什么问题欢迎追问!
【讨论】:
检查我编辑的问题。 好的,我明白了。您不应该在适配器内执行数据下载。那样的东西不属于那里。在Adapter
中用作数据源的List
通常应该是最终的,而不是像您那样处理。我将根据一些建议编辑我的答案。
我已经更新了我的答案!如果您还有其他问题,请随时提问。
我来看看,如果我建议使用不同的方法来加载数据,您会不会感到困扰?你必须使用LoaderManager
吗? CursorJoiner
呢?
我已经使用了 CursorJoing 和它的工作方式,就像你说的那样。但是,如果我的实际通讯录中发生更改,我需要在运行时反映更改。这就是为什么我使用 LoaderManager。【参考方案2】:
如果你在 Fragment 中,那么你可以这样做
// code for fetching the data
// ...
// ...
((BaseAdapter) yourlistview.getAdapter()).notifyDataSetChanged();
【讨论】:
以上是关于刷新同一活动中剩余的当前片段(ListView 数据)的主要内容,如果未能解决你的问题,请参考以下文章
每 2 秒刷新一次从 JSON 响应中填充的 listView
listview 没有在带有 viewpager 选项卡的片段中刷新