Android 刷新同一活动中剩余的当前片段(ListView 数据)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24649960/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:32:56  来源:igfitidea点击:

Refresh Current Fragment (ListView Data) remaining in the same activity

androidlistviewandroid-fragmentsandroid-listview

提问by BST Kaal

Calling a Fragmentfrom an Activity, I am displaying a ListViewwith 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 Fragmentafter i click Show Online. Till now, I have used the following code:

Fragment从 an调用 a Activity,我显示 aListView和两个Buttons。当我点击一个menu_item(即在线显示)时,我正在更新数据,因此ListView. 现在我需要反映更新的数据。Fragment单击“在线显示”后如何刷新。到目前为止,我已经使用了以下代码:

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

But this will restart the whole Activity. I just need to refresh the current Fragment.

但这将重新启动整个Activity. 我只需要刷新当前Fragment.

enter image description hereenter image description here

enter image description hereenter image description here

Edited : Code Added

编辑:添加代码

ACTIVITY CLASS

活动课

    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);
    }

}

Fragment

分段

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;
}

Adapter:

适配器

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;
    }
}  

回答by Xaver Kapeller

You have multiple options to solve this depending on how exactly you implemented your ListViewand Adapter.

您有多种选择来解决这个问题,具体取决于您实现ListViewAdapter.

  1. By calling notifyDataSetChanged()
  2. By resetting the Adapter
  1. 通过调用 notifyDataSetChanged()
  2. 通过重置 Adapter


Updating with notifyDataSetChanged()

使用 notifyDataSetChanged() 更新

This is the best solution there is, but you need to modify the Listthe Adapteris using for this to work. For example if you use an ArrayAdapterlike this:

这是有最好的解决办法,但你需要修改ListAdapter是使用这个工作。例如,如果您使用ArrayAdapter这样的:

String[] dataSource = new String[] {
    "A", "B", "C", ...
};

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

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:

如您所见,String[]是我们的Adapter. 我们可以像这样修改数组,但这些更改不会立即反映在ListView

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

Only once we call notifyDataSetChanged()will the ListViewbe updated:

只有一次我们调用notifyDataSetChanged()才会ListView更新:

adapter.notifyDataSetChanged();

From the documentation:

文档

public void notifyDataSetChanged ()

Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.

public void notifyDataSetChanged()

通知附加的观察者基础数据已更改,任何反映数据集的视图都应自行刷新。

But DO NOTconfuse notifyDataSetChanged()with notifyDataSetInvalidated(), because notifyDataSetInvalidated()does something completely different and would just mess up your ListView.

不要notifyDataSetChanged()notifyDataSetInvalidated(),混淆,因为notifyDataSetInvalidated()它会做一些完全不同的事情,只会弄乱你的ListView.

From the documentation:

文档

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.

public void notifyDataSetInvalidated()

通知附加的观察者基础数据不再有效或可用。一旦调用此适配器就不再有效并且不应报告进一步的数据集更改。



Updating by resetting the Adapter

通过重置更新 Adapter

This is pretty straight forward. Every time you set a new Adapterthe ListViewwill update itself. If you cannot use notifyDataSetChanged()for some reason then you have to do it like this. Just create a new Adapterevery time you want to update your ListView:

这是非常直接的。每次你设置一个新AdapterListView都会更新自己。如果notifyDataSetChanged()由于某种原因无法使用,则必须这样做。Adapter每次要更新时只需创建一个新的ListView

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

And use setAdapter()to set it to the ListView:

并使用setAdapter()将其设置为ListView

listView.setAdapter(adapter);

This will always update the ListViewbut there are a few problems with this solution. First and foremost every time you update the ListViewthis 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.

这将始终更新,ListView但此解决方案存在一些问题。首先,每次以ListView这种方式更新时,它都会滚动回顶部,这在频繁更新或ListView.



EDIT:

编辑:

There are a few things in your code that are not quite optimal. First and foremost, your Adaptershould not contain the code to download the contacts. It just doesn't belong there, the only responsibility of an Adaptershould be that he creates Viewsfrom 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:

您的代码中有一些不太理想的东西。首先,您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;
    }
}

With this code you can get all contacts like this:

使用此代码,您可以获得这样的所有联系人:

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

After this we need to modify your Adapterso that notifyDateSetChanged()will work:

在此之后,我们需要修改您的,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;
    }
}  

I have changed multiple things in this Adapter. First and foremost the Listof Contactsis now final and I added a method contacts()to expose the Listso we can modify the data in the Adapterfrom the outside. I also implemented the view holder pattern so your ListViewscrolls faster and smoother!

我在这方面改变了很多东西Adapter。首先也是最重要的ListofContacts现在是最终的,我添加了一个方法contacts()来公开List以便我们可以Adapter从外部修改数据。我还实现了视图持有者模式,让你的ListView滚动更快更流畅!

I hope I haven't forgotten anything, but this should be all the changes you need. You can use the new Adapterlike this:

我希望我没有忘记任何事情,但这应该是您需要的所有更改。您可以Adapter像这样使用新的:

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

If you want to update the ListViewlater on you need to modify the Listinside the Adapterlike this:

如果ListView以后要更新,则需要像这样修改List内部Adapter

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!

希望我能帮到你,如果你有任何其他问题,请随时提问!

回答by Kaustubh

If you are inside a Fragment then you can do

如果你在一个片段内,那么你可以做

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