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"