刷新同一活动中剩余的当前片段(ListView 数据) [英] Refresh Current Fragment (ListView Data) remaining in the same activity
问题描述
从 Activity
调用 Fragment
,我显示了一个带有两个 Buttons
的 ListView
.当我点击menu_item
(即在线显示)时,我正在更新数据,因此ListView
.现在我需要反映更新的数据.单击在线显示"后如何刷新 Fragment
.到目前为止,我使用了以下代码:
Calling a Fragment
from an Activity
, I am displaying a ListView
with two Buttons
. When I click on a menu_item
(i.e. Show Online), i am updating the data and so the ListView
. Now I need to reflect the updated data. How can i refresh the Fragment
after i click Show Online. Till now, I have used the following code:
Intent intent = getIntent();
Intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);
但这会重启整个Activity
.我只需要刷新当前的 Fragment
.
But this will restart the whole Activity
. I just need to refresh the current 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
的具体方式,您有多种选择来解决这个问题.
You have multiple options to solve this depending on how exactly you implemented your ListView
and Adapter
.
- 通过调用
notifyDataSetChanged()
- 通过重置
Adapter
<小时>
使用 notifyDataSetChanged() 更新
这是最好的解决方案,但您需要修改 Adapter
使用的 List
才能使其工作.例如,如果您使用这样的 ArrayAdapter
:
Updating with notifyDataSetChanged()
This is the best solution there is, but you need to modify the List
the Adapter
is using for this to work. For example if you use an ArrayAdapter
like this:
String[] dataSource = new String[] {
"A", "B", "C", ...
};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, R.layout.example, dataSource);
如您所见,String[]
是我们Adapter
的数据源.我们可以像这样修改数组,但是这些更改不会立即反映在 ListView
中:
As you can see the String[]
is the dataSource for our Adapter
. We can modify the array like this, but those changes will not immediately be reflected in the ListView
:
dataSource[0] = "some new String value";
只有当我们调用 notifyDataSetChanged()
时,ListView
才会更新:
Only once we call notifyDataSetChanged()
will the ListView
be updated:
adapter.notifyDataSetChanged();
来自文档:
public void notifyDataSetChanged()
通知附加的观察者底层数据已经被已更改,任何反映数据集的视图都应自行刷新.
Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
但是不要将 notifyDataSetChanged()
与 notifyDataSetInvalidated()
混淆,因为 notifyDataSetInvalidated()
做了一些完全的事情不同,只会弄乱你的 ListView
.
But DO NOT confuse notifyDataSetChanged()
with notifyDataSetInvalidated()
, because notifyDataSetInvalidated()
does something completely different and would just mess up your ListView
.
来自文档:
public void notifyDataSetInvalidated()
通知附加的观察者底层数据不再有效或可用.一旦调用此适配器就不再有效并且不应报告进一步的数据集更改.
Notifies the attached observers that the underlying data is no longer valid or available. Once invoked this adapter is no longer valid and should not report further data set changes.
<小时>
通过重置Adapter
来更新这很简单.每次设置新的 Adapter
时,ListView
都会自行更新.如果由于某种原因你不能使用 notifyDataSetChanged()
那么你必须这样做.每次要更新 ListView
时,只需创建一个新的 Adapter
:
Updating by resetting the Adapter
This is pretty straight forward. Every time you set a new Adapter
the ListView
will update itself. If you cannot use notifyDataSetChanged()
for some reason then you have to do it like this. Just create a new Adapter
every time you want to update your ListView
:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, R.layout.example, newData);
并使用setAdapter()
将其设置为ListView
:
listView.setAdapter(adapter);
这将始终更新 ListView
但此解决方案存在一些问题.首先,每次以这种方式更新 ListView
时,它都会滚动回顶部,这在频繁更新或 ListView<中有很多内容时会很烦人/代码>.
This will always update the ListView
but there are a few problems with this solution. First and foremost every time you update the ListView
this way it would scroll back to the top which can be quite annoying when there are frequent updates or when there is a lot of content in the ListView
.
您的代码中有一些不太理想的东西.首先,您的 Adapter
不应包含下载联系人的代码.它只是不属于那里,Adapter
的唯一责任应该是他从给定的数据源创建 Views
.因此,首先您应该将 getAllContacts()
方法移到 Adapter
之外.我建议您为此创建静态辅助方法,我冒昧地相应地修改了您的代码:
There are a few things in your code that are not quite optimal. First and foremost, your Adapter
should not contain the code to download the contacts. It just doesn't belong there, the only responsibility of an Adapter
should be that he creates Views
from a given data source. So first you should move the getAllContacts()
method outside of the Adapter
. I suggest you create static helper method for this, I took the liberty of modifying your code accordingly:
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;
}
}
使用此代码,您可以像这样获取所有联系人:
With this code you can get all contacts like this:
List<Contact> contacts = ContactsHelper.getAllContacts(getActivity());
在此之后,我们需要修改您的 Adapter
以便 notifyDateSetChanged()
可以工作:
After this we need to modify your Adapter
so that notifyDateSetChanged()
will work:
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
滚动得更快更流畅!
I have changed multiple things in this Adapter
. First and foremost the List
of Contacts
is now final and I added a method contacts()
to expose the List
so we can modify the data in the Adapter
from the outside. I also implemented the view holder pattern so your ListView
scrolls faster and smoother!
我希望我没有忘记任何事情,但这应该是您需要的所有更改.您可以像这样使用新的 Adapter
:
I hope I haven't forgotten anything, but this should be all the changes you need. You can use the new Adapter
like this:
List<Contact> contacts = ContactsHelper.getAllContacts(getActivity());
CustomAdapterForAllContacts adapter = new CustomAdapterForAllContacts(getActivity(), contacts);
listView.setAdapter(adapter);
如果你想稍后更新ListView
,你需要像这样修改Adapter
中的List
:
If you want to update the ListView
later on you need to modify the List
inside the Adapter
like this:
List<Contact> newData = ContactsHelper.getAllContacts(getActivity());
adapter.contacts().clear();
adapter.contacts().addAll(newData);
adapter.notifyDataSetChanged();
希望我能帮到你,如果你有任何其他问题,请随时提问!
I hope I could help you and if you have any further questions please feel free to ask!
这篇关于刷新同一活动中剩余的当前片段(ListView 数据)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!