android - 刷新同一 Activity 中剩余的当前 fragment (ListView 数据)

标签 android listview android-fragments android-listview

Activity 调用一个 Fragment,我正在显示一个带有两个 ButtonListView。当我单击 menu_item(即 Show Online)时,我正在更新数据以及 ListView。现在我需要反射(reflect)更新的数据。单击 Show Online 后如何刷新 Fragment。到目前为止,我使用了以下代码:

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

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

enter image description here enter image description here

已编辑:已添加代码

Activity 课

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

适配器:

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

最佳答案

根据您实现 ListViewAdapter 的具体方式,您有多种选择来解决这个问题。

  1. 通过调用 notifyDataSetChanged()
  2. 通过重置适配器

使用 notifyDataSetChanged() 更新

这是目前最好的解决方案,但您需要修改 Adapter 正在使用的 List 才能工作。例如,如果您像这样使用 ArrayAdapter:

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

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

如您所见,String[] 是我们的Adapter 的数据源。我们可以像这样修改数组,但这些更改不会立即反射(reflect)在 ListView 中:

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

只有在调用 notifyDataSetChanged() 后,ListView 才会更新:

adapter.notifyDataSetChanged();

来自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.

不要notifyDataSetChanged()notifyDataSetInvalidated()混淆,因为notifyDataSetInvalidated()做的事情完全不同,只会弄乱您的 ListView

来自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.


通过重置适配器进行更新

这很简单。每次设置新的 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 中改变了很多东西。首先,ContactsList 现在是最终的,我添加了一个方法 contacts() 来公开 List所以我们可以从外部修改Adapter中的数据。我还实现了 View 持有者模式,因此您的 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();

希望能帮到您,如果您还有其他问题,请随时提问!

关于android - 刷新同一 Activity 中剩余的当前 fragment (ListView 数据),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24649960/

相关文章:

android - BroadcastReceiver 多次触发 (PROVIDERS_CHANGED_ACTION)

Android:捕获和存储图片

android - Jetpack Compose - 修饰符的顺序

android - SimpleCursorAdapter - 绑定(bind)到 ListView 中的多个项目值

android - 如何到达 ListView 的底部,加载更多项目

android - 无法单击 Horizo​​ntalScrollView 中的列表项

android - 使用 ViewPager 跨多个 TextViews/Fragments 拆分文本

android - 二进制 XML 文件第 7 行 : Duplicate id 0xffffffff, 标记对话框,或带有另一个 fragment 的父 ID 0x0

java - 如何从 fragment 中的工具栏在 ListView 中搜索

android - 重用 Fragment 或布局文件