2016-10-09 10 views
9

यह सैद्धांतिक प्रश्न होगा।व्यूहोल्डर में बाध्यकारी

हर किसी के रूप में हम ऐप के कई हिस्सों में रीसाइक्लिंग व्यू का उपयोग करते हैं। कभी-कभी रीसाइक्लर व्यू में अलग-अलग आइटम होते हैं, उदाहरण के लिए न केवल छवि, बल्कि विज्ञापन, संकेत इत्यादि। और यही कारण है कि हम एडाप्टर में getViewType() विधि का उपयोग कर सकते हैं।

लेकिन समस्या तब होती है जब हमारे पास कई दृश्य होते हैं और एडाप्टर में बाध्यकारी सुरुचिपूर्ण नहीं है। तो यहां सवाल है, क्या व्यूहोल्डर में डेटा को बांधने के लिए यह अच्छा और अच्छा पैटर्न है?

मान लें कि हमारे पास ऐप्स की सूची है।

प्रत्येक ऐप में सादगी के लिए नाम है। हमारे ViewHolder इस तरह दिखता है:

class AppViewHolder extends RecyclerView.ViewHolder { 

    public TextView nameText; 

    AppViewHolder(View itemView) { 
      super(itemView) 
      nameText = (TextView) itemView.findViewById(R.id.text_name); 
    } 
} 

अब हम बाँध विधि जोड़ सकते हैं:

public void bind(App app) { 
    nameText.setText(app.getName()); 
} 

यह अच्छा पैटर्न है?

एक और समाधान ViewModel का उपयोग करेगा। चूंकि हमारे पास RecyclerView में अलग-अलग आइटम हैं, इसलिए हमारे एडाप्टर में कक्षा की सूची हो सकती है जो प्रत्येक व्यूमोडेल के लिए बेस क्लास है।

तो बुनियादी वर्ग है:

class RecyclerViewItem {} 

अब वर्ग है, जो एप्लिकेशन के लिए ViewModel है।

class AppRecyclerViewItem extends RecyclerViewItem { 

    App app; 

    ... 
} 

और हमारे एडाप्टर सिर्फ RecyclerViewItems की सूची है:

class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { 

    List<RecyclerViewItem> items; 

    ... 
} 
इस दृष्टिकोण (मैं ViewModel का उपयोग कर मतलब) यह ViewHolder में बाँध विधि जोड़ने के लिए बेहतर है, या ViewModel में साथ

तो?

उत्तर

6

मैं कहूंगा कि आपके कोई भी समाधान अच्छा नहीं है। पहला आइटम केवल वस्तुओं के लिए अच्छा है, जो एडाप्टर में केवल एक बार दिखाई देता है। ViewHolder के अंदर पंक्ति भरने के लिए एक विधि बनाना एक अच्छा समाधान नहीं है क्योंकि विभिन्न प्रकार के ViewHolders बढ़ेगा और आपके RecyclerView.Adapter अधिक से अधिक लाइनें प्राप्त करेंगे।

दूसरी विधि भी अच्छी नहीं है। मॉडल मॉडल है, केवल डेटा होना चाहिए और आवेदन के व्यावसायिक तर्क नहीं होना चाहिए।

मैं RecyclerView.Adapter को ViewHolder बनाने और उन्हें प्रतिनिधियों को डेटा भरने के तर्क को सुरक्षित और पास रखने का एक समाधान सुझाता हूं, जो कि यानी पंजीकृत होगा। RecyclerView.Adapter कन्स्ट्रक्टर। इस तकनीक को और अधिक here

इस तरह से समझाया गया है, यहां तक ​​कि विभिन्न ViewHolder की Doven expecially RecyclerView.Adapter को बॉयलरप्लेट नहीं जोड़ता है से अधिक दर्ज की गई है, लेकिन प्रतिनिधियों बनाने और उन प्रतिनिधियों के लिए RecyclerView.Adapter पंक्तियों को भरने के तर्क।

लेकिन यह सिर्फ एक सुझाव है।

+0

मुझे लगता है कि पहली विधि अच्छी है क्योंकि विशेष रूप से पुनर्नवीनीकरण में बाइंडव्यूहोल्डर डब्ल्यू ई कॉलधारक में बाध्य करें, इसलिए एडाप्टर को कई लाइनें नहीं मिलेंगी। लेकिन मुझे आपके द्वारा सुझाए गए विचार पसंद हैं, मैं इसमें डुबकी लगाऊंगा। – ThirdMartian

+2

क्या आप इस काम का उपयोग अपने काम पर कर रहे हैं? क्या आप अपना अनुभव साझा कर सकते हैं? – ThirdMartian

0

मेरी क्षुधा के लिए मैं कुछ इस तरह का उपयोग कर:

public abstract class BindableViewHolder<T> extends RecyclerView.ViewHolder { 
    public BindableViewHolder(View itemView) { 
     super(itemView); 
    } 

    public abstract void bind(T thing); 
} 

विचार प्रतिनिधि को ViewHolder के लिए बाध्य के कार्यान्वयन है। यह समाधान उन मामलों के लिए है जब आप विभिन्न दृश्यधारकों को उसी प्रकार की ऑब्जेक्ट बाध्य करना चाहते हैं, लेकिन मुझे लगता है कि यह अधिक सामान्य मामलों में आसानी से विस्तार योग्य है।

यहां एक बहुत ही सरल एडाप्टर का उदाहरण दिया गया है। मुझे लगता है कि यह खुद को समझाता है, उम्मीद है कि यह मदद करता है! http://hannesdorfmann.com/android/adapter-delegates और यह और भी (साधारण परिवर्तन, https://github.com/drstranges/DataBinding_For_RecyclerView के साथ) DataBinding के लिए इस्तेमाल किया जा सकता है -

public class ShowsAdapter extends RecyclerView.Adapter<BindableViewHolder<Show>> { 

    private final DataProvider<Show> showsProvider; 

    public ShowsAdapter(DataProvider<Show> showsProvider) { 
     this.showsProvider = showsProvider; 
    } 

    @Override 
    public BindableViewHolder<Show> onCreateViewHolder(ViewGroup parent, int viewType) { 
     return ShowViewHolder.create(parent); 
    } 

    @Override 
    public void onBindViewHolder(BindableViewHolder<Show> holder, int position) { 
     holder.bind(showsProvider.get(position)); 
    } 

    @Override 
    public int getItemCount() { 
     return showsProvider.size(); 
    } 
} 

यहाँ, ShowViewHolder BindableViewHolder का एक ठोस उपवर्ग,

0

वहाँ प्रतिनिधियों का उपयोग कर महान समाधान है। इस तरह डेटा को व्यूहोल्डर में नहीं जोड़ा गया है और रीसाइक्लर व्यू एडाप्टर में नहीं है लेकिन आइटम डिलीगेट ऐसा करता है, इसलिए आपका कोड स्पष्ट और पठनीय रहता है।

इस दृष्टिकोण दृश्य-प्रकार के साथ सभी काम DelegateManager को प्रत्यायोजित के बाद:

public abstract class AbsDelegationAdapter<T> extends RecyclerView.Adapter { 

protected AdapterDelegatesManager<T> delegatesManager; 
protected T items; 
//... 

    @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     return delegatesManager.onCreateViewHolder(parent, viewType); 
    } 

    @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
     delegatesManager.onBindViewHolder(items, position, holder); 
    } 

    @Override public int getItemViewType(int position) { 
     return delegatesManager.getItemViewType(items, position); 
    } 
} 

और अपने कोड इस तरह दिखेगा:

mAdapter = new BindableAdapter<>(
     new UserDelegate(actionHandler), // you can create custom delegate 
     //new ModelActionItemDelegate<BaseModel>(actionHandler, User.class, R.layout.item_user, BR.user), // or use generic 
     new AnotherItemDelegate()); 

ItemDelegate कहाँ इस तरह दिख सकता:

public class UserDelegate extends BaseAdapterDelegate<BaseModel, ItemUserBinding> { 

    @Override 
    public boolean isForViewType(@NonNull final List<BaseModel> items, final int position) { 
     return items.get(position) instanceof User; 
    } 

    @NonNull 
    @Override 
    public BindingHolder<ItemUserBinding> onCreateViewHolder(final ViewGroup parent) { 
     // create ViewHolder 
     return BindingHolder.newInstance(R.layout.item_user, LayoutInflater.from(parent.getContext()), parent, false); 
    } 

    @Override 
    public void onBindViewHolder(@NonNull final List<BaseModel> items, final int position, @NonNull final BindingHolder<ItemUserBinding> holder) { 
     // Just bind data 
     final User user = (User) items.get(position); 
     holder.getBinding().setUser(user); 
    } 

} 
संबंधित मुद्दे