Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Eliminate RecyclerView Boilerplates

Eliminate RecyclerView Boilerplates

Layout and RecyclerView.ViewHolder binding which uses annotation processor to eliminate RecyclerView boilerplates for Android development.

ViewHolderBinding enables you to eliminate..
- switch or if-else statements for ViewType detection
- layout inflation boilerplate codes
- casting RecyclerView.ViewHolder class for binding layouts and ViewHolders

* GitHub repository
https://github.com/shaunkawano/ViewHolderBinding

* potatotips #37 (iOS/Android開発Tips共有会) - connpass https://potatotips.connpass.com/event/48618/

Shohei Kawano

February 15, 2017
Tweet

More Decks by Shohei Kawano

Other Decks in Technology

Transcript

  1. RecyclerView.Adapter basic methods void onBindViewHolder(VH holder, int position) VH onCreateViewHolder(ViewGroup

    parent, int viewType) int getItemViewType(int position) int getItemCount()
  2. RecyclerView.Adapter basic methods void onBindViewHolder(VH holder, int position) VH onCreateViewHolder(ViewGroup

    parent, int viewType) int getItemViewType(int position) int getItemCount()
  3. @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater

    = LayoutInflater.from(parent.getContext()); switch (viewType) { case R.layout.row_taro:
 View taroView = inflater.inflate(R.layout.row_taro, parent, false);
 return new TaroViewHolder(taroView);
 case R.layout.row_shiro:
 View shiroView = inflater.inflate(R.layout.row_shiro, parent, false);
 return new ShiroViewHolder(shiroView);
 case R.layout.row_leona:
 View leonaView = inflater.inflate(R.layout.row_leona, parent, false);
 return new LeonaViewHolder(leonaView);
 default:
 throw new IllegalArgumentException(“error message here.”);
 }
 } onCreateViewHolder
  4. onBindViewHolder @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int

    viewType = getItemViewType(position);
 switch (viewType) { case R.layout.row_taro:
 onBindTaroViewHolder((TaroViewHolder) holder, position); break; case R.layout.row_shiro:
 onBindShiroViewHolder((ShiroViewHolder) holder, position); break; case R.layout.row_leona:
 onBindLeonaViewHolder((LeonaViewHolder) holder, position); break;
 default:
 throw new IllegalArgumentException(“Some message.”);
 } }
  5. @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int viewType

    = getItemViewType(position);
 switch (viewType) { case R.layout.row_taro:
 onBindTaroViewHolder((TaroViewHolder) holder, position); break; case R.layout.row_shiro:
 onBindShiroViewHolder((ShiroViewHolder) holder, position); break; case R.layout.row_leona:
 onBindLeonaViewHolder((LeonaViewHolder) holder, position); break;
 default:
 throw new IllegalArgumentException(“Some message.”);
 } } onBindViewHolder
  6. @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int viewType

    = getItemViewType(position);
 switch (viewType) { case R.layout.row_taro:
 onBindTaroViewHolder((TaroViewHolder) holder, position); break; case R.layout.row_shiro:
 onBindShiroViewHolder((ShiroViewHolder) holder, position); break; case R.layout.row_leona:
 onBindLeonaViewHolder((LeonaViewHolder) holder, position); break;
 default:
 throw new IllegalArgumentException(“Some message.”);
 } } onBindViewHolder 8FOFFEUPDBTUʜ
  7. RecyclerView.Adapter Overview @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    int viewType = getItemViewType(position);
 switch (viewType) { case R.layout.row_taro:
 onBindTaroViewHolder((TaroViewHolder) holder, position); break; case R.layout.row_shiro:
 onBindShiroViewHolder((ShiroViewHolder) holder, position); break; case R.layout.row_leona: onBindLeonaViewHolder((LeonaViewHolder) holder, position); break;
 default:
 throw new IllegalArgumentException(“Some message.”);
 } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); switch (viewType) { case R.layout.row_taro:
 View taroView = inflater.inflate(R.layout.row_taro, parent, false);
 return new TaroViewHolder(taroView);
 case R.layout.row_shiro:
 View shiroView = inflater.inflate(R.layout.row_shiro, parent, false);
 return new ShiroViewHolder(shiroView);
 case R.layout.row_leona:
 View leonaView = inflater.inflate(R.layout.row_leona, parent, false);
 return new LeonaViewHolder(leonaView);
 default:
 throw new IllegalArgumentException(“error message here.”);
 }
 }
  8. RecyclerView.Adapter Overview @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    int viewType = getItemViewType(position);
 switch (viewType) { case R.layout.row_taro:
 onBindTaroViewHolder((TaroViewHolder) holder, position); break; case R.layout.row_shiro:
 onBindShiroViewHolder((ShiroViewHolder) holder, position); break; case R.layout.row_leona: onBindLeonaViewHolder((LeonaViewHolder) holder, position); break;
 default:
 throw new IllegalArgumentException(“Some message.”);
 } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); switch (viewType) { case R.layout.row_taro:
 View taroView = inflater.inflate(R.layout.row_taro, parent, false);
 return new TaroViewHolder(taroView);
 case R.layout.row_shiro:
 View shiroView = inflater.inflate(R.layout.row_shiro, parent, false);
 return new ShiroViewHolder(shiroView);
 case R.layout.row_leona:
 View leonaView = inflater.inflate(R.layout.row_leona, parent, false);
 return new LeonaViewHolder(leonaView);
 default:
 throw new IllegalArgumentException(“error message here.”);
 }
 }
  9. RecyclerView.Adapter Overview @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    int viewType = getItemViewType(position);
 switch (viewType) { case R.layout.row_taro:
 onBindTaroViewHolder((TaroViewHolder) holder, position); break; case R.layout.row_shiro:
 onBindShiroViewHolder((ShiroViewHolder) holder, position); break; case R.layout.row_leona: onBindLeonaViewHolder((LeonaViewHolder) holder, position); break;
 default:
 throw new IllegalArgumentException(“Some message.”);
 } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); switch (viewType) { case R.layout.row_taro:
 View taroView = inflater.inflate(R.layout.row_taro, parent, false);
 return new TaroViewHolder(taroView);
 case R.layout.row_shiro:
 View shiroView = inflater.inflate(R.layout.row_shiro, parent, false);
 return new ShiroViewHolder(shiroView);
 case R.layout.row_leona:
 View leonaView = inflater.inflate(R.layout.row_leona, parent, false);
 return new LeonaViewHolder(leonaView);
 default:
 throw new IllegalArgumentException(“error message here.”);
 }
 } #PJMFSQMBUFTʜ
  10. RecyclerView Boilerplates void onBindViewHolder(VH holder, int position) VH onCreateViewHolder(ViewGroup parent,

    int viewType) ɾ*OTUBOUJBUFDVTUPN7JFX)PMEFSDMBTTCBTFEPOWJFX5ZQF ɾ0CUBJOWJFX5ZQFGSPNQPTJUJPO ɾ$BTU7JFX)PMEFSUPDVTUPN7JFX)PMEFSCBTFEPOQPTJUJPO
  11. @Override public int getItemViewType(int position) {
 switch (CatType.of(position)) {
 case

    TARO:
 return R.layout.row_taro;
 case SHIRO:
 return R.layout.row_shiro;
 case LEONA:
 return R.layout.row_leona;
 default:
 throw new IllegalArgumentException(“Some message.”);
 }
 } Implement RecyclerView.Adapter#getItemViewType()
  12. @Override public int getItemViewType(int position) {
 switch (CatType.of(position)) {
 case

    TARO:
 return R.layout.row_taro;
 case SHIRO:
 return R.layout.row_shiro;
 case LEONA:
 return R.layout.row_leona;
 default:
 throw new IllegalArgumentException(“Some message.”);
 }
 } Implement RecyclerView.Adapter#getItemViewType() Return R.layout.id as view type
  13. @AdapterBinding public class CatAdapter extends RecyclerView.Adapter { … } @ViewHolder(layout

    = R.layout.row_title) static class TitleViewHolder extends RecyclerView.ViewHolder {
 TitleViewHolder(View itemView) {
 super(itemView);
 } 
 
 @OnBind void onBind() {
 // bind layouts
 }
 … Add @AdapterBinding ,@ViewHolder, @OnBind (optional) annotations
  14. @AdapterBinding public class CatAdapter extends RecyclerView.Adapter { … } @ViewHolder(layout

    = R.layout.row_title) static class TitleViewHolder extends RecyclerView.ViewHolder {
 TitleViewHolder(View itemView) {
 super(itemView);
 } 
 
 @OnBind void onBind() {
 // bind layouts
 }
 … Add @AdapterBinding ,@ViewHolder, @OnBind (optional) annotations Add on RecyclerView.Adapter Add on RecyclerView.ViewHolder Add on inner methods within RecyclerView.ViewHolder
  15. Call static methods within generated class @Override public void onBindViewHolder(RecyclerView.ViewHolder

    holder, int position) { CatAdapterViewHolderBinding.bindViewHolder(this, holder, position); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); return CatAdapterViewHolderBinding.createViewHolder(inflater, parent, viewType); }
  16. Call static methods within generated class @Override public void onBindViewHolder(RecyclerView.ViewHolder

    holder, int position) { CatAdapterViewHolderBinding.bindViewHolder(this, holder, position); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); return CatAdapterViewHolderBinding.createViewHolder(inflater, parent, viewType); } Adapter໊ʴViewHolderBinding.bindViewHolder Adapter໊ʴViewHolderBinding.bindViewHolder.createViewHolder
  17. class CatAdapterViewHolderBinding { public static ViewHolder createViewHolder(LayoutInflater inflater, ViewGroup parent,

    int viewType) { switch (viewType) { case 2130968636: View TaroViewHolderView = inflater.inflate(2130968636, parent, false); return new CatAdapter.TaroViewHolder(TaroViewHolderView); case 2130968635: View ShiroViewHolderView = inflater.inflate(2130968635, parent, false); return new CatAdapter.ShiroViewHolder(ShiroViewHolderView); case 2130968634: View LeonaViewHolderView = inflater.inflate(2130968634, parent, false); return new CatAdapter.LeonaViewHolder(LeonaViewHolderView); case 2130968637: View TitleViewHolderView = inflater.inflate(2130968637, parent, false); return new CatAdapter.TitleViewHolder(TitleViewHolderView); default: throw new IllegalArgumentException(String.format(Locale.US, "Illegal viewType(%d) passed to CatAdapter.", viewType)); } } Generated method: createViewHolder
  18. Generated method: bindViewHolder public static void bindViewHolder(Adapter adapter, ViewHolder holder,

    int position) { int viewType = adapter.getItemViewType(position); switch (viewType) { case 2130968636: ((CatAdapter.TaroViewHolder) holder).onBind(); break; case 2130968635: ((CatAdapter.ShiroViewHolder) holder).onBind(); break; case 2130968634: ((CatAdapter.LeonaViewHolder) holder).onBind(position); break; case 2130968637: ((CatAdapter.TitleViewHolder) holder).onBind(); break; default: throw new IllegalArgumentException(String.format(Locale.US, "Illegal viewType(%d) passed to CatAdapter.", viewType)); } } }
  19. ɾGenerating codes using Annotation Processor is fun! ɾWe’ll keep using

    RecyclerView for sure, so ɾLet us write less to do more! ·ͱΊ