2016-10-09 28 views
9

這將是理論上的問題。在ViewHolder中綁定

正如我們每個人在應用的許多部分使用RecyclerView。有時RecyclerView包含不同的項目,不僅僅是圖像,而且包含廣告,提示等。這就是爲什麼我們可以在Adapter中使用getViewType()方法。

但是,當我們有很多viewTypes並且在Adapter中綁定這個問題時,問題就不是很好。所以這裏有個問題,在ViewHolder中綁定數據是否好又好?

假設我們有應用程序列表。

每個應用程序都有簡潔的名稱。我們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中有不同的項目,所以我們的適配器可以包含每個ViewModel基類的類列表。

所以基本類:

class RecyclerViewItem {} 

現在類是視圖模型爲App。

class AppRecyclerViewItem extends RecyclerViewItem { 

    App app; 

    ... 
} 

和我們的適配器只是有RecyclerViewItems的名單:

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

    List<RecyclerViewItem> items; 

    ... 
} 

所以用這個方法(我的意思是使用視圖模型)是它更好地在ViewHolder添加綁定方法,或視圖模型?

回答

6

我會說,你的解決方案都不是好的。 第一個只適用於在適配器中只出現一次的項目。創建一個方法來填充ViewHolder內的行不是一個好的解決方案,因爲不同類型的ViewHolders會增長,您的RecyclerView.Adapter會獲得越來越多的線。

第二種方法也不好。模型是模型,應該只包含數據而不包含應用程序的業務邏輯。

我會建議一個解決方案,以保持RecyclerView.Adapter清潔,並傳遞邏輯創建ViewHolder並填充它們的數據給委託,這將在ie中註冊。 RecyclerView.Adapter構造函數。 這種技術被解釋更here

這樣,即使在不同的ViewHolder的doven不expecially加樣板到RecyclerView.Adapter註冊,但代表創建和填充RecyclerView.Adapter行的那些代表的邏輯。

但這只是一個建議。

+0

我覺得第一種方法很好,尤其是因爲在recyclerview onBindViewHolder w e調用在視圖中綁定,所以適配器不會獲得很多行。但我喜歡你提出的想法,我會深入研究它。 – 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實施。此解決方案適用於想要將與同類對象綁定到不同視圖的情況,但我認爲它很容易擴展到更一般的情況。

下面是一個非常簡單的適配器的例子。我認爲它解釋了自己,希望它有幫助!

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

有使用委託很好的解決方案 - http://hannesdorfmann.com/android/adapter-delegates,它甚至可以用於數據綁定(簡單的變化,https://github.com/drstranges/DataBinding_For_RecyclerView)。通過這種方式,數據綁定不在ViewHolder中,不在RecyclerView適配器中,但是ItemDelegate執行此操作,因此您的代碼仍然清晰易讀。

按照這一辦法與視圖類型所有的工作委託給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); 
    } 

} 
相關問題