Android - Recycler View item get swapped when scrolled - android

Can somebody explain what is the problem.
I have a recycler grid view with each item consisting countdown timer and view which changes after a countdown time is completed.
But the problem arises when I do scroll to down and back to top, my items were change for other items in the list, and if I do scroll again, the items again are changed.
This is my adapter.
public class TableTransactionRecyclerView extends RecyclerView.Adapter<TableTransactionRecyclerView.ViewHolder> {
private ArrayList<TableInfo> tableList;
private OnItemClickListener listener;
private static Context context;
private static SharedPreferences preferences;
private static List<ViewHolder> lstHolders;
public Runnable updateRemainingTimeRunnable = new Runnable() {
#Override
public void run() {
synchronized (lstHolders) {
for (ViewHolder holder : lstHolders) {
holder.updateTimeRemaining();
}
}
}
};
public TableTransactionRecyclerView(Context context, ArrayList<TableInfo> tableList, OnItemClickListener listener) {
this.tableList = tableList;
this.listener = listener;
this.context = context;
preferences = context.getSharedPreferences(CommonConsts.MY_PREFERENCES, Context.MODE_PRIVATE);
lstHolders = new ArrayList<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewHolder vh;
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.table_transaction_row_layout, parent, false);
vh = new ViewHolder(itemView);
synchronized (lstHolders) {
lstHolders.add(vh);
}
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(tableList, position, listener);
}
#Override
public int getItemCount() {
return tableList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
public ImageButton popupMenuBtn;
private ProgressBar showLoadingImage;
private ImageView successTick;
private ImageView tableIcon;
private LinearLayout processingLayout;
private View lineView;
private LatoTextView transactionAmountTextView;
private LatoTextView timerCountTextView;
private ArrayList<TableInfo> tableList;
private int position;
public ViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.table_id_text_view);
popupMenuBtn = (ImageButton) itemView.findViewById(R.id.pop_menu_btn);
showLoadingImage = (ProgressBar) itemView.findViewById(R.id.show_loading_image);
successTick = (ImageView) itemView.findViewById(R.id.success_image_view);
lineView = itemView.findViewById(R.id.view_id);
tableIcon = (ImageView) itemView.findViewById(R.id.table_icon);
processingLayout = (LinearLayout) itemView.findViewById(R.id.processing_layout);
transactionAmountTextView = (LatoTextView) itemView.findViewById(R.id.transaction_amount_text_view);
timerCountTextView = (LatoTextView) itemView.findViewById(R.id.timer_count_down_id);
}
public void bind(final ArrayList<TableInfo> tableList, final int position, final OnItemClickListener listener) {
TableInfo item = tableList.get(position);
this.tableList = tableList;
this.position = position;
textView.setText(item.getTableNumber());
if (item.getIsProcessing()) {
showLoadingImage.setVisibility(View.VISIBLE);
successTick.setVisibility(View.GONE);
tableIcon.setVisibility(View.GONE);
processingLayout.setVisibility(View.VISIBLE);
transactionAmountTextView.setText(Utils.setFormattedText(String.valueOf(item.getTransactionAmt())));
synchronized (lstHolders) {
updateTimeRemaining();
}
} else {
showLoadingImage.setVisibility(View.GONE);
tableIcon.setVisibility(View.VISIBLE);
processingLayout.setVisibility(View.GONE);
}
setLayout(tableList, position, item.getIsProcessing(), item.isLastTransactionSuccess());
}
public void setLayout(final ArrayList<TableInfo> tableList, final int position, boolean isTransaction, boolean isSuccess) {
final TableInfo item = tableList.get(position);
if(isTransaction){
item.setHandler(null);
item.setUIChangeCompletedSuccess(true);
showLoadingImage.setVisibility(View.VISIBLE);
tableIcon.setVisibility(View.GONE);
processingLayout.setVisibility(View.VISIBLE);
transactionAmountTextView.setText(Utils.setFormattedText(String.valueOf(item.getTransactionAmt())));
lineView.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.txn_view_drawable));
}else{
showLoadingImage.setVisibility(View.GONE);
tableIcon.setVisibility(View.VISIBLE);
processingLayout.setVisibility(View.GONE);
if(item.isUIChangeCompletedSuccess()) {
item.setUIChangeCompletedSuccess(false);
if (isSuccess) {
successTick.setVisibility(View.VISIBLE);
lstHolders.get(position).lineView.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.txn_success_view_drawable));
Handler handler;
if (item.getHandler() == null) {
handler = new Handler();
item.setHandler(handler);
handler.postDelayed(new Runnable() {
#Override
public void run() {
lstHolders.get(position).lineView.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.txn_view_drawable));
successTick.setVisibility(View.GONE);
item.setHandler(null);
}
}, 25000);
}
} else {
successTick.setVisibility(View.GONE);
lstHolders.get(0).lineView.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.txn_unsuccess_view_drawable));
Handler handler;
if (item.getHandler() == null) {
handler = new Handler();
item.setHandler(handler);
handler.postDelayed(new Runnable() {
#Override
public void run() {
lstHolders.get(position).lineView.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.txn_view_drawable));
successTick.setVisibility(View.GONE);
item.setHandler(null);
}
}, 25000);
}
}
}
}
}
public void updateTimeRemaining() {
timerCountTextView.setText(preferences.getString(tableList.get(position).getTableId(), ""));
}
}
}
and i have set adapter like this:
mAdapter = new TableTransactionRecyclerView(this, tableList, this);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(), 4, GridLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(mAdapter);
I have also looked at the problem in following links which didnot solved my problem.
Recyclerview changing items when is scrolled
Recyclerview Changing Items During Scroll

Try overriding the following:
#Override
public int getItemViewType(int position) {
return position;
}

Related

Grouping of RecyclerView elements by several properties

I have a RecyclerView filled with elements of the "Event" class. The class has parameters such as Date and Importance.
Now all Events in RecyclerView are displayed just like that.
I want to show Events by Date separately and also want to show Events by importance separately. I'll attach a picture to show what I mean.
I read that to do separation, for example, by dates, you need to make a separate adapter and viewholder. Question - if I want to split the same data array by importance, do I need to create another adapter?
And let's say I want to choose a grouping method. How can I do this and where?
My First RecyclerViewAdapter of Event
public class EventAdapter extends RecyclerView.Adapter<EventAdapter.EventViewHolder> {
private static final String TAG = "myLogs";
private List<Event> mEventList;
final SparseBooleanArray selectedItems = new SparseBooleanArray();
private int currentSelectedPos;
public List<Event> getEvents(){
return mEventList;
}
private EventAdapterListener itemClickListener;
public interface EventAdapterListener {
void onItemClick(int position);
void onItemLongClick(int position);
}
public void setListener(EventAdapterListener listener){
itemClickListener = listener;
}
private OnItemCheckedListener OnItemChecked;
public interface OnItemCheckedListener {
void onItemChecked(int position, boolean isImportant);
}
public void setOnItemCheckedListener (OnItemCheckedListener listener){
OnItemChecked = listener;
}
public static class EventViewHolder extends RecyclerView.ViewHolder{
public TextView TVtitle;
public TextView TVcomment;
public CheckBox CBimportance;
public TextView TVdate;
//public EventViewHolder(#NonNull View itemView, final EventAdapterListener listener) {
public EventViewHolder(#NonNull View itemView) {
super(itemView);
TVtitle = itemView.findViewById(R.id.tvTitle);
TVcomment = itemView.findViewById(R.id.tvComment);
CBimportance = itemView.findViewById(R.id.cbIconImportant);
TVdate = itemView.findViewById(R.id.tvDate);
}
}
public void removeItem(int position) {
mEventList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mEventList.size());
}
private static DateFormatSymbols myDateFormatSymbols = new DateFormatSymbols(){
#Override
public String[] getMonths() {
return new String[]{"января", "февраля", "марта", "апреля", "мая", "июня",
"июля", "августа", "сентября", "октября", "ноября", "декабря"};
}
};
public EventAdapter(ArrayList<Event> listEvent){
mEventList = listEvent;
}
#NonNull
#Override
public EventViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_cardview, parent, false);
//LayoutInflater inflater = LayoutInflater.from(parent.getContext());
//if (viewType == Constants.VIEWTYPE_GROUP){
//ViewGroup group = (ViewGroup) inflater.inflate(R.layout.group_layout, parent, false);
//GroupViewHolder
//}
return new EventViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull EventViewHolder holder, final int position) {
final Event item = mEventList.get(position);
holder.TVtitle.setText(item.getName());
holder.TVcomment.setText(item.getComment());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM", myDateFormatSymbols);
holder.TVdate.setText(simpleDateFormat.format(item.getDate()));
holder.CBimportance.setOnCheckedChangeListener(null);
holder.CBimportance.setChecked(item.getImportant());
holder.CBimportance.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
item.IsImportant = b;
OnItemChecked.onItemChecked(position, b);
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (selectedItems.size() > 0 && itemClickListener != null){
itemClickListener.onItemClick(position);
}
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if (itemClickListener != null){
itemClickListener.onItemLongClick(position);
}
return true;
}
});
if (currentSelectedPos == position) currentSelectedPos = -1;
}
#Override
public int getItemCount() {
return mEventList.size();
}
void deleteEvents(){
List<Event> events = new ArrayList<>();
for (Event event : mEventList){
if (event.getSelected())
events.add(event);
}
mEventList.removeAll(events);
notifyDataSetChanged();
currentSelectedPos = -1;
}
void toggleSelection(int position) {
currentSelectedPos = position;
if (selectedItems.get(position)) {
selectedItems.delete(position);
mEventList.get(position).setSelected(false);
} else {
selectedItems.put(position, true);
mEventList.get(position).setSelected(true);
}
notifyItemChanged(position);
}}

ItemView.setOnCLickListiner is Being Ignored and does not get clicked when it is clicked

please can anyone help me fix this my itemview is not being clicked wen i click it in my fragment after implementing my onItemClickListener interface in my adapter, i also called the adapter in my fragment but if i run the app and i click d cardview nothing happens and am using list adapter which extends recyclerView. please if anyone can help me i will b grateful
my adapter
public class Apiary_Adapter extends ListAdapter<RecordModel,Apiary_Adapter.ApiaryHolder> {
Apiaries apiaries;
Context context;
RecordOnClickListener listener;
public RecordViewModel record_View_model = Apiaries.record_View_model;
public Apiary_Adapter(Apiaries apiaries, Context context ) {
super(DIFF_CALLBACK);
this.apiaries = apiaries;
this.context = context;
}
private static final DiffUtil.ItemCallback<RecordModel> DIFF_CALLBACK = new DiffUtil.ItemCallback<RecordModel>() {
#Override
public boolean areItemsTheSame(#NonNull RecordModel oldItem, #NonNull RecordModel newItem) {
return oldItem.getId() == newItem.getId();
}
#Override
public boolean areContentsTheSame(#NonNull RecordModel oldItem, #NonNull RecordModel newItem) {
return oldItem.getAddress().equals(newItem.getAddress())&&oldItem.getApiaryNo().equals(newItem.getApiaryNo())
&&oldItem.getTown().equals(newItem.getTown())&&oldItem.getApiaryLongitude().equals(newItem.getApiaryLongitude())
&&oldItem.getApiaryLatitude().equals(newItem.getApiaryLatitude())&&oldItem.getDateOfHarvest().equals(newItem.getDateOfHarvest())
&&oldItem.getDateOfColonisation().equals(newItem.getDateOfColonisation())&&oldItem.getNoOfWaxHarvested().equals(newItem.getNoOfWaxHarvested())
&&oldItem.getQuantityOfHoneyHarvested().equals(newItem.getQuantityOfHoneyHarvested())&&oldItem.getNoOfPropolis().equals(newItem.getNoOfPropolis())
&&oldItem.getNoOfCombs().equals(newItem.getNoOfCombs())&&oldItem.getHiveNo().equals(newItem.getHiveNo())
&&oldItem.getHiveLongitude().equals(newItem.getHiveLongitude())&&oldItem.getHiveLatitude().equals(newItem.getHiveLatitude())
&&oldItem.getTime().equals(newItem.getTime())&&oldItem.getDate().equals(newItem.getDate());
}
};
public class ApiaryHolder extends RecyclerView.ViewHolder {
private TextView address;
private TextView apiary;
private TextView town;
private TextView LocationLatitude;
private TextView LocationLongitude;
private TextView HiveLatitude;
private TextView HiveLongitude;
private TextView date;
private TextView time;
private TextView hiveNo;
private TextView noOfComb;
private TextView dateOfHarvest;
private TextView dateOfColonisation;
private TextView waxHarvested;
private TextView quantityOfhoney;
private TextView noOfPropolis;
private CheckBox checkBox;
CardView cardView;
Apiaries apiaries;
public ApiaryHolder(#NonNull final View itemView, final Apiaries apiaries) {
super(itemView);
address = itemView.findViewById(R.id.customAddress);
apiary = itemView.findViewById(R.id.customApiaryNo);
town = itemView.findViewById(R.id.customTown);
LocationLongitude = itemView.findViewById(R.id.customLongitude);
LocationLatitude = itemView.findViewById(R.id.customLatitude);
checkBox = itemView.findViewById(R.id.customCheckbox);
hiveNo = itemView.findViewById(R.id.customHiveNo);
noOfComb = itemView.findViewById(R.id.customCombNo);
dateOfHarvest = itemView.findViewById(R.id.customDateOfHarvest);
dateOfColonisation = itemView.findViewById(R.id.customDateOfColonisation);
waxHarvested = itemView.findViewById(R.id.customNoOfWaxHarveted);
quantityOfhoney = itemView.findViewById(R.id.customQuantityOfHoney);
noOfPropolis = itemView.findViewById(R.id.customNoOfPropolis);
HiveLatitude = itemView.findViewById(R.id.customHiveLatitude);
HiveLongitude = itemView.findViewById(R.id.customHiveLongitude);
date = itemView.findViewById(R.id.customDate);
time = itemView.findViewById(R.id.customTime);
cardView = itemView.findViewById(R.id.Cardview);
this.apiaries = apiaries;
mainActivity = new MainActivity();
cardView.setOnLongClickListener(apiaries);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int Position = getAdapterPosition();
if (listener != null && Position != RecyclerView.NO_POSITION){
listener.OnItemClick(getItem(Position));
Toast.makeText(context, "Hello9", Toast.LENGTH_LONG).show();
notifyDataSetChanged();
}
}
});
}
#NonNull
#Override
public ApiaryHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.customlayout, parent, false);
final ApiaryHolder apiaryHolder= new ApiaryHolder(itemView, apiaries);
return apiaryHolder;
}
#Override
public void onBindViewHolder(#NonNull ApiaryHolder holder, final int position) {
RecordModel currentRecord = getItem(position);
holder.address.setText(currentRecord.getAddress());
holder.apiary.setText(currentRecord.getApiaryNo());
holder.town.setText(currentRecord.getTown());
holder.LocationLatitude.setText(currentRecord.getApiaryLatitude());
holder.LocationLongitude.setText(currentRecord.getApiaryLongitude());
holder.hiveNo.setText(currentRecord.getHiveNo());
holder.noOfComb.setText(currentRecord.getNoOfCombs());
holder.dateOfHarvest.setText(currentRecord.getDateOfHarvest());
holder.dateOfColonisation.setText(currentRecord.getDateOfColonisation());
holder.waxHarvested.setText(currentRecord.getNoOfWaxHarvested());
holder.quantityOfhoney.setText(currentRecord.getQuantityOfHoneyHarvested());
holder.noOfPropolis.setText(currentRecord.getNoOfPropolis());
holder.HiveLatitude.setText(currentRecord.getHiveLatitude());
holder.HiveLongitude.setText(currentRecord.getHiveLongitude());
holder.date.setText(currentRecord.getDate());
holder.time.setText(currentRecord.getTime());
}
public interface RecordOnClickListener{
void OnItemClick(RecordModel recordModel);
}
public void setOnItemClickListener(RecordOnClickListener listener){
this.listener = listener;
}
my fragment
public class Apiaries extends Fragment implements View.OnLongClickListener {
public static boolean is_in_contextualMode = false;
public static RecordViewModel record_View_model;
Apiary_Adapter apiary_adapter;
public static int counter = 0;
public static ArrayList<RecordModel> selectionList =new ArrayList<>();
private RecyclerView recyclerView;
public static SearchView searchView;
public static final int ADD_RECORD_REQUEST = 1;
public static final int EDIT_RECORD_REQUEST = 2;
com.github.clans.fab.FloatingActionButton floatingActionButton;
FirebaseAuth firebaseAuth;
DatabaseReference reference;
public static MainActivity mainActivity;
private Menu menu;
ArrayList<RecordModel> list = new ArrayList<>();
public Apiaries() {
// Required empty public constructor
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_apiaries, container, false);
floatingActionButton = (FloatingActionButton) view.findViewById(R.id.fab2);
Apiaries apiaries = new Apiaries();
apiary_adapter = new Apiary_Adapter(apiaries, getActivity());
firebaseAuth = FirebaseAuth.getInstance();
String currentUserId = firebaseAuth.getCurrentUser().getUid();
reference = FirebaseDatabase.getInstance().getReference().child("users").child(currentUserId);
recyclerView=(RecyclerView)view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(apiary_adapter);
recyclerView.setHasFixedSize(true);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mainActivity = new MainActivity();
record_View_model = new ViewModelProvider(getActivity()).get(RecordViewModel.class);
record_View_model.getAllRecord().observe(getActivity(), new Observer<List<RecordModel>>() {
#Override
public void onChanged(#Nullable List<RecordModel> recordModels) {
apiary_adapter.submitList(recordModels);
}
});
apiary_adapter.setOnItemClickListener(new Apiary_Adapter.RecordOnClickListener() {
#Override
public void OnItemClick(RecordModel recordModel) {
Intent intent = new Intent(getContext(), EditApiaryAddActivity.class);
intent .putExtra(EditApiaryAddActivity.EXTRA_ID, recordModel.getId());
intent .putExtra(EditApiaryAddActivity.EXTRA_ADDRESS, recordModel.getAddress());
intent .putExtra(EditApiaryAddActivity.EXTRA_APIARYNAME, recordModel.getApiaryNo());
intent .putExtra(EditApiaryAddActivity.EXTRA_TOWN, recordModel.getTown());
intent .putExtra(EditApiaryAddActivity.EXTRA_LOCATION_LATITUDE, recordModel.getApiaryLatitude());
intent .putExtra(EditApiaryAddActivity.EXTRA_LOCATION_LONGITUDE, recordModel.getApiaryLongitude());
intent .putExtra(EditApiaryAddActivity.EXTRA_HIVE_LATITUDE, recordModel.getHiveLatitude());
intent .putExtra(EditApiaryAddActivity.EXTRA_HIVE_LONGITUDE, recordModel.getHiveLongitude());
intent.putExtra(EditApiaryAddActivity.EXTRA_HIVENO, recordModel.getHiveNo());
intent.putExtra(EditApiaryAddActivity.EXTRA_NOOFCOMBS, recordModel.getNoOfCombs());
intent.putExtra(EditApiaryAddActivity.EXTRA_DATEOFHARVEST, recordModel.getNoOfWaxHarvested());
intent.putExtra(EditApiaryAddActivity.EXTRA_DATEOFCOLONISATION, recordModel.getDateOfColonisation());
intent.putExtra(EditApiaryAddActivity.EXTRA_WAXHARVESTED, recordModel.getNoOfWaxHarvested());
intent.putExtra(EditApiaryAddActivity.EXTRA_QUANTITYOFHONEY, recordModel.getQuantityOfHoneyHarvested());
intent.putExtra(EditApiaryAddActivity.EXTRA_NOOFPROPOLIS, recordModel.getNoOfPropolis());
startActivityForResult(intent,EDIT_RECORD_REQUEST);
Apiaries.is_in_contextualMode = false;
mainActivity.clearActionMode();
}
});
}
#Override
public boolean onLongClick(View v) {
MainActivity.toolbar.getMenu().clear();
MainActivity.toolbar.inflateMenu(R.menu.menu_record);
MainActivity.textView1.setVisibility(View.GONE);
MainActivity.itemCountTextView.setVisibility(View.VISIBLE);
MainActivity.edit.setVisibility(View.VISIBLE);
is_in_contextualMode = true;
return true;
}
You should handle Clicks in the onCreateViewHolder method
public ApiaryHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.customlayout, parent, false);
final ApiaryHolder apiaryHolder= new ApiaryHolder(itemView, apiaries);
ApiaryHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//handle the clicks here
}
}
});
return apiaryHolder;
}
You have implemented onLongClickListener Instead of onClickListener
Add the onClickListener Inside on bindviewholder Like holder.itemView.setOnClickLstener

Removing recyclerview items from the Adapter

I have two tabs (fragments), NewOrders and FinishedOrders, I'm populating the orders via Volley requests, now each item inside the New Orders tab has a SwipeLayout which show a clickable textview that makes the order finished, and move it to the other tab (backend stuff..), and I got this working perfectly,
The problem is when I click to finish, the recyclerview isn't updated once the request sent successfully, I have to do pull-to-refresh so it would update..! it seems easy to solve, but the issue is handling the swipelayout listener done inside onBindView method inside the adapter..!! that's only place to access it according to the library I'm using (I guess)..! on the other hand refreshing and populating the list happens in the NewOrder tab fragment..!
So how can I make the item to be removed from the list after the click and becomes updated..?!
Any thoughts..!?
My Adapter Class + ViewHolder
Note: the implemented methods in the adapter are required because of the interface of SwipeLayout library
public class OrdersDataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements SwipeAdapterInterface, SwipeItemMangerInterface {
protected SwipeItemRecyclerMangerImpl mItemManger = new SwipeItemRecyclerMangerImpl(this);
public Context context;
ArrayList<OrderPresenter> orders;
public OrdersDataAdapter(ArrayList<OrderPresenter> orders, Context context) {
this.orders = orders;
this.context = context;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.order_card, parent, false);
return new NewOrderVH(v);
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
final OrderPresenter order = this.orders.get(position);
final NewOrderVH vh1 = (NewOrderVH) holder;
vh1.setData(orders.get(position));
mItemManger.bindView(vh1.itemView, position);
vh1.swipeLayout.setShowMode(SwipeLayout.ShowMode.PullOut);
vh1.swipeLayout.addDrag(SwipeLayout.DragEdge.Left,
vh1.swipeLayout.findViewById(R.id.bottom_wrapper));
if (order.isFinished()) {
vh1.swipeLayout.setSwipeEnabled(false);
vh1.setBadge("DONE");
vh1.setBadgeColor(order.getBadgeColor());
} else {
vh1.finish.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// get the clicked item position?
final int position = vh1.getAdapterPosition();
// these responsible for the request which make the order finished
OrderPresenter order = orders.get(position);
OrderRepository.setOrderFinURL(order.getID());
OrderRepository.FinishOrder(order.getID(), context);
/*the commented three lines below didn't help with the problem*/
// notifyItemChanged(position);
// notifyItemRemoved(position);
// notifyDataSetChanged();*/
order.setStatus(order.getStatusText(Order.FINISHED));
}
});
}
}
#Override
public int getItemCount() {
return orders.size();
}
public class NewOrderVH extends RecyclerView.ViewHolder {
SwipeLayout swipeLayout;
private TextView finish;
private CardView orderCard;
TextView Badge;
private ImageView cusPic;
private TextView cusName;
private TextView CusAdress;
private TextView vendorsNum;
private TextView itemsNum;
private TextView time;
private TextView emptyView;
public NewOrderVH(View itemView) {
super(itemView);
Badge = (TextView) itemView.findViewById(R.id.badge);
swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
finish = (TextView) itemView.findViewById(R.id.finish);
orderCard = (CardView) itemView.findViewById(R.id.OrderCard);
cusPic = (ImageView) itemView.findViewById(R.id.cusPic);
cusName = (TextView) itemView.findViewById(R.id.cusName);
CusAdress = (TextView) itemView.findViewById(R.id.CusAdress);
vendorsNum = (TextView) itemView.findViewById(R.id.vendorsNum);
itemsNum = (TextView) itemView.findViewById(R.id.itemsNum);
time = (TextView) itemView.findViewById(R.id.time);
emptyView = (TextView) itemView.findViewById(R.id.empty_view);
orderCard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), OrderDetails.class);
v.getContext().startActivity(intent);
}
});
}
public void setData(final OrderPresenter data) {
time.setText(data.getOrderTime());
cusName.setText(data.getFullName());
vendorsNum.setText(data.getVendorsCount());
itemsNum.setText(data.getItemsCount());
CusAdress.setText(data.getFullAddress());
Picasso.with(context).load(data.getCustomerPicture()).into(cusPic);
}
public void setBadgeColor(int drawable) {
this.Badge.setBackgroundResource(drawable);
}
public void setBadge(String badge) {
this.Badge.setText(badge);
}
}
#Override
public int getSwipeLayoutResourceId(int position) {
return R.id.swipe;
}
#Override
public void openItem(int position) {
}
#Override
public void closeItem(int position) {
}
#Override
public void closeAllExcept(SwipeLayout layout) {
}
#Override
public void closeAllItems() {
}
#Override
public List<Integer> getOpenItems() {
return null;
}
#Override
public List<SwipeLayout> getOpenLayouts() {
return null;
}
#Override
public void removeShownLayouts(SwipeLayout layout) {
}
#Override
public boolean isOpen(int position) {
return false;
}
#Override
public Attributes.Mode getMode() {
return null;
}
#Override
public void setMode(Attributes.Mode mode) {
}
}
My NewOrder Fragment
Note: the FinishedOrders tab (fragment) does the same thing as new order but filters the current the Finished status.
public class NewOrdersTab extends Fragment {
RecyclerView recyclerView;
OrdersDataAdapter adapter;
private SwipeRefreshLayout swiperefresh;
private TextView emptyView;
ArrayList<OrderPresenter> modelData;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.new_orders_tab_frag, container, false);
modelData = new ArrayList<>();
recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
swiperefresh = (SwipeRefreshLayout) rootView.findViewById(R.id.swiperefresh);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getActivity()));
swiperefresh.setColorSchemeResources(R.color.colorPrimary, R.color.color_error, R.color.colorInfo);
adapter = new OrdersDataAdapter(modelData, getActivity());
emptyView = (TextView) rootView.findViewById(R.id.empty_view);
recyclerView.setAdapter(adapter);
adapter.setMode(Attributes.Mode.Single);
OrderRepository.fetchOrders("awaiting-shipment", getActivity(), new DataFetch() {
#Override
public void onResponse(ArrayList<OrderPresenter> data) {
swiperefresh.setRefreshing(true);
if (data.size() != 0) {
swiperefresh.setRefreshing(true);
emptyView.setVisibility(View.GONE);
modelData.clear();
modelData.addAll(data);
adapter.notifyDataSetChanged();
} else {
emptyView.setVisibility(View.VISIBLE);
emptyView.setText(getString(R.string.No_New_Orders));
}
swiperefresh.setRefreshing(false);
}
});
return rootView;
}
}
I figured it out, I just added these two lines after I make the request..!
orders.remove(position);
notifyItemRemoved(position);
//notifyDataSetChanged(position);

Duplicate items in the recyclerView

I am new here, I have an activity that contains ViewPager with two Fragments. Each Fragment has a RecyclerView. on selecting a tab through OnTabSelection items in the RecyclerView gets repeated. I can't understand what is causing this problem.
I am using DataHandler to save the data because I have to use this data in other activities as well.
class DataHandler {
private ArrayList<MenuHolder> listOfItemsFromJson;
private static DataHandler mInstance = null;
static public DataHandler getInstance() {
if (null == mInstance) {
mInstance = new DataHandler();
}
return mInstance;
}
public DataHandler() {
listOfItemsFromJson = new ArrayList<>();
}
public ArrayList<MenuHolder> getListOfItemsFromJson() {
return listOfItemsFromJson;
}
public void clearList() {
listOfItemsFromJson.clear();
}
public void addData(MenuHolder holder) {
listOfItemsFromJson.add(holder);
}
public MenuHolder getData(int position) {
return listOfItemsFromJson.get(position);
}
public void removeData(int position) {
listOfItemsFromJson.remove(getData(position));
}
public int size() {
return listOfItemsFromJson.size();
}
}
Here is my Fragment
class ComboRecycler extends Fragment {
private ArrayList<Integer> index = new ArrayList<>();
private LinearLayout mViewCartLayout;
private RelativeLayout relativeLayout;
private RecyclerView recyclerView;
RecyclerView.Adapter recyclerAdapter;
RecyclerView.LayoutManager recylerViewLayoutManager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recycler_combo, container, false);
relativeLayout = (RelativeLayout) view.findViewById(R.id.relativelayout1);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
recylerViewLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(recylerViewLayoutManager);
new FetchTask().execute();
return view;
}
public class FetchTask extends AsyncTask<Void, Void, JSONArray> {
#Override
protected JSONArray doInBackground(Void... params) {
JSONArray jsonArray;
........
}
#Override
protected void onPostExecute(JSONArray result) {
if (result != null) {
try {
for (int i = 0; i < DataHandler.getInstance().size(); i++) {
if (DataHandler.getInstance().getData(i).isCombo()) {
DataHandler.getInstance().removeData(i);
}
}
for (int i = 0; i < result.length(); i++) {
JSONObject mJsonObject = result
.getJSONObject(i);
MenuHolder mDataHolder = new MenuHolder();
......
mDataHolder.setCombo(true);
mDataHolder.setItemCount("0");
DataHandler.getInstance().addData(mDataHolder);
}
setAdapter();
} catch (Exception e) {
}
}
}
}
private void setAdapter() {
index.clear();
for (int i = 0; i < DataHandler.getInstance().size(); i++) {
if (DataHandler.getInstance().getListOfItemsFromJson().get(i).isCombo()) {
index.add(i);
}
}
recyclerComboAdapter = new RecyclerComboAdapter(getActivity(), index);
recyclerView.setAdapter(recyclerComboAdapter);
}
}
Here is my RecyclerAdapter
class RecyclerComboAdapter extends RecyclerView.Adapter<RecyclerComboAdapter.ViewHolder> {
Context context;
View view1;
ViewHolder viewHolder1;
ArrayList<Integer> index;
LinearLayout mViewCart;
Recycler recycler;
private AQuery mQuery;
public RecyclerComboAdapter(Context context1, ArrayList<Integer> index) {
this.index = index;
context = context1;
mQuery = new AQuery(context1);
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view1 = LayoutInflater.from(context).inflate(R.layout.combo_meals_adapter, parent, false);
viewHolder1 = new ViewHolder(view1);
return viewHolder1;
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final int pos = position;
MenuHolder menuHolder =DataHandler.getInstance().getData(index.get(position));
holder.itemName.setText(menuHolder.getItemname());
holder.itemPrice.setText(menuHolder.getItemprice());
mQuery.id(holder.imageView).image(menuHolder.getItemPicture());
holder.counter.setText(menuHolder.getItemCount());
}
#Override
public int getItemCount() {
return index.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView add, minus, plus, counter, itemName, itemPrice;
ViewHolder(View v) {
super(v);
itemName = (TextView) v.findViewById(R.id.itemnametxt);
imageView = (ImageView) v.findViewById(R.id.image);
itemPrice = (TextView) v.findViewById(R.id.price);
minus = (TextView) v.findViewById(R.id.minus);
plus = (TextView) v.findViewById(R.id.plus);
counter = (TextView) v.findViewById(R.id.count);
add = (TextView) v.findViewById(R.id.addtxt);
}
}
}
After swiping the list multiple times I am seeing repeated list items. Please help me with this problem. Thanks in advance.

Update and control multiple CountDownTimer in RecyclerView (pause, resume, delete)

I've implemented to my Android app multiple countdown timers with Service.
CountDownTimer is running with service, thus data to fragment is being passed with BroadcastReceiver.
I would like to add each timer as a separate item to the RecyclerView in the fragment and be able to update it as timer is ticking and also to control it - pause, resume, add 1 min and delete.
At the moment the problem is that each second that timer is running, new item is added to RecyclerView and I'm not able to control it - pause, resume and ect.
Service Class:
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constants.ACTION.START_FOREGROUND_ACTION)){
HandlerThread thread = new HandlerThread("ServiceStartArguments",
android.os.Process.THREAD_PRIORITY_BACKGROUND);
thread.setName(nameOfFood);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
Thread.currentThread().setName(nameOfFood);
try {
showCountDownTimer(enteredTimeFormatted);
} catch (Exception e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
stopSelf(msg.arg1);
}
private void showCountDownTimer(long number) {
String normalStartTime = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(number),
TimeUnit.MILLISECONDS.toMinutes(number) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(number)),
TimeUnit.MILLISECONDS.toSeconds(number) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(number)));
Intent timerStartInfoIntent = new Intent(TIMER_START_INFO);
timerStartInfoIntent.putExtra("VALUE", normalStartTime);
timerStartInfoIntent.putExtra("NAME_FOOD", nameOfFood);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerStartInfoIntent);
CountDownTimer timer = new CountDownTimer(number, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeLeft = millisUntilFinished;
counter = millisUntilFinished / 1000;
normalTime = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(timeLeft),
TimeUnit.MILLISECONDS.toMinutes(timeLeft) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeLeft)),
TimeUnit.MILLISECONDS.toSeconds(timeLeft) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeLeft)));
Intent timerInfoIntent = new Intent(TIME_INFO);
timerInfoIntent.putExtra("VALUE", normalTime);
timerInfoIntent.putExtra("NAME_FOOD", nameOfFood);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerInfoIntent);
}
#Override
public void onFinish() {
counter = 0;
Intent timerFinishInfoIntent = new Intent(TIMER_FINISH_INFO);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerFinishInfoIntent);
}
};
timer.start();
}
Adapter Class:
public class TimerRecyclerViewAdapter extends RecyclerView.Adapter<TimerRecyclerViewAdapter.MyViewHolder> {
final private Context mContext;
public List<ModelTimer> mModelTimerList;
private final List<MyViewHolder> listHolder;
public TimerRecyclerViewAdapter(List<ModelTimer> modelTimerList, Context context) {
super();
this.mContext = context;
this.mModelTimerList = modelTimerList;
listHolder = new ArrayList<>();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView nameTextView;
public final TextView timerTextView;
public final Button pauseBtn;
public final Button addMinBtn;
public final Button deleteBtn;
ModelTimer mModelTimer;
public MyViewHolder(View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.active_timer_name);
timerTextView = (TextView) itemView.findViewById(R.id.active_timer_timeLeft);
pauseBtn = (Button) itemView.findViewById(R.id.active_timer_btn_pause);
pauseBtn.setOnClickListener(this);
addMinBtn = (Button) itemView.findViewById(R.id.active_timer_btn_addMin);
addMinBtn.setOnClickListener(this);
deleteBtn = (Button) itemView.findViewById(R.id.active_timer_btn_delete);
deleteBtn.setOnClickListener(this);
}
public void setData (ModelTimer modelTimer){
this.mModelTimer = modelTimer;
timerTextView.setText(modelTimer.expirationTime);
nameTextView.setText(modelTimer.name);
}
#Override
public void onClick(View v) {
// TODO
}
}
#Override
public TimerRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (parent instanceof RecyclerView) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_active_timer,
parent,
false);
v.setFocusable(true);
return new MyViewHolder(v);
} else {
throw new RuntimeException("No bound to RecyclerViewSelection");
}
}
#Override
public void onBindViewHolder(TimerRecyclerViewAdapter.MyViewHolder holder, int position) {
holder.setData(mModelTimerList.get(position));
synchronized (listHolder){
listHolder.add(holder);
}
}
#Override
public int getItemCount() {
return mModelTimerList.size();
}
Here I tried to create a method that will be upgrading each second a timer on specific position instead of adding new item to RecyclerView each time that timer is ticking.
public void swap(List<ModelTimer> modelTimerList){
mModelTimerList.clear();
mModelTimerList.addAll(modelTimerList);
notifyItemChanged(???);
}
public void delete() {
mModelTimerList.clear();
notifyDataSetChanged();
}
}
Fragment with RecyclerView:
public class ActiveTimersFragment extends Fragment {
private RecyclerView mRecyclerView;
private TimerRecyclerViewAdapter mAdapter;
private ArrayList<ModelTimer> listOfTimers;
private TimerStatusReceiver mTimerStatusReceiver;
private static final String ARG_SECTION_NUMBER = "section_number";
public ActiveTimersFragment() {
}
public static ActiveTimersFragment newInstance(int sectionNumber) {
ActiveTimersFragment activeTimersFragment = new ActiveTimersFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
activeTimersFragment.setArguments(args);
return activeTimersFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_active_timers, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_active_timers_recycler_view);
mTimerStatusReceiver = new TimerStatusReceiver();
listOfTimers = new ArrayList<>();
return view;
}
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIME_INFO));
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIMER_START_INFO));
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIMER_FINISH_INFO));
}
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mTimerStatusReceiver);
}
private class TimerStatusReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals(NotificationService.TIME_INFO)) {
ModelTimer modelTimer = new ModelTimer();
if (intent.hasExtra("VALUE")) {
modelTimer.setexpirationTime(intent.getStringExtra("VALUE"));
}
if (intent.hasExtra("NAME_FOOD")) {
modelTimer.setName(intent.getStringExtra("NAME_FOOD"));
}
listOfTimers.add(modelTimer);
mAdapter = new TimerRecyclerViewAdapter(listOfTimers, getActivity());
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// Not working
// mAdapter.swap(listOfTimers);
mRecyclerView.setAdapter(mAdapter);
}
if (intent != null && intent.getAction().equals(NotificationService.TIMER_FINISH_INFO)) {
mAdapter.delete();
}
}
}
}
Your whole implementation of recyclerview adapter is wrong. In onBindViewHolder() you are adding new item. onBindViewHolder is called when RecyclerView tries to show new item. So it keeps on iterating, if you add new item in onBindViewHolder. Also, you should use the onBindViewHolder to set the views values in ViewHolder class. Check the whole adapter implementation.
public class TimerRecyclerViewAdapter extends RecyclerView.Adapter<TimerRecyclerViewAdapter.MyViewHolder> {
final private Context mContext;
public List<ModelTimer> mModelTimerList;
public TimerRecyclerViewAdapter(List<ModelTimer> modelTimerList, Context context) {
super();
this.mContext = context;
this.mModelTimerList = modelTimerList;
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView nameTextView;
public final TextView timerTextView;
public final Button pauseBtn;
public final Button addMinBtn;
public final Button deleteBtn;
public MyViewHolder(View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.active_timer_name);
timerTextView = (TextView) itemView.findViewById(R.id.active_timer_timeLeft);
pauseBtn = (Button) itemView.findViewById(R.id.active_timer_btn_pause);
pauseBtn.setOnClickListener(this);
addMinBtn = (Button) itemView.findViewById(R.id.active_timer_btn_addMin);
addMinBtn.setOnClickListener(this);
deleteBtn = (Button) itemView.findViewById(R.id.active_timer_btn_delete);
deleteBtn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// TODO
}
}
#Override
public TimerRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (parent instanceof RecyclerView) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_active_timer,
parent,
false);
v.setFocusable(true);
return new MyViewHolder(v);
} else {
throw new RuntimeException("No bound to RecyclerViewSelection");
}
}
#Override
public void onBindViewHolder(TimerRecyclerViewAdapter.MyViewHolder holder, int position) {
ModelTimer modelTimer=mModelTimerList.get(position);
holder.timerTextView.setText(modelTimer.expirationTime);
holder.nameTextView.setText(modelTimer.name);
}
#Override
public int getItemCount() {
return mModelTimerList.size();
}

Categories

Resources