So I have a app where I am displaying the products list from the database using a Recycler View.
There is delete button beside each item which is working fine.
And there is a scan item button which opens a BARCODE SCANNER which on succesfull scanning adds the new product to the database and goes back to the Recycler View display is supposed to refresh the view and display the new Item.
but I am having problem with refreshing the recycler view on adding a new Product.
there is also a delete product function which works perfectly so I tried to do the add item method the same way, but the recycler view doesn't refresh.
UserPage activity
public class UserPage extends AppCompatActivity implements ProductAdaptar.clickedItem {
Toolbar toolbar;
RecyclerView recyclerView;
String rfidNo;
public static String barcode;
Button scanItem;
Button payBill;
TextView total;
ProductAdaptar productAdaptar;
Call<List<UserLoginResp>> productList;
List<UserLoginResp> productListsItems = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_page);
toolbar=findViewById(R.id.toolbar);
recyclerView=findViewById(R.id.recyclerview);
scanItem = findViewById(R.id.scanItem);
payBill = findViewById(R.id.payBill);
total = findViewById(R.id.total);
scanItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(),ScannerView.class).putExtra("rfid",rfidNo));
}
});
payBill.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkout();
}
});
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
productAdaptar = new ProductAdaptar(this::clickedItem, this);
Intent intent =getIntent();
if(intent.getExtras()!=null){
rfidNo= intent.getStringExtra("rfid");
}
getAllProducts(rfidNo);
}
public void getAllProducts(String rfidno){
LinearLayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
productAdaptar = new ProductAdaptar(this::clickedItem,this);
productList= ApiClient.getUserPageService().getCartItems(rfidno);
productList.enqueue(new Callback<List<UserLoginResp>>() {
#Override
public void onResponse(Call<List<UserLoginResp>> call, Response<List<UserLoginResp>> response) {
if (response.isSuccessful()) {
productListsItems = response.body();
productAdaptar.setData(productListsItems);
RecyclerView recyclerView = findViewById(R.id.recyclerview);
recyclerView.setAdapter(productAdaptar);
getTotal();
}
}
#Override
public void onFailure(Call<List<UserLoginResp>> call, Throwable t) {
Log.e("listfailed",t.getLocalizedMessage());
}
});
}
public void getTotal(){
Call<getBill> bill = ApiClient.getUserPageService().getBill(rfidNo);
bill.enqueue(new Callback<getBill>() {
#Override
public void onResponse(Call<getBill> call, Response<getBill> response) {
if(response.isSuccessful()){
getBill getBill = response.body();
String bill = String.valueOf(getBill.getBill());
total.setText(bill);
}
}
#Override
public void onFailure(Call<getBill> call, Throwable t) {
Log.e("bill error",""+t);
}
});
}
public void checkout(){
Call<String> payment= APIClientString.getUserPageService().checkout(rfidNo);
payment.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()){
getAllProducts(rfidNo);
Toast.makeText(UserPage.this, "Payment Successful", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e("paymentfail",""+t);
}
});
}
#Override
public void clickedItem(UserLoginResp userLoginResp) {
Log.e("clicked prodcut", userLoginResp.toString());
}
}
ScannerView Class
enter #Override
public void handleResult(Result rawResult) {
barcode = rawResult.getText();
if(addItem(barcode,rfidNo)) {
userPage.getAllProducts(rfidNo);
}
onBackPressed();
}
public boolean addItem(String barcode,String rfidNo){
final boolean[] res = {false};
Call<String> resp = APIClientString.getUserPageService().addProduct(barcode,rfidNo);
resp.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()){
Toast.makeText(ScannerView.this, response.body().toString(), Toast.LENGTH_SHORT).show();
res[0] =true;
}
}
This is the scanner class which is suppose to call the call the getAllproducts function from the UserPage Activity to refresh the view. It shows no error but the recycler view doesn't get updated.
This is the Adapter Class
public class ProductAdaptar extends RecyclerView.Adapter<ProductAdaptar.ProductAdaptarVH> {
private List<UserLoginResp> productListItems;
private UserPage context;
private clickedItem clickedItem;
public ProductAdaptar(clickedItem clickedItem, UserPage activity) {
this.clickedItem = clickedItem;
this.context= activity;
}
public void setData(List<UserLoginResp> productListItems) {
this.productListItems = productListItems;
notifyDataSetChanged();
}
#NonNull
#Override
public ProductAdaptarVH onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ProductAdaptar.ProductAdaptarVH(LayoutInflater.
from(context).inflate(R.layout.row_products,parent,false));
}
#Override
public void onBindViewHolder(#NonNull ProductAdaptarVH holder, int position) {
UserLoginResp userLoginResp = productListItems.get(position);
String pName = userLoginResp.getProductName();
String pQuan = userLoginResp.getQuantity();
String pPrice = userLoginResp.getProductPrice();
String pBarcode = userLoginResp.getProductID();
String userID = userLoginResp.getUserID();
holder.pName.setText(pName);
holder.pQuan.setText(pQuan);
holder.pPrice.setText(pPrice);
holder.delProdcut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
delProduct(userID,pBarcode);
}
});
holder.moreDetails.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
public interface clickedItem{
public void clickedItem(UserLoginResp userLoginResp);
}
public void delProduct(String userID, String pBarcode){
Call<String> res = APIClientString.getUserPageService().deleteProduct(pBarcode,userID);
res.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()){
Toast.makeText(context, response.body().toString(), Toast.LENGTH_SHORT).show();
context.getAllProducts(userID);
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e("deletefailed",""+t);
}
});
}
#Override
public int getItemCount() {
return productListItems.size();
}
public static class ProductAdaptarVH extends RecyclerView.ViewHolder {
TextView pName;
TextView pQuan;
TextView pPrice;
Button delProdcut;
Button moreDetails;
public ProductAdaptarVH(#NonNull View itemView) {
super(itemView);
pName=itemView.findViewById(R.id.pName);
pQuan=itemView.findViewById(R.id.pQuantity);
pPrice=itemView.findViewById(R.id.pPrice);
delProdcut=itemView.findViewById(R.id.delProduct);
moreDetails=itemView.findViewById(R.id.moreDetails);
}
}
}
In this Product Apdapter there is a delete product item function
holder.delProdcut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
delProduct(userID,pBarcode);
}
});
public void delProduct(String userID, String pBarcode){
Call<String> res = APIClientString.getUserPageService().deleteProduct(pBarcode,userID);
res.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()){
Toast.makeText(context, response.body().toString(), Toast.LENGTH_SHORT).show();
context.getAllProducts(userID);
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e("deletefailed",""+t);
}
});
}
Which also calls the getProduts function from UserPage activity and it works perfectly fine but the AddItem function doesn't refresh the view.
The Retrofit APIs are working completly fine too, the problem is only with refreshing the recycler view display on Item Add.
I am new to android coding so I can't seem to understand how to do it.
As you are refreshing your adapter using getAllProducts() method but it is being called in onCreate(). Now whenever you start a ScannerView activity, UserPage activity gets paused and then started (not created) when ScannerView activity finishes. So, you should call getAllProducts() in onStart() method like this:
#Override
protected void onStart() {
super.onStart();
Intent intent = getIntent();
if (intent.getExtras() != null) {
rfidNo = intent.getStringExtra("rfid");
}
getAllProducts(rfidNo);
}
Related
does anyone here encountered when you are updating a data it duplicates the existing data visually only but when I will back and go to the activity again it shows the real data.
Data 1 and Data 2, when I delete Data 2, it will show Data 1 Data2 and Data 1. However like I said, it is just visual had to go back and go to the activity again to show the current data which is Data 1 only since Data 2 has been deleted. I have tried searching but none of them are related to my problem and I genuinely do not know if this is from the database or the card or in the recyclerview. Any help will be much appreciated.
MainActivity
public class AdminReqFormsActivity extends AppCompatActivity {
RecyclerView adminreqform_recycler;
ImageView adminreqfromfield_backbtn;
DatabaseReference databaseReference;
ArrayList<ResearchReqForm> reqFormArrayList;
AdminRequestFormAdapter adminRequestFormAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin_req_forms);
adminreqform_recycler = findViewById(R.id.adminreqform_recycler);
adminreqfromfield_backbtn = findViewById(R.id.adminreqfromfield_backbtn);
databaseReference = FirebaseDatabase.getInstance().getReference("ResearchRequest");
adminreqform_recycler.setLayoutManager(new LinearLayoutManager(this));
reqFormArrayList = new ArrayList<ResearchReqForm>();
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
ResearchReqForm researchReqForm = dataSnapshot.getValue(ResearchReqForm.class);
reqFormArrayList.add(researchReqForm);
}
adminRequestFormAdapter = new AdminRequestFormAdapter(AdminReqFormsActivity.this, reqFormArrayList);
adminreqform_recycler.setAdapter(adminRequestFormAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(AdminReqFormsActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
adminreqfromfield_backbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), WelcomeAdminActivity.class));
}
});
}
}
Model
public class ResearchReqForm {
String studentName;
String requestedtitle;
String requestedtags;
String requestMessage;
String requestid;
String requestStatus;
public ResearchReqForm() {
}
public ResearchReqForm(String studentName, String requestedtitle, String requestedtags, String requestMessage, String requestid, String requestStatus) {
this.studentName = studentName;
this.requestedtitle = requestedtitle;
this.requestedtags = requestedtags;
this.requestMessage = requestMessage;
this.requestid = requestid;
this.requestStatus = requestStatus;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getRequestedtitle() {
return requestedtitle;
}
public void setRequestedtitle(String requestedtitle) {
this.requestedtitle = requestedtitle;
}
public String getRequestedtags() {
return requestedtags;
}
public void setRequestedtags(String requestedtags) {
this.requestedtags = requestedtags;
}
public String getRequestMessage() {
return requestMessage;
}
public void setRequestMessage(String requestMessage) {
this.requestMessage = requestMessage;
}
public String getRequestid() {
return requestid;
}
public void setRequestid(String requestid) {
this.requestid = requestid;
}
public String getRequestStatus() {
return requestStatus;
}
public void setRequestStatus(String requestStatus) {
this.requestStatus = requestStatus;
}
}
Adapter
public class AdminRequestFormAdapter extends RecyclerView.Adapter<AdminRequestFormAdapter.AdminRequestFormViewHolder> {
Context context;
ArrayList<ResearchReqForm> requestFormArrayList;
public AdminRequestFormAdapter(Context c, ArrayList<ResearchReqForm> reqFormsList){
context = c;
requestFormArrayList = reqFormsList;
}
#NonNull
#Override
public AdminRequestFormViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new AdminRequestFormAdapter.AdminRequestFormViewHolder(LayoutInflater.from(context).inflate(R.layout.admin_request_list,parent,false));
}
#Override
public void onBindViewHolder(#NonNull AdminRequestFormViewHolder holder, final int position) {
holder.adminsudentname_reqcv.setText(requestFormArrayList.get(position).getStudentName());
holder.adminrelatedtopic_requestcv.setText(requestFormArrayList.get(position).getRequestedtitle());
holder.admintopictags_requestcv.setText(requestFormArrayList.get(position).getRequestedtags());
holder.adminbriefmessage_reqeuestcv.setText(requestFormArrayList.get(position).getRequestMessage());
holder.deleteresearch_request.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("Delete Request Research?");
alert.setMessage("Are you sure you want to delete?");
alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("ResearchRequest");
final String uniqueKey = requestFormArrayList.get(position).getRequestid();
databaseReference.child(uniqueKey).removeValue();
Toast.makeText(context, "Student's Request has been deleted.", Toast.LENGTH_SHORT).show();
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(context, "Form Closed.", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
alert.show();
}
});
holder.acceptresearch_request.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "Test Toast For Accept", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return requestFormArrayList.size();
}
class AdminRequestFormViewHolder extends RecyclerView.ViewHolder{
TextView adminsudentname_reqcv, adminrelatedtopic_requestcv, admintopictags_requestcv, adminbriefmessage_reqeuestcv;
Button deleteresearch_request, acceptresearch_request;
public AdminRequestFormViewHolder(#NonNull View itemView) {
super(itemView);
adminsudentname_reqcv = itemView.findViewById(R.id.adminsudentname_reqcv);
adminrelatedtopic_requestcv =itemView.findViewById(R.id.adminrelatedtopic_requestcv);
admintopictags_requestcv = itemView.findViewById(R.id.admintopictags_requestcv);
adminbriefmessage_reqeuestcv = itemView.findViewById(R.id.adminbriefmessage_reqeuestcv);
deleteresearch_request = itemView.findViewById(R.id.deleteresearch_request);
acceptresearch_request = itemView.findViewById(R.id.acceptresearch_request);
}
}
}
Yes, this is actually quite common and comes from a misunderstanding of how Firebase snapshots work.
Whenever your onDataChange is called it gets a full snapshot of all the data at databaseReference. So even if there's only one change since you rendered the data, you get called with a full snapshot of all data at databaseReference including the change. And since you add all data in snapshot to reqFormArrayList, you end up duplicating it each time onDataChange gets called.
The simplest solution is to clear reqFormArrayList inside onDataChange:
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
reqFormArrayList.clear(); // this is the new line
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
ResearchReqForm researchReqForm = dataSnapshot.getValue(ResearchReqForm.class);
reqFormArrayList.add(researchReqForm);
}
adminRequestFormAdapter = new AdminRequestFormAdapter(AdminReqFormsActivity.this, reqFormArrayList);
adminreqform_recycler.setAdapter(adminRequestFormAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(AdminReqFormsActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
})
if the page is loaded, the button is active, if not, how can I do passive control?
What I want to do is, if the Viewpager Page is loaded, the button is active, if not, the Button is Passive. But I couldn't do any kind.
Is there anyone who can help?
If viewpager2 is installed Button enabled, if viewpager2 is not installed button false;
List<Movie> movieList = new ArrayList<>();
private ImageButton btn_down, btn_fav;
private Button btn_setter;
private DatabaseReference movies;
private IFirebaseLoadDone iFirebaseLoadDone;
public CartoonFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_cartoon, container, false);
movies = FirebaseDatabase.getInstance().getReference("Sports");
movies.keepSynced(true);
iFirebaseLoadDone = this;
loadMovie();
viewPager2 = view.findViewById(R.id.viewPager2_);
btn_down = view.findViewById(R.id.btn_down);
btn_setter = view.findViewById(R.id.btn_setter);
btn_fav = view.findViewById(R.id.btn_fav);
btn_down.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SaveToGallery();
}
});
btn_setter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
btn_fav.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
return view;
}
private void loadMovie() {
movies.addValueEventListener(this);
}
#Override
public void onFirebaseLoadSuccess(List<Movie> movieList) {
viewPagerAdapter = new ViewPagerAdapter(getContext(), movieList, viewPager2);
viewPager2.setAdapter(viewPagerAdapter);
}
#Override
public void onFirebasLoadFailed(String message) {
}
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot moviesSnapShot : dataSnapshot.getChildren())
movieList.add(moviesSnapShot.getValue(Movie.class));
Collections.reverse(movieList);
iFirebaseLoadDone.onFirebaseLoadSuccess(movieList);
viewPagerAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
iFirebaseLoadDone.onFirebasLoadFailed(databaseError.getMessage());
}
#Override
public void onDestroy() {
movies.removeEventListener(this);
super.onDestroy();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onStop() {
movies.removeEventListener(this);
super.onStop();
}
}
Replace your methods with mine.
private void loadMovie() {
movies.addValueEventListener(this);
btn_down.setEnabled(false);
btn_fav.setEnabled(false);
btn_setter.setEnabled(false);
}
Firebase methods
#Override
public void onFirebaseLoadSuccess(List<Movie> movieList) {
viewPagerAdapter = new ViewPagerAdapter(getContext(), movieList, viewPager2);
viewPager2.setAdapter(viewPagerAdapter);
if(movieList!=null && !movieList.isEmpty()){
btn_down.setEnabled(true);
btn_fav.setEnabled(true);
btn_setter.setEnabled(true);
}
}
#Override
public void onFirebasLoadFailed(String message) {
btn_down.setEnabled(false);
btn_fav.setEnabled(false);
btn_setter.setEnabled(false);
}
There was an error loading
private void loadMovie() {
movies.addValueEventListener(this);
btn_down.setEnabled(false);
btn_fav.setEnabled(false);
btn_setter.setEnabled(false);
}
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageButton.setEnabled(boolean)' on a null object reference
at com.example.duvarlar.Fragment.CartoonFragment.loadMovie(CartoonFragment.java:386)
at com.example.duvarlar.Fragment.CartoonFragment.onCreateView(CartoonFragment.java:90)
I want to update the items inside RecyclerView using sending request to API and a timer.
This is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
get_items();
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
synchronized public void run() {
get_items();
}
}, TimeUnit.SECONDS.toMillis(3), TimeUnit.SECONDS.toMillis(3));
}
public void get_items(){
Client client = ServiceGenerator.createService(Client.class,getBaseContext());
final Call<List<Items>> call = Client.getItems("items");
call.enqueue(new Callback<List<Items>>() {
#Override
public void onResponse(Call<List<Items>> call, Response<List<Items>> response) {
List<Items> items = response.body();
ItemsAdapter adapter = new ItemsAdapter(items);
recyclerView = findViewById(R.id.chatrecycler);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(Activity.this, LinearLayoutManager.VERTICAL,true));
}
#Override
public void onFailure(Call<List<Items>> call, Throwable t) {
}
});
}
And every 3 seconds the list updates but it starts from beginning.
What should I do to keep the position of the list during update??
You should not create new RecyclerView object in every api call. Also you are assigning adapter and LayoutManager with yout RecycletView in each call.
You just need to setAdapter with your RecycletView once and then second time just add new data in your adapter list and notify your adapter to refresh.
Please check below code.
private ItemsAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
recyclerView = findViewById(R.id.chatrecycler);
recyclerView.setLayoutManager(new LinearLayoutManager(SingleChat.this, LinearLayoutManager.VERTICAL,true));
get_items();
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
synchronized public void run() {
get_items();
}
}, TimeUnit.SECONDS.toMillis(3), TimeUnit.SECONDS.toMillis(3));
}
public void get_items(){
Client client = ServiceGenerator.createService(Client.class,getBaseContext());
final Call<List<Items>> call = Client.getItems("items");
call.enqueue(new Callback<List<Items>>() {
#Override
public void onResponse(Call<List<Items>> call, Response<List<Items>> response) {
List<Items> items = response.body();
if(adapter == null) {
adapter = new ItemsAdapter(items);
recyclerView.setAdapter(adapter);
} else {
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.addMoreItems(items);
adapter.notifyDatasetChanged();
}
});
}
}
#Override
public void onFailure(Call<List<SingleChatItem>> call, Throwable t) {
}
});
}
Add one method in your ItemsAdapter.java like,
public void addMoreItems(List<Items> items) {
this.items = items;
}
I have not tested this code myself.But it must work.Let me know if it doesn't.
final ItemsAdapter adapter = null;
ArrayList<Items> items = null;
recyclerView = findViewById(R.id.chatrecycler);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(Activity.this, LinearLayoutManager.VERTICAL,true));
call.enqueue(new Callback<List<Items>>() {
#Override
public void onResponse(Call<List<Items>> call, Response<List<Items>> response) {
List<Items> newItems = response.body();
if(adapter == null){
adapter = new ItemsAdapter(items);
items.addAll(newItems);
}else{
int i = 0;
for(Item item : items){
int index = newItems.indexOf(item);
item.stuff = newItems.get(index).stuff;
adapter.notifyItemChanged(i);
i++;
}
}
}
#Override
public void onFailure(Call<List<Items>> call, Throwable t) {
}
});
i have a fragment that contains a recyclerview which needs pagination
so once it reach end of it it will call the API to retrieve a new data and append to the list.
in addition i had just added a swipeRefreshLayout to the view once the user swipe for a refresh it will clear the recyclerview and add the data again
Now the problem is that the adapter is unable to detect end of recyclerview once the swipe to refresh is called
Code Below:
newsSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
generateNews(1);
}
});
adapterNews.setLoadMore(new ToLoadMore() {
#Override
public void LoadMore() {
if (next_offset != 0) {
newsList.add(null);
adapterNews.notifyItemInserted(newsList.size() - 1);
newsApi.GetNews(Constant.ACCESSTOKEN, next_offset).enqueue(new Callback<NewsData>() {
#Override
public void onResponse(Call<NewsData> call, Response<NewsData> response) {
Log.d("PAGINATION", "PAGINATION");
newsList.remove(newsList.size() - 1);
adapterNews.notifyItemRemoved(newsList.size());
newsList.addAll(response.body().getNews());
next_offset = response.body().getNextOffset();
adapterNews.notifyDataSetChanged();
adapterNews.setLoaded();
}
#Override
public void onFailure(Call<NewsData> call, Throwable t) {
}
});
}
}
});
generateNews(1);
return v;
}
the function which generate news is the below
private void generateNews(final int offset) {
newsApi.GetNews(Constant.ACCESSTOKEN, offset).enqueue(new Callback<NewsData>() {
#Override
public void onResponse(Call<NewsData> call, Response<NewsData> response) {
newsList.clear();
newsList.addAll(response.body().getNews());
next_offset = response.body().getNextOffset();
if (newsSwipeRefreshLayout.isRefreshing()) {
newsSwipeRefreshLayout.setRefreshing(false);
}
news_progressbar.setVisibility(View.GONE);
news_progressText.setVisibility(View.GONE);
newsRecyclerView.setVisibility(View.VISIBLE);
adapterNews.notifyDataSetChanged();
}
#Override
public void onFailure(Call<NewsData> call, Throwable t) {
snackbar = Snackbar.make(getView(), "No Internet Connection", Snackbar.LENGTH_INDEFINITE).setAction("Close", new View.OnClickListener() {
#Override
public void onClick(View v) {
snackbar.dismiss();
generateNews(1);
}
});
snackbar.show();
if (newsSwipeRefreshLayout.isRefreshing()) {
newsSwipeRefreshLayout.setRefreshing(false);
}
}
});
}
Basically i followed the accepted answer of this with few changes in my Activity and it worked perfect. My problem is that I wrote the exact same codes for my Fragment. when I open my app, it doesn't show anything. Before I changed my code in my fragment from a custom Adapter to the FirebaseRecyclerAdapter, everything worked fine.
This is my Fragment class
public class HomeFragment extends BaseFragment {
public Button buttonsrch, openFreezer, openRef, openPantry, scrollToFreezer, scrollToRef, scrollToPantry;
public NestedScrollView scrollView;
public RelativeLayout mFreezerLayout,mRefrigeratorLayout, mPantryLayout;
public FloatingActionButton mAddItems;
public DatabaseReference mDatabaseFreezer;
public RecyclerView mFreezerRecyclerView;
public ArrayList<Event> mDataSet;
private FirebaseRecyclerAdapter<Event, ProductHolder> firebaseRecyclerAdapter;
#Override
public int getLayoutResId() {
return R.layout.fragment_home;
}
#Override
public View inOnCreateView(View root, #Nullable ViewGroup container, Bundle savedInstancesState) {
View view = mRoot;
buttonsrch = view.findViewById(R.id.searchButton);
openPantry = view.findViewById(R.id.ShowMorePantry);
openRef = view.findViewById(R.id.ShowMoreRefrigerator);
openFreezer = view.findViewById(R.id.ShowMoreFreezer);
scrollToFreezer = view.findViewById(R.id.bringToFreezer);
scrollToPantry = view.findViewById(R.id.bringToPantry);
scrollToRef = view.findViewById(R.id.bringToRefrigerator);
scrollView = view.findViewById(R.id.scrollViewHomeFragment);
mFreezerLayout = view.findViewById(R.id.FreezerLayout);
mPantryLayout =view.findViewById(R.id.PantryRelativeLayout);
mRefrigeratorLayout = view.findViewById(R.id.RefrigeratorRelativeLayout);
mAddItems = view.findViewById(R.id.addItems_Inventory);
mAddItems.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getActivity(), AddInventoryActivity.class));
}
});
buttonsrch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(getActivity(), Search_Activity.class);
getActivity().startActivity(i);
}
});
openPantry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent h = new Intent(getActivity(), PantryActivity.class);
getActivity().startActivity(h);
}
});
openRef.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent g = new Intent(getActivity(), RefActivity.class);
getActivity().startActivity(g);
}
});
openFreezer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent s = new Intent(getActivity(), FreezerActivity.class);
getActivity().startActivity(s);
}
});
scrollToFreezer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FocusToFreezer();
}
});
scrollToRef.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FocusToRef();
}
});
scrollToPantry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FocusToPantry();
}
});
mDataSet = new ArrayList<>();
mFreezerRecyclerView = view.findViewById(R.id.FreezerRecyclerView);
mFreezerRecyclerView.setHasFixedSize(true);
mFreezerRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mDatabaseFreezer = FirebaseDatabase.getInstance().getReference().child("FreezerItems");
Query query = mDatabaseFreezer;
FirebaseRecyclerOptions<Event> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Event>()
.setQuery(query, Event.class).build();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Event, ProductHolder>(firebaseRecyclerOptions) {
#Override
protected void onBindViewHolder(ProductHolder holder, int position, Event model) {
model = mDataSet.get(position);
holder.mItemName.setText(model.getName());
holder.mItemDate.setText(model.getDate());
final Event finalModel = model;
holder.mDeleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mDatabaseFreezer.child(finalModel.get_id()).removeValue();
}
});
}
#Override
public ProductHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view_row_inventory,parent,false);
return new ProductHolder(view);
}
};
mDatabaseFreezer.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
HashMap<String, String> value = (HashMap<String,String>) dataSnapshot.getValue();
if (value != null) {
String name = value.get("Name");
String date = value.get("Date");
String key = value.get("Key");
mDataSet.add(new Event(name,date,null, key));
Collections.sort(mDataSet, new Comparator<Event>() {
#Override
public int compare(Event event, Event t1) {
if (event.getDate() == null || t1.getDate() == null)
return 0;
return event.getDate().compareTo(t1.getDate());
}
});
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mFreezerRecyclerView.setAdapter(firebaseRecyclerAdapter);
return root;
}
private class ProductHolder extends RecyclerView.ViewHolder{
private TextView mItemName, mItemDate;
private Button mDeleteBtn;
public ProductHolder(View itemView) {
super(itemView);
mItemName = itemView.findViewById(R.id.ItemNameTxtView);
mItemDate = itemView.findViewById(R.id.BestBeoforeTxtView);
mDeleteBtn = itemView.findViewById(R.id.deleteItem);
}
}
#Override
public void onStart() {
super.onStart();
firebaseRecyclerAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
if (firebaseRecyclerAdapter != null){
firebaseRecyclerAdapter.startListening();
}
}
private void FocusToFreezer(){
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.smoothScrollTo(0, mFreezerLayout.getTop());
}
});
}
private void FocusToRef(){
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.smoothScrollTo(0, mRefrigeratorLayout.getTop());
}
});
}
private void FocusToPantry(){
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.smoothScrollTo(0, mPantryLayout.getTop());
}
});
}
}
The only difference I could find is OnStart() and onStop() in activity are protected while on fragments are public
EDIT I found another page with the same problem and apparently FirebaseRecyclerAdapter doesn't work well with Fragments
I finally found an answer
simply remove mFreezerRecyclerView.setHasFixedSize(true);