Update RecyclerView with Firebase Values not working - android

I am working on a Bus app and visualized the seats of a bus in an activity using Recyclerview as follows
I am taking the no of available and booked seats from Firebase. What I want to do is
update the color of the seat according to the count of available
and booked seats.
For example, if booked seats: 2 then there should be 2 green-colored seats in the recycler view. Here is my code
SeatsFragment.java:
public class SeatsFragment extends Fragment {
public static int mCountSeat, mTotal;
public static StringBuffer mSb;
private int mSeatNo = 0;
private RecyclerView mRvViewSeats;
private ImageView mIvAvailable, mIvBooked;
private LinearLayout mLinear, mLlDack, mLlDynamic;
private List<AbstractItem> mAbstractItemsList;
private List<SeatModel> mSeatModelsItemsList;
private TextView tvAvailabe, tvBooked;
SeatAdapter adapter;
// Firebase
FirebaseDatabase database;
DatabaseReference seatsRef;
public SeatsFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_seats, container, false);
tvAvailabe = view.findViewById(R.id.tvAvailableSeats);
tvBooked = view.findViewById(R.id.tvBookedSeats);
database = FirebaseDatabase.getInstance();
seatsRef = database.getReference(Common.SEATS_REFERENCE).child("2").child(Common.AVAILABLE_SEATS);
// Toast.makeText(getActivity(), seatsRef.toString(), Toast.LENGTH_SHORT).show();
seatsRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
tvBooked.setText(snapshot.getValue().toString());
tvAvailabe.setText(String.valueOf(40 - (Long.parseLong(snapshot.getValue().toString()))));
mSeatModelsItemsList.add(new SeatModel(SeatType.AVAILABLE.BOOKED));
initializeSeats();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initLayouts(view);
initializeSeats();
}
/* initialize seats */
private void initializeSeats() {
mIvAvailable.setColorFilter(ContextCompat.getColor(getActivity(), R.color.view_color));
mIvBooked.setColorFilter(ContextCompat.getColor(getActivity(), R.color.colorPrimary));
for (int i = 0; i < 40; i++) {
mSeatModelsItemsList.add(new SeatModel(SeatType.BOOKED));
mSeatModelsItemsList.add(new SeatModel(SeatType.AVAILABLE));
int mCOLUMNS = 5;
if (i % mCOLUMNS == 0 || i % mCOLUMNS == 4) {
mSeatNo++;
mAbstractItemsList.add(new EdgeItem(String.valueOf(mSeatNo)));
} else if (i % mCOLUMNS == 1 || i % mCOLUMNS == 3) {
mSeatNo++;
mAbstractItemsList.add(new CenterItem(String.valueOf(mSeatNo)));
} else {
mAbstractItemsList.add(new EmptyItem(mSeatModelsItemsList));
}
GridLayoutManager mManager = new GridLayoutManager(getActivity(), mCOLUMNS);
mRvViewSeats.setLayoutManager(mManager);
adapter = new SeatAdapter(mSeatModelsItemsList, mAbstractItemsList, getActivity());
mRvViewSeats.setAdapter(adapter);
}
mSeatNo = 0;
}
private void initLayouts(View view) {
mLinear = view.findViewById(R.id.llOffer);
mIvAvailable = view.findViewById(R.id.ivAvailable);
mIvBooked = view.findViewById(R.id.ivSeatFragmentBooked);
mAbstractItemsList = new ArrayList<>();
mSeatModelsItemsList = new ArrayList<>();
mSb = new StringBuffer();
mRvViewSeats = view.findViewById(R.id.rvSeat);
mLlDack = view.findViewById(R.id.lvDack);
mLlDynamic = view.findViewById(R.id.llDynamicContent);
}
}
Look at the initializeSeats() method above. I've added two items(available and booked) to the list that is passed to the adapter. These items should be added according to the no of available and booked seats
e.g
if booked seats are 38, then 38 booked items should be added to the list
When I try to call initializeSeats() in the onDataChange() it adds the correct no of seats to list but
since seats are added through loop every time seats get doubled, 1st time 40,80 and so on.
SeatsAdapter.java:
public class SeatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<SeatModel> mSeatItem;
private List<AbstractItem> mItems;
private LayoutInflater mLayoutInflater;
private Context mCtx;
public SeatAdapter(List<SeatModel> mSeatItem, List<AbstractItem> mItems, Context mCtx) {
this.mSeatItem = mSeatItem;
this.mItems = mItems;
this.mCtx = mCtx;
mLayoutInflater = LayoutInflater.from(mCtx);
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == AbstractItem.TYPE_CENTER) {
View itemView = mLayoutInflater.inflate(R.layout.list_item_seat, parent, false);
return new CenterViewHolder(itemView);
} else if (viewType == AbstractItem.TYPE_EDGE) {
View itemView = mLayoutInflater.inflate(R.layout.list_item_seat, parent, false);
return new EdgeViewHolder(itemView);
} else {
View itemView = new View(mCtx);
return new EmptyViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
int type = mItems.get(position).getType();
final SeatModel seatModel = mSeatItem.get(position);
if (type == AbstractItem.TYPE_CENTER) {
final CenterViewHolder centerViewHolder = (CenterViewHolder)holder;
if (seatModel.getSeatType().equals(SeatType.AVAILABLE)){
centerViewHolder.mIvSeat.setVisibility(View.VISIBLE);
} else {
centerViewHolder.mIvSeatBooked.setVisibility(View.VISIBLE);
}
} else if (type == AbstractItem.TYPE_EDGE) {
final EdgeViewHolder edgeViewHolder = (EdgeViewHolder) holder;
if (seatModel.getSeatType().equals(SeatType.AVAILABLE)){
edgeViewHolder.mIvSeat.setVisibility(View.VISIBLE);
} else {
edgeViewHolder.mIvSeatBooked.setVisibility(View.VISIBLE);
}
}
}
#Override
public int getItemCount() {
return mItems.size();
}
#Override
public int getItemViewType(int position) {
return mItems.get(position).getType();
}
/*view holder*/
private static class CenterViewHolder extends RecyclerView.ViewHolder {
private ImageView mIvSeat, mIvSeatBooked;
CenterViewHolder(View itemView) {
super(itemView);
mIvSeat = itemView.findViewById(R.id.ivSeat);
mIvSeatBooked = itemView.findViewById(R.id.ivSeatBooked);
}
}
/*view holder*/
private static class EdgeViewHolder extends RecyclerView.ViewHolder {
private ImageView mIvSeat, mIvSeatBooked;
EdgeViewHolder(View itemView) {
super(itemView);
mIvSeat = itemView.findViewById(R.id.ivSeat);
mIvSeatBooked = itemView.findViewById(R.id.ivSeatBooked);
}
}
/*view holder*/
private static class EmptyViewHolder extends RecyclerView.ViewHolder {
EmptyViewHolder(View itemView) {
super(itemView);
}
}
}
Any help or guidance would be appreciable.
Thank you.

You just keep on adding new data in your onDataChange callback, you should clear the data when you have a new data change.
There is no need to create new adapter each time, you create your adapter once and then you just notify about changes, you should add a method in your adapter that will take a new list so you can update it in other way not only though the constructor only.
I would strongly recommend taking a look at Diff Utils It is the best way to update data inside RecyclerView and the most performant.
There are many resources on it so you can find a lot about it.
Example: https://iammert.medium.com/using-diffutil-in-android-recyclerview-bdca8e4fbb00

Inside your value eventListener you need to clear the list every time, and because you are not doing this so every time the new data gets added to the older ones that's why you are facing this issue. Add this line mSeatModelsItemsList.clear();
Solution is here
seatsRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
mSeatModelsItemsList.clear();// add this line
tvBooked.setText(snapshot.getValue().toString());
tvAvailabe.setText(String.valueOf(40 - (Long.parseLong(snapshot.getValue().toString()))));
mSeatModelsItemsList.add(new SeatModel(SeatType.AVAILABLE.BOOKED));
initializeSeats();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});

Related

Firestore Recycler loads in one page (instance) but not another

I have a restaurant app with a food page that is populated by 2 Firestore recycler views. The weird this is one restaurant loads everything normal but the others fail. I have gone over the database and everything seems fine there but it just won't work. here are some images showing the differences:
PS how do i resize uploaded images?
As you can see there is no size option in the first pic but the 2nd pic has them.
here is my code:
the page:
private void setUpSizes() {
if (getIntent() != null)
foodId = getIntent().getStringExtra("foodid");
Log.d("TAG", "setUpSizes: "+foodId);
if (!foodId.isEmpty() && foodId != null) {
Log.d("TAG", "setUpSizes: "+foodId);
Query foodSizes = db.collectionGroup("sizes").whereEqualTo("id", foodId);
FirestoreRecyclerOptions<SizeOptionsModel> options = new FirestoreRecyclerOptions.Builder<SizeOptionsModel>()
.setQuery(foodSizes, SizeOptionsModel.class)
.build();
mSelectedFoodSizeAdapter = new SizeOptionsAdapter(options);
RecyclerView recyclerView = findViewById(R.id.size_recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(mSelectedFoodSizeAdapter);
}
}
}
#Override
protected void onStart() {
super.onStart();
mSelectedFoodExtrasAdapter.startListening();
mSelectedFoodSizeAdapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
mSelectedFoodExtrasAdapter.stopListening();
mSelectedFoodSizeAdapter.stopListening();
}
}
the adapter:
private FoodSizesHolder holder;
private int mSelectedItem = -1;
private Context context;
public String getPriceFromAdapter() {
return priceFromAdapter;
}
private String priceFromAdapter;
public SizeOptionsAdapter(#NonNull FirestoreRecyclerOptions<SizeOptionsModel> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull FoodSizesHolder holder, int position, #NonNull SizeOptionsModel model) {
holder.food_size.setText(model.getName());
holder.food_size_price.setText(model.getPrice());
//Allow only one radio button to be checked
holder.food_size.setChecked(position == mSelectedItem);
//Auto select the first item
}
#Override
public int getItemCount() {
return super.getItemCount();
}
#NonNull
#Override
public FoodSizesHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.sizes_item, parent, false);
return new FoodSizesHolder(v);
}
class FoodSizesHolder extends RecyclerView.ViewHolder {
RadioButton food_size;
TextView food_size_price;
public FoodSizesHolder(#NonNull final View itemView) {
super(itemView);
food_size = itemView.findViewById(R.id.sizes_checkbox);
food_size_price = itemView.findViewById(R.id.sizes_prices);
if (food_size.isChecked()){
priceFromAdapter = String.valueOf(food_size_price.getText());
}
}
});
}
}
}

Recyclerview is not showing data even everything seems alright

This is my fragment code below.
public class pendingactivity extends Fragment {
MyViewModel myViewModel;
List<Activity_> activity_list;
CheckBox act_check;
View view;
int project_id;
Projectid_pointing_towards_activity PPta;
public pendingactivity() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
RecyclerView mrecyclerView;
//Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_pendingactivity, container, false);
mrecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_frag1);
act_check = (CheckBox) view.findViewById(R.id.activity_check);
myViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
myViewModel.GetAllPPTA().observe(this, new Observer<List<Projectid_pointing_towards_activity>>()
{
#Override
public void onChanged(List<Projectid_pointing_towards_activity> PPTA) {
PPta = PPTA.get(1);
project_id = PPta.getProject_id();
}
});
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mrecyclerView.setLayoutManager(linearLayoutManager);
final activitycardAdaptor Acticityadaptor = new activitycardAdaptor(getContext(), project_id);
myViewModel.GetAllActivity().observe(this, new Observer<List<Dactivity>>() {
#Override
public void onChanged(List<Dactivity> dactivities) {
Acticityadaptor.setActivity(dactivities);
}
});
mrecyclerView.setAdapter(Acticityadaptor);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
below is my recyler adapter code
package com.example.builderpro;
public class activitycardAdaptor extends RecyclerView.Adapter<ActivityCardViewHolder> {
private Context context;
private List<Dactivity> mactivity;
int project_id;
public activitycardAdaptor(Context context, int id) {
this.context = context;
this.project_id = id;
}
#Override
public ActivityCardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mview = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_activity, parent,
false);
return new ActivityCardViewHolder(mview);
}
#Override
public void onBindViewHolder(ActivityCardViewHolder holder, int position) {
Dactivity dactivity = mactivity.get(position);
holder.Activity_title.setText(dactivity.getName());
holder.Activity_Type.setText(dactivity.getType());
Calendar calendar = Calendar.getInstance();
String curentDate = DateFormat.getDateInstance(DateFormat.FULL).format(calendar.getTime());
holder.Date.setText(curentDate);
}
#Override
public int getItemCount() {
return mactivity == null ? 0 : mactivity.size();
}
public void setActivity(List<Dactivity> dactivities) {
Dactivity current_activity;
for (int i = 0; i < dactivities.size(); i++) {
current_activity = dactivities.get(i);
if (project_id == current_activity.getProject_id()) {
mactivity.add(current_activity);
}
}
notifyDataSetChanged();
}
}
class ActivityCardViewHolder extends RecyclerView.ViewHolder {
CardView mcardview;
TextView Activity_title, Activity_Type, Date;
CheckBox activity_check;
public ActivityCardViewHolder(View itemView) {
super(itemView);
Activity_title = itemView.findViewById(R.id.Activity_name);
Activity_Type = itemView.findViewById(R.id.activity_type);
Date = itemView.findViewById(R.id.date);
activity_check = itemView.findViewById(R.id.activity_check);
mcardview = itemView.findViewById(R.id.activity_card);
}
}
Same code i'm running in another fragment and adapter and there is no error at debug time . i have tried many solution available on internet but nothing going right for my code. i think data is not entering in the list name of mactivity in adapter. Kindly help me because i'm stuck on this about 3 days.
I don't know if it's a mistake in your post or if it's in your code but something looks rather strange here final activitycardAdaptor Acticityadaptor = new activitycardAdaptor(getContext(), project_id); shouldn't it be final ActivitycardAdaptor acticityAdaptor = new ActivitycardAdaptor(getContext(), project_id); ?

Recyclerview ListAdapter not updating

I have implemented a basic ListAdapter in RecyclerView as I am using View Model. The data I am getting is from networkManager to Viewmodel by calling API. Even when I did got the data the submitList is not Working and thus no data is getting inflated.
UpcomingGroupFragment
public class UpcomingGroupFragment extends Fragment {
private UpcomingViewModel mViewModel;
private RecyclerView recyclerView;
private GroupAdapter_new adapter;
public static UpcomingGroupFragment newInstance() {
return new UpcomingGroupFragment();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_chatgroups, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
adapter = new GroupAdapter_new();
recyclerView.setAdapter(adapter);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(UpcomingViewModel.class);
mViewModel.getMutableLiveData().observe(this, new Observer<List<ChatGroups_New>>() {
#Override
public void onChanged(#Nullable List<ChatGroups_New> chatGroups_news) {
adapter.submitList(chatGroups_news);
Log.e("Upcoming", String.valueOf(chatGroups_news.size()));
}
});
}
}
The Adapter Class extends the ListAdapter.
Link for overriding submitlist: https://stackoverflow.com/a/50062174
The Code is as follows:
GroupAdapter_new
public class GroupAdapter_new extends ListAdapter<ChatGroups_New,GroupAdapter_new.ViewHolder> {
public GroupAdapter_new() {
super(DIFF_CALLBACK);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
int layoutID = R.layout.ongoing_group;
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(layoutID,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ChatGroups_New currentGroup = getItem(position);
holder.text_flightarrival.setText(currentGroup.getFlightNameArrival());
}
class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
//... Finding ID's for various Views
}
}
/****ADDED THIS FROM CODE*****/
#Override
public void submitList(List<ChatGroups_New> list) {
super.submitList(list != null ? new ArrayList<ChatGroups_New>() : null);
}
/***********/
private static final DiffUtil.ItemCallback<ChatGroups_New> DIFF_CALLBACK =
new DiffUtil.ItemCallback<ChatGroups_New>() {
#Override
public boolean areItemsTheSame(ChatGroups_New oldItem, ChatGroups_New newItem) {
Log.e("areItemsTheSame", String.valueOf(oldItem.getMergedLogId() == newItem.getMergedLogId()));
return oldItem.getMergedLogId() == newItem.getMergedLogId();
}
#Override
public boolean areContentsTheSame(ChatGroups_New oldItem, ChatGroups_New newItem) {
if(oldItem.getFlightIcon().equals(newItem.getFlightIcon()) && oldItem.getFlightNameArrival().equals(newItem.getFlightNameArrival())){
if(oldItem.getGateValue().equals(newItem.getGateValue()) && oldItem.getEtaValue().equals(newItem.getEtaValue())){
if(oldItem.getAlertValue().equals(newItem.getAlertValue()) && oldItem.getTaskcompletedValue().equals(newItem.getTaskcompletedValue())){
Log.e("areContentsTheSame", "true");
return true;
}
}
}
return false;
}
};
}
If you want to see my ViewModel Class then:
UpcomingViewModel
public class UpcomingViewModel extends AndroidViewModel
implements I_NetworkResponse {
private NetworkManager networkManager;
private SharedPrefService prefService;
private HashMap<String, String> header;
private final String TAG = "UpcomingViewModel";
private List<ChatGroups_New> upcomingList;
private MutableLiveData<List<ChatGroups_New>> mutableLiveData;
public UpcomingViewModel(#NonNull Application application) {
super(application);
prefService = SharedPrefService.getInstance(application);
networkManager = new NetworkManager(application,this);
upcomingList = new ArrayList<>();
mutableLiveData = new MutableLiveData<>();
mutableLiveData.setValue(upcomingList);
header = new HashMap<>();
header.put("authorizationcode",prefService.getStringValue(Keys.getPreferenceAuthKey()));
if(upcomingList.isEmpty()){
networkManager.Volley_JsonObjectRequest(Keys.getBaseUrl()+"AviLeap/flights/upcoming",
header,null,TAG,"AviLeap/flights/upcoming");
}
}
public MutableLiveData<List<ChatGroups_New>> getMutableLiveData() { return mutableLiveData; }
#Override
public void getNetworkSuccessResponse(String TAG, String successResponse, String TAGforApi) {
Log.e(TAGforApi,successResponse);
parseUpcomingFlight(successResponse, upcomingList);
mutableLiveData.setValue(upcomingList);
}
#Override
public void getNetworkFailResponse(String TAG, VolleyError failResponse, String TAGforApi) { }
#Override
protected void onCleared() {
super.onCleared();
networkManager.stopNetworkCallsWithTag(TAG);
}
private void parseUpcomingFlight(String successResponse, List<ChatGroups_New> upcomingList) {
try {
JSONObject rootObject = new JSONObject(successResponse);
if(rootObject.has("upcomingflights") && rootObject.opt("upcomingflights") instanceof JSONArray){
JSONArray flightsArray = rootObject.optJSONArray("upcomingflights");
for(int flightIndex = 0; flightIndex < flightsArray.length(); flightIndex++){
JSONObject flightObject = flightsArray.optJSONObject(flightIndex);
int mergedLogId = flightObject.optInt("logid");
upcomingList.add(new ChatGroups_New(mergedLogId));
Log.e("parseUpcomingFlight", String.valueOf(upcomingList.size()));//..... Log Point
}
}
}
catch (JSONException e) { e.printStackTrace(); }
}
}
Initially the Size of the List is zero, so the Error is coming for as
AviLeap/flights/upcoming: //.... API CALL
2019-03-02 13:25:53.652 8477-8477/com.avileapconnect.com E/parseUpcomingFlight: 1 2019-03-02 13:25:53.652 8477-8477/com.avileapconnect.com E/parseUpcomingFlight: 2
2019-03-02 13:25:53.653 8477-8477/com.avileapconnect.com E/Upcoming: 2
The above logs show that the data is being added to the arraylist, but it is not updating. Also after all these logs when I go back to my Fragment I get the following error.
no adapter Attached, Skipping Layout
One more thing to add is that the adapter's getItemCount is getting updated properly. But even after that I am getting error:
no adapter Attached, Skipping Layout
EDIT: I fixed the error by commenting out the code for overriding the SubmitList method. I am also setting the adapter in the observer method in the fragment Class

Adding item to a recyclerview from dialog within a fragment class.?

I have a fragment which must contains two recycler views. The view looks like follows. i need to add an item to the bottom recyclerview from a dialog. L'll post my code for the adapter class and xml. Please guide me to achieve this, a sample or a code is more than welcome.
I've tried to pass the data from the dialog to the second recyclerview but it does not show the added item. Tell me anything i'm doing wrong here. Nothing i tried worked out to update my second recyclerview... :/
My Fragment Class
public class ReceiptFragment extends Fragment { //implements ContReceiptsAdapter.ItemOnClickListener
RecyclerView rv_rceipts, rv_addpayments;
RecyclerView.Adapter mContReceiptsAdapter,mAddPaymentsAdapter;
RecyclerView.LayoutManager mLayoutManager1,mLayoutManager2;
View receipts_view;
private Context mContext;
ContReceiptsAdapter contReceiptsAdapter;
AddPaymentsAdapter addPaymentsAdapter;
//-- items in detailed dialog here
private ArrayList<Contract> contracts;
private ArrayList<AddPayments> payments;
private View linearLayout;
public View mRootView;
public ReceiptFragment() {
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
receipts_view = inflater.inflate(R.layout.fragment_receipt, container, false);
BuildReceiptsRV();
BuildAddedPaymentsRV();
// for setting the first item as default in the list
// onItemClicked(0);
return receipts_view;
}
private void BuildReceiptsRV() {
rv_rceipts = receipts_view.findViewById(R.id.rv_tobe_added);
rv_rceipts.setHasFixedSize(true);
rv_rceipts.setItemAnimator(new DefaultItemAnimator());
mLayoutManager1 = new LinearLayoutManager(getActivity());
rv_rceipts.setLayoutManager(mLayoutManager1);
mContReceiptsAdapter = new ContReceiptsAdapter(getActivity(), ApplicationClass.contractList);
rv_rceipts.setAdapter(mContReceiptsAdapter);
}
private void BuildAddedPaymentsRV() {
rv_addpayments = receipts_view.findViewById(R.id.rv_added);
rv_addpayments.setHasFixedSize(true);
rv_addpayments.setItemAnimator(new DefaultItemAnimator());
mLayoutManager2 = new LinearLayoutManager(getActivity());
rv_addpayments.setLayoutManager(mLayoutManager2);
mAddPaymentsAdapter = new AddPaymentsAdapter(getActivity(),ApplicationClass.paymentList);
rv_addpayments.setAdapter(mAddPaymentsAdapter);
}
//change when click on change on item added to second rv
private void changeLayoutRV() {
linearLayout = mRootView.findViewById(R.id.rv_tobe_added);
if (linearLayout.getVisibility() == View.GONE) {
linearLayout.setVisibility(View.VISIBLE);
} else {
linearLayout.setVisibility(View.GONE);
}
}
}
My Adapter for the First Recyclerview
public class ContReceiptsAdapter extends RecyclerView.Adapter<ContReceiptsAdapter.ReceiptsViewHolder> {
// private static Dialog AddItemDialog;
private ArrayList<Contract> contracts;
private ArrayList<AddPayments> payments = new ArrayList<>();
Context mContext;
String inPending;
//for the details dialog
EditText et_number, contract_id_val, product_type_val, mobile_number_ADialog, et_amount_add;
// ImageView btn_add_item;
//--to set to add item dialog
public TextView contract_number, vehicle_number, contract_number_ADialog, vehicle_number_ADialog;
CheckBox checkbox_pending;
public ContReceiptsAdapter(Context context, ArrayList<Contract> contractList) {
contracts = contractList;
mContext = context;
}
public class ReceiptsViewHolder extends RecyclerView.ViewHolder {
TextView tv_contract, tvVehicleN, tvContractType;
ImageView btn_add_item;
LinearLayout detailsLayout;
public ReceiptsViewHolder(#NonNull final View itemView) {
super(itemView);
detailsLayout = itemView.findViewById(R.id.add_details_item_id);
tv_contract = itemView.findViewById(R.id.tv_contract);
tvVehicleN = itemView.findViewById(R.id.tvVehicleN);
tvContractType = itemView.findViewById(R.id.tvContractType);
btn_add_item = itemView.findViewById(R.id.btn_add_item);
}
}
#NonNull
#Override
public ContReceiptsAdapter.ReceiptsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.receipt_tobe_added_rv_item, viewGroup, false);
final ReceiptsViewHolder receiptsViewHolder = new ReceiptsViewHolder(view);
//dialog ini
// ShowDetails();
final Dialog detailedDialog = new Dialog(this.mContext);
detailedDialog.setContentView(R.layout.fragment_details);
receiptsViewHolder.detailsLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//click view dto show the detaileds view of the list item
contract_number = detailedDialog.findViewById(R.id.contract_id_val);
vehicle_number = detailedDialog.findViewById(R.id.vehicle_num_val);
contract_number.setText(contracts.get(receiptsViewHolder.getAdapterPosition()).getContractNumber());
vehicle_number.setText(contracts.get(receiptsViewHolder.getAdapterPosition()).getVehicleNumber());
detailedDialog.show();
detailedDialog.setCancelable(true);
// mListener.onItemClicked(contracts.indexOf(v.getTag()));
}
});
return receiptsViewHolder;
}
#Override
public void onBindViewHolder(#NonNull final ContReceiptsAdapter.ReceiptsViewHolder viewHolder, int i) {
viewHolder.itemView.setTag(contracts.get(i));
// Contract currentItem = contracts.get(i);
viewHolder.tv_contract.setText(contracts.get(i).getContractNumber());
viewHolder.tvVehicleN.setText(contracts.get(i).getVehicleNumber());
viewHolder.tvContractType.setText(contracts.get(i).getContractType());
final Dialog AddItemDialog = new Dialog(mContext);
AddItemDialog.setContentView(R.layout.fragment_add_receipt);
viewHolder.btn_add_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// ShowDetails();7
contract_number_ADialog = AddItemDialog.findViewById(R.id.contract_id_val_add);
contract_number_ADialog.setText(contracts.get(viewHolder.getAdapterPosition()).getContractNumber());
vehicle_number_ADialog = AddItemDialog.findViewById(R.id.product_type_val_add);
vehicle_number_ADialog.setText(contracts.get(viewHolder.getAdapterPosition()).getVehicleNumber());
mobile_number_ADialog = AddItemDialog.findViewById(R.id.et_number_add);
mobile_number_ADialog.setText(contracts.get(viewHolder.getAdapterPosition()).getMobileNumber());
checkbox_pending = AddItemDialog.findViewById(R.id.checkbox_pending_add);
checkbox_pending.setChecked(Boolean.parseBoolean(contracts.get(viewHolder.getAdapterPosition()).getPendingState()));
Button btn_cancel_receipt = AddItemDialog.findViewById(R.id.btn_cancel_receipt);
Button btn_add_receipt = AddItemDialog.findViewById(R.id.btn_add_receipt);
et_amount_add = AddItemDialog.findViewById(R.id.et_amount_add);
AddItemDialog.show();
AddItemDialog.setCancelable(true);
btn_cancel_receipt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AddItemDialog.dismiss();
}
});
btn_add_receipt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AddData();
//add item to rv2
AddItemDialog.dismiss();
}
});
}
});
}
#Override
public int getItemCount() {
return contracts.size();
}
private void addAnItem(AddPayments payment) {
payments = ApplicationClass.paymentList;
payments.add(payment);
this.notifyDataSetChanged();
}
private void AddData() {
String c_code = contract_number_ADialog.getText().toString();
String c_mobile = mobile_number_ADialog.getText().toString();
String c_amount = et_amount_add.getText().toString();
AddPayments added_payment = new AddPayments(c_amount, c_code, c_mobile, "true");
payments.add(added_payment);
notifyDataSetChanged();
}
}
My Adapter class for the Second Recyclerview
public class AddPaymentsAdapter extends RecyclerView.Adapter<AddPaymentsAdapter.AddPayViewHolder> {
private ArrayList<AddPayments> payments;
Context mContext;
public AddPaymentsAdapter(Context context, ArrayList<AddPayments> addPayments) {
mContext = context ;
payments = addPayments;
}
public class AddPayViewHolder extends RecyclerView.ViewHolder{
TextView tv_contract_d, tv_amount_d, tv_isPending_d, tv_mobile_num_d;
ImageView btn_delete_item;
ConstraintLayout addedPaymentLayout;
public AddPayViewHolder(#NonNull View itemView) {
super(itemView);
addedPaymentLayout = itemView.findViewById(R.id.added_payment_item_id);
tv_contract_d = itemView.findViewById(R.id.tv_contract_d);
tv_amount_d = itemView.findViewById(R.id.tv_amount_d);
tv_isPending_d = itemView.findViewById(R.id.tv_isPending_d);
tv_mobile_num_d = itemView.findViewById(R.id.tv_mobile_num_d);
btn_delete_item = itemView.findViewById(R.id.btn_delete_item);
}
}
#NonNull
#Override
public AddPaymentsAdapter.AddPayViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.receipt_added_rv_item, viewGroup, false);
final AddPayViewHolder addPayViewHolder= new AddPayViewHolder(view);
return addPayViewHolder;
}
#Override
public void onBindViewHolder(#NonNull AddPaymentsAdapter.AddPayViewHolder addPayViewHolder, final int i) {
AddPayments currentItem = payments.get(i);
addPayViewHolder.itemView.setTag(payments.get(i));
addPayViewHolder.tv_contract_d.setText(payments.get(i).getAddContractCode());
addPayViewHolder.tv_isPending_d.setText(payments.get(i).getAddIsPending());
addPayViewHolder.tv_amount_d.setText(payments.get(i).getAddAmount());
addPayViewHolder.tv_mobile_num_d.setText(payments.get(i).getAddMobile());
addPayViewHolder.btn_delete_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//delete function
// Toast.makeText(mContext, "clicked delete icon inHoldernAdapter", Toast.LENGTH_SHORT).show();
removeItem(i);
}
});
}
#Override
public int getItemCount() {
return payments.size();
}
private void removeItem(int i) {
payments.remove(i);
this.notifyItemRemoved(i);
}
}
From your code in the adapter for the first recycler view you are using this method AddData(); to add data. But this method adds data to payments which is the list where you hold the data which you want to show in the second recycler view but have no connection to it(it's just a field of the adapter class).
The this.notifyDataSetChanged() notifies the current adapter for a change in data(first recycler view). You will need to add this data to the second recycler view adapter thou. You aren't doing that right now.
So a way would be to create a method inside of the fragment which takes a list of AddPayments as argument and add this data to the second recycler view adapater. It would be something like this:
Fragment method:
public void addSecondRVData(AddPayments itemToAdd) {
mAddPaymentsAdapter.addNewPayment(itemToAdd);
}
Second recycler view method:
public void addData(AddPayments itemToAdd) {
payments.add(itemToAdd);
this.notifyDataSetChanged():
}
Dont forget to initialize the payment list in the second recycler view.
Then in the first adapter do smth like this:
private ReceiptFragment receiptFragment;
//Constructor
public ContReceiptsAdapter(Context context, ArrayList<Contract> contractList, ReceiptFragment receiptFragment) {
contracts = contractList;
mContext = context;
this.receiptFragment = receiptFragment;
}
//Use this to add elements to second rv
receiptFragment.addSecondRVData(newItem);
Hope this helps although is not the cleanest solution. Check the example I wrote here because can't test it at the moment.

Admob banner ads making my recyclerview lag

I am showing banner ads within my android app. I followed official doc for implementing admob banner contentView ads and I successfully loaded ads but now my recyclerview starts lagging like hell. If i remove ads from my code scroll becomes smooth. Please help me with this problem.
Here's my fragment class
public class WallpaperFragment extends Fragment {
private RecyclerView recyclerView;
private DatabaseReference wallRef;
private String category;
private FirebaseAuth mAuth;
private final String CATEGORY = "Category";
private Context context;
private ArrayList<Object> modelList = new ArrayList<>();
private GridLayoutManager manager;
// The number of native ads to load and display.
public int NUMBER_OF_ADS = 5;
// List of native ads that have been successfully loaded.
private List<NativeAd> mNativeAds = new ArrayList<>();
private WallpaperAdapter adapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fg_wallpaper, container, false);
category = "Recent";
init(view);
Util.showDialog(context, "Loading wallpapers...");
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return (position % (SPACE_BETWEEN_ADS + 1) == SPACE_BETWEEN_ADS) ? 2 : 1;
}
});
setScrollListener();
initializeFirebaseDatabase();
return view;
}
private void init(View view) {
context = getContext();
MobileAds.initialize(context, getString(R.string.admob_app_id));
wallRef = FirebaseDatabase.getInstance().getReference().child(WALL).child(CATEGORY).child(category).getRef();
mAuth = FirebaseAuth.getInstance();
recyclerView = view.findViewById(R.id.recyclerView);
manager = new GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(manager);
recyclerView.addItemDecoration(new GridItemDecor(0));
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(null);
}
private void setScrollListener() {
recyclerView.addOnScrollListener(new HidingScrollListener() {
#Override
public void onHide() {
if (context instanceof ToolbarShowHideListener) {
((ToolbarShowHideListener) context).hideBottomNavigation();
}
}
#Override
public void onShow() {
if (context instanceof ToolbarShowHideListener) {
((ToolbarShowHideListener) context).showBottomNavigation();
}
}
});
}
private void initializeFirebaseDatabase() {
mNativeAds.clear();
wallRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
modelList.clear();
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
WallpaperModel model = childDataSnapshot.getValue(WallpaperModel.class);
modelList.add(model);
}
NUMBER_OF_ADS = modelList.size() / 2;
loadNativeAd();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void loadNativeAd() {
loadNativeAd(0);
}
private void insertAdsInMenuItems() {
if (mNativeAds.size() <= 0) {
return;
}
int offset = (modelList.size() / mNativeAds.size()) + 1;
int index = 2;
for (NativeAd ad : mNativeAds) {
modelList.add(index, ad);
index = index + offset;
}
if (adapter == null) {
adapter = new WallpaperAdapter(context, modelList, Objects.requireNonNull(mAuth.getCurrentUser()).getUid(), true, WALLPAPER_FRAGMENT);
recyclerView.setAdapter(adapter);
} else {
adapter.updateList(modelList);
}
}
private void loadNativeAd(final int adLoadCount) {
if (adLoadCount >= NUMBER_OF_ADS) {
insertAdsInMenuItems();
return;
}
AdLoader.Builder builder = new AdLoader.Builder(context, /*getString(R.string.ad_unit_id)*/"ca-app-pub-3940256099942544/2247696110");
AdLoader adLoader = builder.forContentAd(new NativeContentAd.OnContentAdLoadedListener() {
#Override
public void onContentAdLoaded(NativeContentAd ad) {
// A content ad loaded successfully, call this method again to
// load the next ad in the items list.
mNativeAds.add(ad);
loadNativeAd(adLoadCount + 1);
}
}).withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// A native ad failed to load. Call this method again to load
// the next ad in the items list.
Log.e("MainActivity", "The previous native ad failed to load. Attempting to" +
" load another.");
loadNativeAd(adLoadCount + 1);
}
}).build();
// Load the Native Express ad.
adLoader.loadAd(new AdRequest.Builder().addTestDevice("9F50A23B86C21B90330202FAECE3C331").build());
}
}
and here's my adapter class,
public class WallpaperAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private int height, fragment_id;
private String uId;
private Animation fadeout, fadein;
private DatabaseReference favCheckRef;
private final String CATEGORY = "Category";
private ArrayList<Object> modelList;
private boolean showLikeBtn;
public WallpaperAdapter(Context context, ArrayList<Object> modelList, String uId, boolean showLikeBtn, int fragment_id) {
this.context = context;
this.modelList = modelList;
this.uId = uId;
this.showLikeBtn = showLikeBtn;
height = context.getResources().getDisplayMetrics().heightPixels;
fadeout = AnimationUtils.loadAnimation(context, R.anim.anim_fade_out);
fadein = AnimationUtils.loadAnimation(context, R.anim.anim_fade_in);
favCheckRef = FirebaseDatabase.getInstance().getReference().child(WALL).child(USER)
.child(uId).child(FAVOURITES).getRef();
this.fragment_id = fragment_id;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case NATIVE_CONTENT_AD_VIEW_TYPE:
View nativeContentLayoutView = LayoutInflater.from(
parent.getContext()).inflate(R.layout.ad_content,
parent, false);
return new NativeContentAdViewHolder(nativeContentLayoutView);
case MENU_ITEM_VIEW_TYPE:
// Fall through.
default:
View dataView = LayoutInflater.from(context).inflate(R.layout.single_wallpaper_unit, parent, false);
return new ViewHolder(dataView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
Util.dismissDialog();
switch (viewType) {
case NATIVE_CONTENT_AD_VIEW_TYPE:
NativeContentAd contentAd = (NativeContentAd) modelList.get(position);
populateAdView(contentAd, (NativeContentAdView) holder.itemView);
break;
case MENU_ITEM_VIEW_TYPE:
// fall through
default:
final ViewHolder wallHolder = (ViewHolder) holder;
WallpaperModel model = (WallpaperModel) modelList.get(position);
wallHolder.wallpaper.getLayoutParams().height = (int) (height / 2.5);
wallHolder.name.setText(model.getName());
favCheck(wallHolder, model);
Glide.with(wallHolder.wallpaper.getContext())
.load(model.getThumbnail())
.into(wallHolder.wallpaper);
break;
}
}
#Override
public int getItemViewType(int position) {
Object recyclerViewItem = modelList.get(position);
if (recyclerViewItem instanceof NativeContentAd) {
return NATIVE_CONTENT_AD_VIEW_TYPE;
}
return MENU_ITEM_VIEW_TYPE;
}
#Override
public int getItemCount() {
return modelList.size();
}
private void populateAdView(NativeContentAd ad,NativeContentAdView adView){
((TextView) adView.getHeadlineView()).setText(ad.getHeadline());
List<NativeAd.Image> images = ad.getImages();
if (images.size() > 0) {
((ImageView) adView.getImageView()).setImageDrawable(images.get(0).getDrawable());
}
adView.setNativeAd(ad);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
ImageView wallpaper, favouriteIcon;
private ViewHolder(View itemView) {
super(itemView);
wallpaper = itemView.findViewById(R.id.wallpaper);
name = itemView.findViewById(R.id.name);
favouriteIcon = itemView.findViewById(R.id.favouriteIcon);
}
}
public class NativeContentAdViewHolder extends RecyclerView.ViewHolder {
NativeContentAdViewHolder(View view) {
super(view);
NativeContentAdView adView = (NativeContentAdView) view;
adView.setHeadlineView(adView.findViewById(R.id.contentad_headline));
adView.setImageView(adView.findViewById(R.id.contentad_image));
}
}
}
You are loading native express, not banner.
The problem is the ads have images, just like a normal viewholder, you have to handel the caching of the images, I see you already use glide...
Also, it's not a good idea showing your ad ID.
Last thing, NONE of this matters because native express ads are deprecated and will anyway not work.
Another option is to use Native Ads Advance, but unless you have a few million downloads you will not be able to use it - look here:
Note: Native Ads Advanced is currently released to a limited set of publishers. If you're interested in participating, reach out to your account manager to discuss the possibility.
What I would suggest is using some ad provider like Appodeal which supports native ads.

Categories

Resources