Data on recycleview item is not correct when scroll - android

My adapter code:
public class BrandAdapter extends RecyclerView.Adapter<BrandAdapter.BrandViewHolder> {
private static final String TAG = BrandAdapter.class.getSimpleName();
private List<BrandItem> brands;
private Context context;
public BrandAdapter(Context context, List<BrandItem> data) {
this.context = context;
this.brands = data;
}
public void setData(List<BrandItem> dataDownload) {
this.brands = dataDownload;
}
#Override
public BrandViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item_brand, null);
BrandViewHolder holder = new BrandViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(BrandViewHolder holder, int position) {
BrandItem brandItem = brands.get(position);
String name = brandItem.getName();
int count = brandItem.getCountArticles();
holder.tvName.setText(name);
if (count > 0) {
holder.tvCount.setText("" + count);
} else {
holder.tvCount.setVisibility(View.GONE);
}
}
#Override
public int getItemCount() {
return brands.size();
}
public static class BrandViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
TextView tvCount;
public BrandViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tv_brand_name);
tvCount = (TextView) itemView.findViewById(R.id.tv_count_article);
}
}
}
Fragment code :
recyclerView = (RecyclerView) view.findViewById(R.id.recycleView);
linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
adapter = new BrandAdapter(getActivity(), brands);
recyclerView.setAdapter(adapter);
Data for brands is downloaded from server. After downloaded finished, I just set new data for adapter by this code :
brands = downloadedBrands();
adapter.setData(brands);
adapter.notifyDataSetChanged();
Everything is Ok when data loaded for first time after the download finish. But when I scroll down the recycleview and scroll up again, data for each item is wrong now, all textview tvCount is gone. I do not know why.
Is there any problem from my code ?

Greenrobo's answer is correct but here is an explanation as to WHY you are having this issue.
You are assuming that your view is always set to the default values in your onBindViewHolder method.
The RecyclerView re-uses views that have scrolled off screen and therefore the view you are binding to may have already been previously used (and changed).
You onBindViewHolder method should always set EVERYTHING up. i.e all views reset to the exact values you want and do not assume that because you default an item to visible, it will always be so.

Please make tvCount visible when setting a non-zero count.
if (count > 0) {
holder.tvCount.setText("" + count);
holder.tvCount.setVisibility(View.VISIBLE);
} else {
holder.tvCount.setVisibility(View.GONE);
}
See if this helps.

You told that if count is less than 0, hide the view. What if count is greater than zero ? You are not making the view visible again. So simply make the below changes in your if condition:
if (count > 0) {
holder.tvCount.setText("" + count);
holder.tvCount.setVisibility(View.VISIBLE);
} else {
holder.tvCount.setVisibility(View.GONE);
}

Related

Removing element from adapter throws Index out of bound exception

I have two recycler views. The first recyclerview is basically a list of data where I can choose an item and its quantity and I am storing this chosen item data into a map. The second one is the list of the selected data. which I am generating from getting the values() from the map. The second one also has similar viewholder and I can change the quantity there also. One the quantity reaches zero I remove the item from the list and try to notifydatasetChanged().
The problem is the removing of an item from the second list is not working properly and the app crashes with error
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder
I am using a listener interface on my first Recycler so that when the quantity is changed and the item is added to the map. The adapter of the second recycler is notified of the changes. below is the code i am using to update the second recycler view.
public void updateList(){
mMap = ((UserMainActivity)getActivity()).getItemMap();
inputs.clear();
// adapter.notifyDataSetChanged();
adapter = new MyCartAdapter(inputs,getContext());
cartList.setAdapter(adapter);
for(AllItems t:mMap.values()) {
inputs.add(t);
}
adapter.notifyDataSetChanged();
}
Below is my second recycler view's adapter. Where I am changing the quantities of the selected items.
public class MyCartAdapter extends RecyclerView.Adapter<MyCartAdapter.MyCartViewHolder>{
private List<AllItems> listItems1;
private Context context;
private Typeface typeface;
public MyCartAdapter(List<AllItems> listItems1, Context context) {
this.listItems1 = listItems1;
this.context = context;
}
#NonNull
#Override
public MyCartAdapter.MyCartViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cart_items_layout, parent, false);
return new MyCartViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull final MyCartAdapter.MyCartViewHolder holder, final int position) {
final AllItems orderItem = listItems1.get(position);
holder.setProductImage(orderItem.getImageUrl(),context);
holder.name.setText(orderItem.getName());
String price = String.valueOf(orderItem.getPrice());
holder.price.setText(price);
final HashMap<String, AllItems> items = ((UserMainActivity)context).getItemMap();
holder.counter.setText(orderItem.getQuantity());
holder.add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String quantity = String.valueOf(holder.counter.getText());
int count = Integer.parseInt(quantity)+1;
holder.counter.setText(String.valueOf(count));
String url = orderItem.getImageUrl();
AllItems newitem = new AllItems(orderItem.getName(),orderItem.getComname(),url, String.valueOf(count),orderItem.getWeight,orderItem.getPrice());
((UserMainActivity)context).addItem(orderitemname,newitem);
// notifyItemChanged(position);
}
});
//counter text iitem.textview showing the quantity of the selected item . integer count returns the value of counter text below i am checking if its zero than it simply sets the value to zero and else reduce it and update the map.
holder.minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String counterText = String.valueOf(holder.counter.getText());
int count = Integer.parseInt(counterText);
if (count==0){
holder.counter.setText("0");
}
if (count==1){
holder.counter.setText("0");
AllItems item = items.get(orderItem.getName());
if (item!=null){
String orderit = orderItem.getName();
((UserMainActivity)context).removeItem(orderit);
// here i am removing the value from the list which throws the exception
listItems1.remove(position);
notifyItemRemoved(position);
}
}
if (count>1){
String quantity = String.valueOf(count-1);
holder.counter.setText(quantity);
String orderitemname = orderItem.getName();
String url = orderItem.getImageUrl();
String weight = "100";
long weightl = Long.parseLong(weight);
AllItems newitem = new AllItems(orderItem.getName(),orderItem.getComname(),url, quantity,weight,orderItem.getPrice());
((UserMainActivity)context).addItem(orderitemname,newitem);
// listItems1.set(position, newitem);
// notifyItemChanged(position);
}
}
});
}
#Override
public int getItemCount() {
return listItems1.size();
}
public class MyCartViewHolder extends RecyclerView.ViewHolder {
public TextView name,price,count,comname;
public TextView weight;
LinearLayout add,minus;
TextView counter;
public MyCartViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.ProName);
price = (TextView) itemView.findViewById(R.id.proPrice);
weight = (TextView) itemView.findViewById(R.id.ProWeight);
counter = (TextView) itemView.findViewById(R.id.counter);
add = (LinearLayout) itemView.findViewById(R.id.addLin);
minus= (LinearLayout) itemView.findViewById(R.id.minusLin);
}
public void setProductImage(final String thumb_image, final Context ctx){
productImage = (ImageView) itemView.findViewById(R.id.ProImage);
Picasso.with(ctx).setIndicatorsEnabled(false);
Picasso.with(ctx)
.load(thumb_image)
.networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.basket_b).into(productImage, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(ctx).load(thumb_image).placeholder(R.drawable.basket).into(productImage);
}
});
}
public void setComname(String name){
comname = (TextView)itemView.findViewById(R.id.proComName);
comname.setText(name);
}
}
}
This jumps out at me:
listItems1.remove(position);
notifyItemChanged(position);
The notifyItemChanged() method exists to tell the adapter that the data at the given position has changed, and that the ViewHolder should be re-bound. This is not what you're doing; you're removing an item.
Probably your app is crashing because you're removing the last item in your data set (e.g. position 10) and then telling the adapter that the item at position 10 has changed... but now the maximum position in your data set is 9.
Instead, you should use the notifyItemRemoved() method.
listItems1.remove(position);
notifyItemRemoved(position);

Compare Old Data with New Data in Recyclerview

I am new in Android Development and working on a project where I need to call an API after every one second, in that API there is field "Amount"(dBID) which keeps on changing, so I need to update the latest Amount (dBID) in recyclerview.
In order to do so, I have called this API in a service after every interval of one second.
The data is Showing Properly no Issue.
But for Now I need to perform some action on the Old Amount and New Amount.
Action Required : I need to compare the old value (dBID) with the New Value (dBID).
If the New Value is greater then I need to change the Text Color of Amount (dBID) to BLUE.
If the New Value is smaller then I need to change the Text Color of Amount (dBID) to RED.
Tried to achieve this by storing the old data in a Variable and then Comparing it to the new Value.
Issue : This logic is working fine until there are 5 or less Items in recyclerview as soon as the sixth item is added the same logic does not work.
Help me if anyone knows how I can achieve this.
For Example you can refer an App Vertexfx : Quotes Tab.
Below is the Code which I Tried.
Adapter class of the RecyclerView:
public class QuoteAdapter extends RecyclerView.Adapter <QuoteAdapter.MyViewHolder>{
Context context;
List<QuoteData> data;
public QuoteAdapter(Context context,List<QuoteData> data)
{
this.data = data;
this.context = context;
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView time,symbol,sellmax,selllow,buymax,buylow,buy,sell,spread,lowtext,hightext;
LinearLayout layout,layoutbid,layoutask;
float currentbid,lastbid,currentask,lastask;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
time = itemView.findViewById(R.id.TVTime);
symbol = itemView.findViewById(R.id.TVSymbol);
sellmax = itemView.findViewById(R.id.TVSELLMAX);
selllow = itemView.findViewById(R.id.TVSELLLOW);
buymax = itemView.findViewById(R.id.TVBUYMAX);
buylow = itemView.findViewById(R.id.TVBUYHIGH);
buy = itemView.findViewById(R.id.TVBUY);
sell = itemView.findViewById(R.id.TVSELL);
spread = itemView.findViewById(R.id.TVSpread1);
lowtext = itemView.findViewById(R.id.low);
hightext = itemView.findViewById(R.id.high);
layout = itemView.findViewById(R.id.layout);
layoutbid = itemView.findViewById(R.id.LLBid);
layoutask = itemView.findViewById(R.id.LLAsk);
currentbid = 0;
lastbid = 0;
currentask = 0;
lastask = 0;
}
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.quotelist,viewGroup,false);
return new MyViewHolder(view);
}
#SuppressLint("ResourceAsColor")
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, final int i) {
final QuoteData data1 = data.get(i);
myViewHolder.time.setText(data1.dLut);
myViewHolder.symbol.setText(data1.dSymbol);
myViewHolder.sellmax.setText(data1.dBid); //Bid
myViewHolder.selllow.setText(data1.dLow);
myViewHolder.buymax.setText(data1.dAsk); //ask
myViewHolder.buylow.setText(data1.dHigh);
myViewHolder.currentbid = Float.parseFloat((data1.dBid));
myViewHolder.currentask = Float.parseFloat((data1.dAsk));
if (myViewHolder.currentbid > myViewHolder.lastbid)
{
myViewHolder.sellmax.setTextColor(Color.BLUE);
}
if (myViewHolder.currentbid < myViewHolder.lastbid)
{
myViewHolder.sellmax.setTextColor(Color.RED);
}
myViewHolder.lastbid = myViewHolder.currentbid;
myViewHolder.lastask = myViewHolder.currentask;
}
});
}
I suggest you take a look at those classes from the Android SDK:
DiffUtil
AsyncListDiffer
ItemAnimator
DiffUtil
DiffUtil is designed to compare existing and new recycler view items and fires appropriate events. You need to pass a callback that can tell if two items are the same and if their content has changed.
AsyncListDiffer
It wraps the DiffUtil and executes it's logic asynchronously, giving better performance.
ItemAnimator
The ItemAnimator for a given RecyclerView is called by default when change events are fired on it's items. You can provide an implementation of the animateChange method to change your color accordingly.
For Future reference I have resolved the above mentioned issue using the below code.
Defined two ArrayList of String in Adapter
public class QuoteAdapter extends RecyclerView.Adapter <QuoteAdapter.MyViewHolder>{
Context context;
List<QuoteData> data;
List<String> olddatabid = new ArrayList<String>();
List<String> newdatabid = new ArrayList<String>();
List<String> olddataask = new ArrayList<String>();
List<String> newdataask = new ArrayList<String>();
class MyViewHolder extends RecyclerView.ViewHolder{
TextView time,symbol,sellmax,selllow,buymax,buylow,buy,sell,spread,lowtext,hightext;
LinearLayout layout,layoutbid,layoutask;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
time = itemView.findViewById(R.id.TVTime);
symbol = itemView.findViewById(R.id.TVSymbol);
sellmax = itemView.findViewById(R.id.TVSELLMAX);
selllow = itemView.findViewById(R.id.TVSELLLOW);
buymax = itemView.findViewById(R.id.TVBUYMAX);
buylow = itemView.findViewById(R.id.TVBUYHIGH);
buy = itemView.findViewById(R.id.TVBUY);
sell = itemView.findViewById(R.id.TVSELL);
spread = itemView.findViewById(R.id.TVSpread1);
lowtext = itemView.findViewById(R.id.low);
hightext = itemView.findViewById(R.id.high);
layout = itemView.findViewById(R.id.layout);
layoutbid = itemView.findViewById(R.id.LLBid);
layoutask = itemView.findViewById(R.id.LLAsk);
}
}
public QuoteAdapter(Context context,List<QuoteData> data)
{
this.data = data;
this.context = context;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.quotelist,viewGroup,false);
return new MyViewHolder(view);
}
#SuppressLint("ResourceAsColor")
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, final int i) {
final QuoteData data1 = data.get(i);
myViewHolder.time.setText(data1.dLut);
myViewHolder.symbol.setText(data1.dSymbol);
myViewHolder.sellmax.setText(data1.dBid); //Bid
myViewHolder.selllow.setText(data1.dLow);
myViewHolder.buymax.setText(data1.dAsk); //ask
myViewHolder.buylow.setText(data1.dHigh);
if (newdatabid.size()< data.size())
{
newdatabid.add(data1.dBid); //Insert Value in array for the first time
}
if (olddatabid.size()< data.size())
{
olddatabid.add(data1.dBid); //Insert Value in array for the first time
}
if (newdataask.size()< data.size())
{
newdataask.add(data1.dAsk); //Insert Value in array for the first time
}
if (olddataask.size()< data.size()) //Insert Value in array for the first time
{
olddataask.add(data1.dAsk);
}
newdatabid.set(i,data1.dBid); //Store Value in array
newdataask.set(i,data1.dAsk); //Store Value in array
//Compare and perform Logic
if (Float.valueOf(newdatabid.get(i)) > Float.valueOf(olddatabid.get(i)))
{
myViewHolder.sellmax.setTextColor(Color.BLUE);
}
if (Float.valueOf(newdatabid.get(i)) < Float.valueOf(olddatabid.get(i)))
{
myViewHolder.sellmax.setTextColor(Color.RED);
}
if (Float.valueOf(newdataask.get(i)) > Float.valueOf(olddataask.get(i)))
{
myViewHolder.buymax.setTextColor(Color.BLUE);
}
if (Float.valueOf(newdataask.get(i)) < Float.valueOf(olddataask.get(i)))
{
myViewHolder.buymax.setTextColor(Color.RED);
}
olddatabid.set(i,newdatabid.get(i));
olddataask.set(i,newdataask.get(i));
}
});
}
}
#Override
public int getItemCount() {
return data.size();
}
}

Recyclervew clear viewholder when deleting item

file with working code to test my issue, you have to add 2 items, then delete any of those and then add a new one to see how the deleted gets on top of the newly addded
https://www.dropbox.com/s/ojuyz5g5f3kaz0h/Test.zip?dl=0
I have a problem when deleting an item from the recyclerview, when ever I delete an item, IF I add a new item, the deleted item will appear in top of the newly added item, how could I get a fresh view or avod this from happening as is a big issue.
this is how i add items from my main activity
if (!resta || (diff > (3*60*1000)))
{
Ri.add(dataroot);
Integer position = adapter.getItemCount() + 1;
adapter.notifyItemInserted(position);
}
here my Adapter
public class ComandaAdapter extends RecyclerView.Adapter<ComandaAdapter.ComandaAdapterViewHolder>{
private Context mContext;
private ArrayList<Integer> lista_entradas = new ArrayList<>();
private ArrayList<Integer> lista_fondos = new ArrayList<>();
private ArrayList<Integer> lista_postres= new ArrayList<>();
private Boolean primeritem;
private ArrayList<DataRoot> Rir;
private TextView txt_comandas;
private TextView txt_entracola;
private TextView txt_fondocola;
private TextView txt_postrecola;
public ComandaAdapter(Context context, TextView tx_entracola, TextView tx_fondocola, TextView tx_postrecola, TextView tx_comandas, ArrayList<DataRoot> Rir)
{
this.mContext = context;
this.txt_comandas = tx_comandas;
this.txt_entracola = tx_entracola;
this.txt_fondocola = tx_fondocola;
this.txt_postrecola = tx_postrecola;
this.Rir= Rir;
}
#Override
public ComandaAdapter.ComandaAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
return new ComandaAdapter.ComandaAdapterViewHolder(LayoutInflater.from(mContext).inflate(R.layout.row,parent,false));
}
#Override
public void onBindViewHolder(final ComandaAdapter.ComandaAdapterViewHolder holder, final int position)
{
DataRoot Rdata = Rir.get(position);
holder.setdata(Rdata);
}
public void delete(int position)
{
Rir.remove(position);
notifyItemRemoved(position);
}
public class ComandaAdapterViewHolder extends RecyclerView.ViewHolder
{
Button btn_cerrar;
public ComandaAdapterViewHolder(View itemView)
{
super(itemView);
btn_cerrar = (Button) itemView.findViewById(R.id.btn_cerrar);
void setData(final DataRoot Rdata)
{
btn_cerrar.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
btn_cerrar.setEnabled(false);
btn_cerrar.setBackgroundTintList(mContext.getColorStateList(R.color.cboff));
updateRetrofitEstadoorden(Rdata.get_id());
updateRetrofitNrocomanda(Rdata.get_id(), txt_comanda.getText().toString());
delete(getAdapterPosition());
}
});
Rdata.gerOrder();
creaboton():
and here my recyler
private void setAdapter()
{
adapter = new ComandaAdapter(this, txt_entracola, txt_fondocola, txt_postrecola, txt_comandas, Ri);
recyclerView.getRecycledViewPool().setMaxRecycledViews(-1, Ri.size());//va en 0 supuestamente -1 es default
recyclerView.setItemViewCacheSize(Ri.size()); //ver si hay que cambiar con cada item
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
}
Thanks in advance for any help.
Images to show the problem
You are using the Recyclerview in a very non standard way. The issue you are seeing is because the views are being recycled (as they should be in a Recyclerview) but you are not clearing out the items from the previous view.
The problem in in this method:
public void setData(String value) {
container.removeAllViews(); // Remove all previously added views
textview.setText(value);
Random r = new Random();
int i1 = r.nextInt(5 - 1) + 1;
for (int i = 0; i < i1; i++) {
be = new Button(mContext);
be.setText("Boton " + i);
be.setLayoutParams(new LinearLayout.LayoutParams(240, LinearLayout.LayoutParams.WRAP_CONTENT));
container.addView(be);
}
}
By calling container.addView(be), you are manually adding extra views to the views that the Recyclerview creates. When you remove these views, they are cached and reused the next time you press "Add". The problem is that the cached view still contains all of the manually added views so you are then adding more views under the existing ones.
As you can see in the code above, i added container.removeAllViews(); which removes the views that were added previously ensuring that "Container" is empty before you start adding your extra views to it.
Also, unless you have a very specific reason for doing so, I would removes these lines as I believe you are hurting performance by having them:
list.getRecycledViewPool().setMaxRecycledViews(-1, index);
list.setItemViewCacheSize(index);

Change the visibility of a View while repeating data

I am populating OrderHistory by retrieving data from Server in my app. Here I need to populate listitem depends on OrderId. If OrderId repeats I need to hide the LinearLayout which is marked in green in screenshot. Otherwise the Layout has to be usual view.Please help me.
MyAdapter Class:
public class MyOrderAdapter extends RecyclerView.Adapter<MyOrderAdapter.ViewHolder> {
Context mContext;
List<CartRes> mOrderList = new ArrayList<>();
private ImageLoader imageLoader;
public MyOrderAdapter(Context context, List<CartRes> orderList) {
mContext = context;
mOrderList = orderList;
Log.e("Json Adapter", "" + mOrderList);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_order_history, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.cartResOrder = mOrderList.get(position);
imageLoader = CustomVolleyRequest.getInstance(mContext).getImageLoader();
String IMAGE_URL = "http://" + Config.IMAGE_URL + holder.cartResOrder.ORDER_IMAGE;
Log.e("Image URL", IMAGE_URL + " " + holder.cartResOrder.ORDER_IMAGE);
imageLoader.get(IMAGE_URL, ImageLoader.getImageListener(holder.orderImage, 0, 0));
holder.orderImage.setImageUrl(IMAGE_URL, imageLoader);
holder.txtOrderId.setText(holder.cartResOrder.ORDER_ID);
holder.txtOrderProduct.setText(holder.cartResOrder.ORDER_PRODUCT);
holder.txtorderedDate.setText(holder.cartResOrder.ORDER_DATE);
holder.txtDeliveredDate.setText(holder.cartResOrder.ORDER_DELIVERY_DATE);
}
#Override
public int getItemCount() {
return mOrderList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtOrderId, txtOrderProduct, txtorderedDate, txtDeliveredDate;
Button butDetail, butRemove;
NetworkImageView orderImage;
CartRes cartResOrder;
public ViewHolder(View itemView) {
super(itemView);
txtOrderId = (TextView) itemView.findViewById(R.id.orderId);
txtOrderProduct = (TextView) itemView.findViewById(R.id.orderProduct);
txtorderedDate = (TextView) itemView.findViewById(R.id.orderedDate);
txtDeliveredDate = (TextView) itemView.findViewById(R.id.orderDeliveredDate);
butDetail = (Button) itemView.findViewById(R.id.orderViewDetail);
butRemove = (Button) itemView.findViewById(R.id.orderRemove);
orderImage = (NetworkImageView) itemView.findViewById(R.id.OrderproductImage);
}
}
}
UPDATE:
public void onBindViewHolder(ViewHolder holder, int position) {
holder.cartResOrder = mOrderList.get(position);
imageLoader = CustomVolleyRequest.getInstance(mContext).getImageLoader();
String IMAGE_URL = "http://" + Config.IMAGE_URL + holder.cartResOrder.ORDER_IMAGE;
Log.e("Image URL", IMAGE_URL + " " + holder.cartResOrder.ORDER_IMAGE);
imageLoader.get(IMAGE_URL, ImageLoader.getImageListener(holder.orderImage, 0, 0));
holder.orderImage.setImageUrl(IMAGE_URL, imageLoader);
holder.txtOrderId.setText(holder.cartResOrder.ORDER_ID);
holder.txtOrderProduct.setText(holder.cartResOrder.ORDER_PRODUCT);
holder.txtorderedDate.setText(holder.cartResOrder.ORDER_DATE);
holder.txtDeliveredDate.setText(holder.cartResOrder.ORDER_DELIVERY_DATE);
if (position > 0 && mOrderList.get(position).ORDER_ID == mOrderList.get(position - 1).ORDER_ID) {
//make sure it is not the first one, and make sure it has the same ID as previous.
holder.OrderLinear.setVisibility(View.GONE); //hide it, you need to set the reference first.
holder.txtOrderId.setVisibility(View.GONE);
}
}
One way you could do it:
Have a new holder variable that refers to your LinearLayout you want to hide.
In your onBindViewHolder()
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
//setup everything else above...
if (position > 0 && mOrderList.get(position).ORDER_ID == mOrderList.get(position - 1).ORDER_ID){
//make sure it is not the first one, and make sure it has the same ID as previous.
holder.thelinearlayout.setVisibility(View.GONE); //hide it, you need to set the reference first.
}else holder.thelinearlayout.setVisibility(View.VISIBLE);
//if somehow order gets changed.(e.g. previous row is deleted).
}
EDIT:
I'm assuming that the data inside is sorted by ORDER_ID, so there won't be a case where there are two elements with the same ORDER_ID that is not next to each other.
You might want to sort them based on ORDER_ID before passing the list into adapter.
EDIT2:
Added else condition as suggested in the comment.
The screenshot does not tell that but if your view is RecyclerView or ListView then I'd preprocess the data prior feeding it to the adapter (i.e. by wrapping your model into another class with additional attributes).
Alternatively you can try checking previous row (by fetching it from your data source or adapter) while populating current one and adjust the view
maybe just add field boolean repeatOrderId to your CartRes class and in constructor do some for loop and flag all items? you may check also in runtime, but you have pretty fixed list, preparing in construtor this flag is better for performance
for(int i=0; i<mOrderList.getCount(); i++){
CartRes cr = mOrderList.get(i);
cr.repeatOrderId=true;
for(int j=0; j<i; j++){
if(cr.ORDER_ID==mOrderList.get(j).ORDER_ID){
cr.repeatOrderId=false; //default true
break;
}
}
}
then inside onBindViewHolder check this flag and setVisibility(cr.repeatOrderId); for desired layout

How should I initialize an array inside RecyclerView Adapter which has the size of a list while the list will not available on Adapter construction?

I have a RecyclerView that will contain list of item retrieved from the internet. So at first, the list will be empty. After the data retrieved from the internet, it will update the list and call notifyDataSetChanged().
I can adapt the data into the RecyclerView just fine. But, I have an ImageButton for each of item which has different Image if it's clicked. If I initialize the flags array inside onBindViewHolder, each time I scrolled the RecyclerView, the flag array will be reinitialize to false. If I initialize it in the Adapter constructor, it will be 0 index since the list will be empty at first. Where should I put array initializing in adapter if the data will come at some amount of time later?
Below is my code, but the flag array (isTrue) is always reinitialize each time I scrolled my RecyclerView.
public class SomethingAdapter extends RecyclerView.Adapter<SomethingAdapter.ViewHolder> {
private ArrayList<String> someList;
private boolean[] isTrue;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView someText;
public ImageButton someButton;
public ViewHolder(View v) {
super(v);
someText = (TextView) v.findViewById(R.id.text);
someButton = (ImageButton) v.findViewById(R.id.button);
}
}
public SomethingAdapter(ArrayList<String> someList) {
this.someList = someList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.some_layout, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
//TODO: This thing will make isTrue always reinitialize if scrolled
this.isTrue = new boolean[someList.getResults().size()];
viewHolder.someText.setText(someList.get(position));
if (isTrue[position]) {
viewHolder.someButton.setImageResource(R.drawable.button_true);
} else {
viewHolder.someButton.setImageResource(R.drawable.button_false);
}
viewHolder.someButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isTrue[position]) {
//Connect to the internet and if response is positive {
//isTrue[position] = false;
//viewHolder.someButton.setImageResource(R.drawable.button_false);
//}
} else {
//Connect to the internet and if response is positive {
//isTrue[position] = true;
//viewHolder.someButton.setImageResource(R.drawable.button_true);
//}
}
}
});
}
#Override
public int getItemCount() {
return someList.size();
}
Initialize it when you add items to someList.
Also, don't add click listener in your onBind, create it in onCreateViewHolder. You cannot use position in the click callback, instead you should be using ViewHolder#getAdapterPosition.
See docs for details:
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onBindViewHolder(VH, int)

Categories

Resources