2017-11-03 224 views
0

嗯,我有一個應用程序管理聯繫人,我用2 RecyclerView顯示未選中和選定的聯繫人。用戶可以選擇和取消選擇聯繫人。通知*方法不更新RecyclerView的視圖

這裏是我的情況:

我有這兩個RecyclerView,一個用於管理選定的聯繫人和其他用於managin未選擇聯繫人。當用戶從未被選擇的列表中選擇一個聯繫人時,該聯繫人將從該列表中刪除並插入到所選列表中。如果用戶從所選列表中選擇一個聯繫人,只會將聯繫人從所選列表中刪除並插入未選中列表中,同樣的情況也會發生。我有一個自定義的RadioButton已實施,並且在onCheckedChanged事件中,我選擇或取消選擇時將適當的適配器中的聯繫人刪除。

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

例如,如果用戶選擇在未選擇列表中的聯繫人,在onCheckedChanged事件我之前保存的接觸從適配器中(我這樣做是因爲我需要它傳遞給回調,因此可以插入另一個適配器中),然後從適配器中刪除該聯繫人。這觸發SortedListonRemoved方法,在那裏我呼叫notifyItemRemoved(position)position指示被刪除的聯繫人的位置)以及將該聯繫人插入到選定列表中的回調。

由於某些原因,通知*方法不會更新RecyclerView視圖。我試過notifyDataSetChanged,它可以工作,但它不適合我,因爲我需要更新快速,幾乎是瞬間的。

我有2 RecyclerView的發起與FastScroll setNestedScrollingEnabled(false)。以防萬一......

這裏是我的代碼:

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


我有兩個觸點選擇在這裏(「祖母通」和「阿黛拉薩帕塔」):
two_contacts_selected_top two_contacts_selected_bottom


而在這裏,在左邊,我都未被選擇我的第一個項目(聯繫人「Abuela」)。右邊是所有聯繫人列表中取消選擇:
first_contact_unselected unselected_list

回答

0

好了,終於研究的一個星期,我已經找到了解決辦法之後......奇妙的是我懷疑setHasFixedSize(true)有事情做與視圖沒有按」即使更新了項目,也無法重新調整大小或重新繪製...在從2個適配器配置中刪除該行後,所有工作都非常順利...很有趣,我發現解決方案的時間晚於發佈問題的時間。