簡體   English   中英

notify *方法不會更新RecyclerView的視圖

[英]notify* methods doesn't update RecyclerView's view

好吧,我有一個管理聯系人的應用程序,我使用2 RecyclerView顯示未選中和選中的聯系人。 用戶可以選擇和取消選擇聯系人。

這是我的情況:

我有這兩個RecyclerView ,一個用於管理選定的聯系人,另一個用於管理未選定的聯系人。 當用戶從未選擇的列表中選擇一個聯系人時,該聯系人將從該列表中刪除,並插入到所選列表中。 如果用戶從選定列表中選擇一個聯系人,則只有從該選定列表中刪除該聯系人並將其插入未選定列表中時,才會發生同樣的情況。 我實現了一個自定義RadioButton並且在onCheckedChanged事件中, onCheckedChanged選中還是未選中,我都從相應的適配器中刪除該聯系人。

我有一個用於選定列表的適配器( SelectedContactsAdapter ),還有一個用於未選定列表的適配器( UnselectedContactsAdapter )。 我使用新的SortedList集合來管理適配器的數據,並在SortedList的回調中將更改通知給適配器,並發送回調消息以更新其他適配器。

例如,如果用戶在未選擇的列表中選擇一個聯系人,那么在onCheckedChanged事件中,我先保存該聯系人,然后再將其從適配器中刪除(這樣做是因為我需要將其傳遞給回調,以便可以將其插入另一個適配器中),然后從適配器中刪除該聯系人。 觸發該onRemoved所述的方法SortedList並且有我請notifyItemRemoved(position) (與position beign除去的接觸的位置)和插入在所選列表的接觸回調。

由於某種原因,notify *方法不會更新RecyclerView視圖。 我嘗試使用notifyDataSetChanged ,它可以工作,但對我來說不是一個選擇,因為我需要快速,幾乎即時的更新。

我有2個RecyclerViewsetNestedScrollingEnabled(false)啟動的,用於FastScroll。 萬一這很重要...

這是我的代碼:

public abstract class FilterableContactsAdapter extends RecyclerView.Adapter<FilterableContactsAdapter.ContactViewHolder>
        implements Filterable {

    //... Some variables like the filter
    protected Contact mLastContactTouched;
    protected SortedList<Contact> mFilteredContacts;
    protected ContactCallback mContactCallback;
    protected boolean mPropagate;

    public FilterableContactsAdapter() {
        mPropagate = true;
        mFilteredContacts = new SortedList<>(Contact.class, new SortedList.Callback<Contact>() {
            @Override
            public int compare(Contact o1, Contact o2) {
                return o1.getName().compareToIgnoreCase(o2.getName());
            }

            @Override
            public void onChanged(int position, int count) {
                notifyItemChanged(position);
                if(mContactCallback != null && mPropagate) mContactCallback.onContactChanged(mLastContactTouched, position);
            }

            @Override
            public boolean areContentsTheSame(Contact oldItem, Contact newItem) {
                boolean sameIds = (oldItem.getId() == newItem.getId());
                boolean sameNames = oldItem.getName().equals(newItem.getName());
                boolean samePhoneNumbers = oldItem.getNormalizedPhoneNumber().equals(newItem.getNormalizedPhoneNumber());

                if(sameIds && sameNames && samePhoneNumbers) return true;
                else return false;
            }

            @Override
            public boolean areItemsTheSame(Contact item1, Contact item2) {
                return item1.getId() == item2.getId();
            }

            @Override
            public void onInserted(int position, int count) {
                notifyItemInserted(position);
                /*if(FilterableContactsAdapter.this instanceof SelectedContactsAdapter) notifyDataSetChanged();
                else notifyItemInserted(position);*/
                if(mContactCallback != null && mPropagate) mContactCallback.onContactInserted(mLastContactTouched, position);
            }

            @Override
            public void onRemoved(int position, int count) {
                notifyItemRemoved(position);
                /*if(FilterableContactsAdapter.this instanceof SelectedContactsAdapter) notifyDataSetChanged();
                else notifyItemRemoved(position);*/
                if(mContactCallback != null && mPropagate) mContactCallback.onContactRemoved(mLastContactTouched, position);
            }

            @Override
            public void onMoved(int fromPosition, int toPosition) {
                notifyItemMoved(fromPosition, toPosition);
                if(mContactCallback != null && mPropagate) mContactCallback.onContactMoved(mLastContactTouched, fromPosition, toPosition);
            }
        });
    }

    public void add(Contact contact) {
        mFilteredContacts.add(contact);
    }

    public void remove(Contact contact) {
        mFilteredContacts.remove(contact);
    }

    //... Some other methods like onCreateViewHolder, the ContactViewHolder declaration and the filter implementation
}


public interface ContactCallback {
    void onContactInserted(Contact contact, int adapterPosition);
    void onContactRemoved(Contact contact, int adapterPosition);
    void onContactMoved(Contact contact, int from, int to);
    void onContactChanged(Contact contact, int adapterPosition);
}


public class SelectedContactsAdapter extends FilterableContactsAdapter {

    @Override
    public void onBindViewHolder(final ContactViewHolder holder, final int position) {
        final Contact contact = mFilteredContacts.get(position);

        if(contact != null) {
            holder.parentLayout.setVisibility(View.VISIBLE);
            holder.nameTV.setText(contact.getName());
            holder.phoneNumberTV.setText(contact.getNormalizedPhoneNumber());
            holder.selectCB.setSafeCheck(true, SafeCheckBox.IGNORE);
            holder.selectCB.setOnSafeCheckedListener(new SafeCheckBox.OnSafeCheckedListener() {
                @Override
                public void onAlwaysCalledListener(CompoundButton buttonView, boolean isChecked) {

                }

                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    contact.setSelected(isChecked);
                    mLastContactTouched = contact;
                    remove(contact);
                }
            });
        } else {
            holder.parentLayout.setVisibility(View.GONE);
        }
    }
}


public class UnselectedContactsAdapter extends FilterableContactsAdapter {

    @Override
    public void onBindViewHolder(final ContactViewHolder holder, final int position) {
        final Contact contact = mFilteredContacts.get(position);

        if(!contact.isSelected()) {
            holder.parentLayout.setVisibility(View.VISIBLE);
            holder.nameTV.setText(contact.getName());
            holder.phoneNumberTV.setText(contact.getNormalizedPhoneNumber());
            holder.selectCB.setSafeCheck(false, SafeCheckBox.IGNORE);
            holder.selectCB.setOnSafeCheckedListener(new SafeCheckBox.OnSafeCheckedListener() {
                @Override
                public void onAlwaysCalledListener(CompoundButton buttonView, boolean isChecked) {

                }

                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    contact.setSelected(isChecked);
                    mLastContactTouched = contact;
                    remove(contact);
                }
            });
        } else {
            holder.parentLayout.setVisibility(View.GONE);
        }
    }
}


public class ContactsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // init the views and setup the searchbar
        setupMultiContactsPicker();
    }

    //... Some other stuff like an OnClick implementation and 
    //other utility methods that only manage visibility of some
    //components of the UI like 2 TextViews and a ProgressBar



    private void setupMultiContactsPicker() {
        final Filter.FilterListener filterListener = new Filter.FilterListener() {
            @Override
            public void onFilterComplete(int count) {
                progressBar.setVisibility(View.GONE);
                updateLayout();
            }
        };

        unselectedContactsAdapter = new UnselectedContactsAdapter();
        unselectedContactsAdapter.setContactCallback(new ContactCallback() {
            @Override
            public void onContactInserted(Contact contact, int adapterPosition) {
                selectedContactsAdapter.setPropagate(false);
                if(selectedContactsAdapter.getItemCount() > 0) selectedContactsAdapter.remove(contact);
                selectedContactsAdapter.setPropagate(true);
                updateLayout();
            }

            @Override
            public void onContactRemoved(Contact contact, int adapterPosition) {
                selectedContactsAdapter.setPropagate(false);
                selectedContactsAdapter.add(contact);
                selectedContactsAdapter.setPropagate(true);
                updateLayout();
            }

            @Override
            public void onContactMoved(Contact contact, int from, int to) {

            }

            @Override
            public void onContactChanged(Contact contact, int adapterPosition) {

            }
        });
        unselectedContacsRV.setVisibility(View.VISIBLE);
        LinearLayoutManager uLayoutManager = new LinearLayoutManager(ContactsActivity.this, LinearLayoutManager.VERTICAL, false);
        unselectedContacsRV.setLayoutManager(uLayoutManager);
        unselectedContacsRV.setAdapter(unselectedContactsAdapter);
        unselectedContacsRV.setHasFixedSize(true);
        // Initisialize the adapter with the correct contacts (ContactsFilter.UNSELECTED)
        unselectedContactsAdapter.getFilter().filter(FilterableContactsAdapter.ContactsFilter.UNSELECTED, new Filter.FilterListener() {
            @Override
            public void onFilterComplete(int count) {
                onLoadFinish(); //This method call updateLayout(); when the 2 filters finish to load data into the adapters.
            }
        });

        selectedContactsAdapter = new SelectedContactsAdapter();
        selectedContactsAdapter.setContactCallback(new ContactCallback() {
            @Override
            public void onContactInserted(Contact contact, int adapterPosition) {
                unselectedContactsAdapter.setPropagate(false);
                if(unselectedContactsAdapter.getItemCount() > 0) unselectedContactsAdapter.remove(contact);
                unselectedContactsAdapter.setPropagate(true);
                updateLayout(); // This method show or hide some TextViews that I use as section titles, nothing more
            }
            @Override
            public void onContactRemoved(Contact contact, int adapterPosition) {
                unselectedContactsAdapter.setPropagate(false);
                unselectedContactsAdapter.add(contact);
                unselectedContactsAdapter.setPropagate(true);
                updateLayout(); // This method show or hide some TextViews that I use as section titles, nothing more
            }
            @Override
            public void onContactMoved(Contact contact, int from, int to) {

            }
            @Override
            public void onContactChanged(Contact contact, int adapterPosition) {

            }
        });
        LinearLayoutManager sLayoutManager = new LinearLayoutManager(ContactsActivity.this, LinearLayoutManager.VERTICAL, false);
        selectedContacsRV.setLayoutManager(sLayoutManager);
        selectedContacsRV.setAdapter(selectedContactsAdapter);
        selectedContacsRV.setHasFixedSize(true);
        // Initisialize the adapter with the correct contacts (ContactsFilter.SELECTED)
        selectedContactsAdapter.getFilter().filter(FilterableContactsAdapter.ContactsFilter.SELECTED, new Filter.FilterListener() {
            @Override
            public void onFilterComplete(int count) {
                onLoadFinish();
            }
        });
    }
}


以下是我在談論的一些照片:

我在這里選擇了一個聯系人:
one_contact_selected_top one_contact_selected_bottom


我在這里選擇了兩個聯系人(“ Abuela”和“ Adela Zapata”):
two_contacts_selected_top two_contacts_selected_bottom


在這里,我沒有選擇我選擇的第一項(聯系人“ Abuela”)。 右側是未選中所有聯系人的列表:
first_contact_unselected unselected_list

好吧,終於在經過一周的研究后,我找到了解決方案... setHasFixedSize(true)般地,我懷疑setHasFixedSize(true)與視圖有關,即使項目已更新,也不會調整大小或重新繪制...我刪除之后來自2個適配器配置的那條線都工作得很好...有趣的是,我在提出問題后數小時便找到了解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM