Recyclerview Viewholder : Oncreateviewholder , View Binding And Onbindviewholder In The Same Class
Solution 1:
As promised I have created a new answer, which does not use reflection. It technically uses two classes (a factory class and a holder class), not one, but is just the same. The code is tested, and it works.
MyAdapter.java
publicclassMyAdapterextendsRecyclerView.Adapter<MyViewHolder>
{
List<Object> _data;
MyViewHolder.Factory _factory;
MyAdapter(List data, MyViewHolder.Factory factory)
{
_data = data;
_factory = factory;
if (_data == null || _factory == null)
{
thrownewNullPointerException("Both data and factory cannot be null!");
}
}
@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
return _factory.createViewHolder(parent, viewType);
}
@OverridepublicvoidonBindViewHolder(MyViewHolder holder, int position)
{
holder.bindViewHolder(_data.get(position));
}
@OverridepublicintgetItemCount()
{
return _data.size();
}
}
MyViewHolder.java
publicabstractclassMyViewHolderextendsRecyclerView.ViewHolder
{
publicinterfaceFactory
{
publicabstract MyViewHolder createViewHolder(ViewGroup parent, int viewType);
}
publicMyViewHolder(View itemView)
{
super(itemView);
}
publicabstractvoidbindViewHolder(Object data);
}
MainActivity.java
publicclassMainActivityextendsAppCompatActivity
{
staticclassNameViewHolderextendsMyViewHolder
{
// If preferred, the following can be created anonymously in codestaticclassFactoryimplementsMyViewHolder.Factory
{
@Overridepublic MyViewHolder createViewHolder(ViewGroup parent, int viewType)
{
Viewv= LayoutInflater.from(parent.getContext()).inflate(R.layout.main_recycler_item, parent, false);
returnnewNameViewHolder(v);
}
};
TextView tv;
NameViewHolder(View v)
{
super(v);
tv = (TextView)v.findViewById(R.id.textView);
}
@OverridepublicvoidbindViewHolder(Object data)
{
tv.setText((String)data);
}
}
@OverrideprotectedvoidonCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbartoolbar= (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButtonfab= (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(newView.OnClickListener()
{
@OverridepublicvoidonClick(View view)
{
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
RecyclerViewrv= (RecyclerView)findViewById(R.id.my_recycler_view);
rv.setHasFixedSize(true);
LinearLayoutManagerlayoutManager=newLinearLayoutManager(this);
rv.setLayoutManager(layoutManager);
ArrayList<String> data = newArrayList();
for (inti=1; i < 100; ++i)
data.add(Integer.toString(1000 + i));
MyAdapteradapter=newMyAdapter(data, newNameViewHolder.Factory());
rv.setAdapter(adapter);
}
}
Solution 2:
I would suggest creating an abstract ViewHolder parent Class. It should have a static instantate method and a bindViewHolder method. Design the Adapter constructor to accept the ViewHolder parent Class object. When used, pass the child Class Object, and in onCreateViewHolder, use Reflection to create the child ViewHolder. When you get an onBindViewHolder, just pass it to the ViewHolder.
Here is a working example. I tested it, and it worked. I have removed non-essential code.
MainActivity.java
publicclassMainActivityextendsAppCompatActivity
{
staticclassNameViewHolderextendsMyViewHolder
{
TextView tv;
publicstatic MyViewHolder instantate(ViewGroup parent, int viewType)
{
Viewv= LayoutInflater.from(parent.getContext()).inflate(R.layout.main_recycler_item, parent, false);
MyViewHoldervh=newNameViewHolder(v);
return vh;
}
NameViewHolder(View v)
{
super(v);
tv = (TextView)v.findViewById(R.id.textView);
}
@OverridepublicvoidbindViewHolder(Object data)
{
tv.setText((String)data);
}
}
@OverrideprotectedvoidonCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerViewrv= (RecyclerView)findViewById(R.id.my_recycler_view);
rv.setHasFixedSize(true);
LinearLayoutManagerlayoutManager=newLinearLayoutManager(this);
rv.setLayoutManager(layoutManager);
ArrayList<String> data = newArrayList();
for (inti=1; i < 100; ++i)
data.add(Integer.toString(1000 + i));
MyAdapteradapter=newMyAdapter(data, NameViewHolder.class);
rv.setAdapter(adapter);
}
}
MyViewHolder.java
publicabstractclassMyViewHolderextendsRecyclerView.ViewHolder
{
// The following has to be declared in sub class. As Java 7 does not support static interface, we commented it out here//public static MyViewHolder instantate(ViewGroup parent, int viewType);publicMyViewHolder(View itemView)
{
super(itemView);
}
publicabstractvoidbindViewHolder(Object data);
}
MyAdapter.java
publicclassMyAdapterextendsRecyclerView.Adapter<MyViewHolder>
{
List<Object> _data;
Class _holderClass;
MyAdapter(List data, Class holderClass)
{
_data = data;
_holderClass = holderClass;
}
@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
MyViewHoldervh=null;
try
{
Class[] cArg = {ViewGroup.class, int.class};
MethodinstantateMethod= _holderClass.getMethod("instantate", cArg);
vh = (MyViewHolder) instantateMethod.invoke(null, parent, viewType);
}
catch (NoSuchMethodException e)
{
e.printStackTrace();
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
return vh;
}
@OverridepublicvoidonBindViewHolder(MyViewHolder holder, int position)
{
holder.bindViewHolder(_data.get(position));
}
@OverridepublicintgetItemCount()
{
return _data.size();
}
}
Solution 3:
You can by making passing R.layout to your RVadapter
staticint layoutResource;
publicRVadapter(Context context, int id){
layoutResource = id;
}
then you can do this in your ViewHolder
if(RVadapter.layoutResource == R.layout.message_layout) {
message_view = (CardView) itemView.findViewById(R.id.card_message);
message_image = (ImageView) itemView.findViewById(R.id.message_image);
message_name = (TextView) itemView.findViewById(R.id.messenger);
message_details = (TextView) itemView.findViewById(R.id.details);
}
elseif(RVadapter.layoutResource == R.layout.guide_layout){
guide_name = (TextView) itemView.findViewById(R.id.new_travel_name);
guide_gendr_age = (TextView) itemView.findViewById(R.id.new_travel_gender_age);
guide_tours = (TextView) itemView.findViewById(R.id.new_travel_tour);
rb = (RatingBar) itemView.findViewById(R.id.new_travel_rb);
}
Post a Comment for "Recyclerview Viewholder : Oncreateviewholder , View Binding And Onbindviewholder In The Same Class"