How to get The current Item position Of FirebaseRecyclerAdpter
madapter = new FirebaseRecyclerAdapter<user, contact.UserViewHolder>(user.class, R.layout.activity_dialogs_list, contact.UserViewHolder.class, muserref) {
#Override
protected void populateViewHolder(final UserViewHolder viewHolder, user model, final int position) {
final String ais = model.getName();
viewHolder.setName(model.getName());
final String b = model.getQuery();
(final UserViewHolder viewHolder, user model, ---->final int position<------)
how to use that int position to find the current position.
I'm not sure what is your concrete problem, but I suggest You t use
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html
It is more flexible if you extend this class, and create your own adapter.
In this case you will have a dataset, which can be easily modified.
Also, the accessing of data is simpler.
Actually that position in the populateViewHolder is the current position of the view.
Easiest way is to create an integer value position in the ViewHolder class and assign the value to it like this
madapter = new FirebaseRecyclerAdapter<user, contact.UserViewHolder>(user.class, R.layout.activity_dialogs_list, contact.UserViewHolder.class, muserref) {
#Override
protected void populateViewHolder(final UserViewHolder viewHolder, user model, final int position) {
final String ais = model.getName();
viewHolder.setName(model.getName());
viewHolder.setPosition(position);
final String b = model.getQuery();
And you can use the position by viewHolder.getPosition();
Related
Hello so I have a function in an app where you will add a data from the adapter if the quantity is non-zero and it will be saved to the firebase realtime database. What i wanna do is if the other item in adapter is non-zero it will add a child to the database but instead firebase is just replacing the item instead of adding a new child what should i do?
here is the code
public class UsualFragRViewAdapter extends RecyclerView.Adapter <UsualFragRViewAdapter.ViewHolder> {
private List<FragmentsUsualModels> items;
private Context context;
public UsualFragRViewAdapter( Context context,List<FragmentsUsualModels> items ) {
this.context = context;
this.items = items;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_usual_array, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
final FragmentsUsualModels arrayitems = items.get(position);
holder.itemName.setText(arrayitems.getItemName());
holder.price.setText(String.valueOf("$ " +arrayitems.getPrice()));
holder.quantity.setNumber(arrayitems.getQuantity());
holder.card.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
holder.quantity.setOnValueChangeListener(new ElegantNumberButton.OnValueChangeListener() { //all items are located in its positions
#Override
public void onValueChange(ElegantNumberButton view, int oldValue, int newValue) { //Need to pass all non-zero items as chatview
arrayitems.setQuantity(String.valueOf(newValue));
if (newValue !=0){
String datavalue = holder.itemName.getText().toString();
String dataprice = holder.price.getText().toString();
String dataquantity = holder.quantity.getNumber().toString();
DatabaseReference data = FirebaseDatabase.getInstance().getReference("itemdata");
data.child("dataname").setValue(datavalue);
data.child("dataprice").setValue(dataprice);
data.child("dataquantity").setValue(dataquantity);
Log.d(TAG, "the new value of this data is: " +dataquantity);
Log.d(TAG, "the itemname of this position is: "+datavalue);
Log.d(TAG, "the price of this item in this position is: " +dataprice);
}
Log.d(TAG, "user changed the quantity in this position to " +arrayitems);
}
});
}
#Override
public int getItemCount() {
return items.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
CardView card;
ImageView image;
TextView itemName;
TextView price;
ElegantNumberButton quantity;
Button donebtn;
public ViewHolder(#NonNull View itemView) {
super(itemView);
card = itemView.findViewById(R.id.ucard);
image = itemView.findViewById(R.id.uimage);
itemName = itemView.findViewById(R.id.uitemName);
price = itemView.findViewById(R.id.uprice);
quantity = itemView.findViewById(R.id.uquantity);
donebtn = itemView.findViewById(R.id.udonebtn);
}
}
}
If you want to generate a new child node under a location, call push() on that DatabaseReference. So to create a new child node under itemdata:
DatabaseReference data = FirebaseDatabase.getInstance().getReference("itemdata");
DatabaseReference newData = data.push();
Now you can write the data to this new location as:
newData.child("dataname").setValue(datavalue);
newData.child("dataprice").setValue(dataprice);
newData.child("dataquantity").setValue(dataquantity);
One additional change to consider is the reducing the number of writes. Your current code does a separate setValue() call for each property. This works, but it means that any listeners will get called three times, once for each property.
While this may be what you want, it is quite common to want these writes to appear as one operation. If that is the case, you can perform a single setValue() with:
Map<String,Object> values = new HashMap<>();
values.put("dataname", datavalue);
values.put("dataprice", dataprice);
values.put("dataquantity", dataquantity);
newData.setValue(values);
The end result will be exactly the same as before, but now with a single write operation.
You should use push() to create unique id for database item
dataBase.child(/*CHILD*/).push().setValue(dataValue);
I am new in Android Development and working on a project where I need to call an API after every one second, in that API there is field "Amount"(dBID) which keeps on changing, so I need to update the latest Amount (dBID) in recyclerview.
In order to do so, I have called this API in a service after every interval of one second.
The data is Showing Properly no Issue.
But for Now I need to perform some action on the Old Amount and New Amount.
Action Required : I need to compare the old value (dBID) with the New Value (dBID).
If the New Value is greater then I need to change the Text Color of Amount (dBID) to BLUE.
If the New Value is smaller then I need to change the Text Color of Amount (dBID) to RED.
Tried to achieve this by storing the old data in a Variable and then Comparing it to the new Value.
Issue : This logic is working fine until there are 5 or less Items in recyclerview as soon as the sixth item is added the same logic does not work.
Help me if anyone knows how I can achieve this.
For Example you can refer an App Vertexfx : Quotes Tab.
Below is the Code which I Tried.
Adapter class of the RecyclerView:
public class QuoteAdapter extends RecyclerView.Adapter <QuoteAdapter.MyViewHolder>{
Context context;
List<QuoteData> data;
public QuoteAdapter(Context context,List<QuoteData> data)
{
this.data = data;
this.context = context;
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView time,symbol,sellmax,selllow,buymax,buylow,buy,sell,spread,lowtext,hightext;
LinearLayout layout,layoutbid,layoutask;
float currentbid,lastbid,currentask,lastask;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
time = itemView.findViewById(R.id.TVTime);
symbol = itemView.findViewById(R.id.TVSymbol);
sellmax = itemView.findViewById(R.id.TVSELLMAX);
selllow = itemView.findViewById(R.id.TVSELLLOW);
buymax = itemView.findViewById(R.id.TVBUYMAX);
buylow = itemView.findViewById(R.id.TVBUYHIGH);
buy = itemView.findViewById(R.id.TVBUY);
sell = itemView.findViewById(R.id.TVSELL);
spread = itemView.findViewById(R.id.TVSpread1);
lowtext = itemView.findViewById(R.id.low);
hightext = itemView.findViewById(R.id.high);
layout = itemView.findViewById(R.id.layout);
layoutbid = itemView.findViewById(R.id.LLBid);
layoutask = itemView.findViewById(R.id.LLAsk);
currentbid = 0;
lastbid = 0;
currentask = 0;
lastask = 0;
}
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.quotelist,viewGroup,false);
return new MyViewHolder(view);
}
#SuppressLint("ResourceAsColor")
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, final int i) {
final QuoteData data1 = data.get(i);
myViewHolder.time.setText(data1.dLut);
myViewHolder.symbol.setText(data1.dSymbol);
myViewHolder.sellmax.setText(data1.dBid); //Bid
myViewHolder.selllow.setText(data1.dLow);
myViewHolder.buymax.setText(data1.dAsk); //ask
myViewHolder.buylow.setText(data1.dHigh);
myViewHolder.currentbid = Float.parseFloat((data1.dBid));
myViewHolder.currentask = Float.parseFloat((data1.dAsk));
if (myViewHolder.currentbid > myViewHolder.lastbid)
{
myViewHolder.sellmax.setTextColor(Color.BLUE);
}
if (myViewHolder.currentbid < myViewHolder.lastbid)
{
myViewHolder.sellmax.setTextColor(Color.RED);
}
myViewHolder.lastbid = myViewHolder.currentbid;
myViewHolder.lastask = myViewHolder.currentask;
}
});
}
I suggest you take a look at those classes from the Android SDK:
DiffUtil
AsyncListDiffer
ItemAnimator
DiffUtil
DiffUtil is designed to compare existing and new recycler view items and fires appropriate events. You need to pass a callback that can tell if two items are the same and if their content has changed.
AsyncListDiffer
It wraps the DiffUtil and executes it's logic asynchronously, giving better performance.
ItemAnimator
The ItemAnimator for a given RecyclerView is called by default when change events are fired on it's items. You can provide an implementation of the animateChange method to change your color accordingly.
For Future reference I have resolved the above mentioned issue using the below code.
Defined two ArrayList of String in Adapter
public class QuoteAdapter extends RecyclerView.Adapter <QuoteAdapter.MyViewHolder>{
Context context;
List<QuoteData> data;
List<String> olddatabid = new ArrayList<String>();
List<String> newdatabid = new ArrayList<String>();
List<String> olddataask = new ArrayList<String>();
List<String> newdataask = new ArrayList<String>();
class MyViewHolder extends RecyclerView.ViewHolder{
TextView time,symbol,sellmax,selllow,buymax,buylow,buy,sell,spread,lowtext,hightext;
LinearLayout layout,layoutbid,layoutask;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
time = itemView.findViewById(R.id.TVTime);
symbol = itemView.findViewById(R.id.TVSymbol);
sellmax = itemView.findViewById(R.id.TVSELLMAX);
selllow = itemView.findViewById(R.id.TVSELLLOW);
buymax = itemView.findViewById(R.id.TVBUYMAX);
buylow = itemView.findViewById(R.id.TVBUYHIGH);
buy = itemView.findViewById(R.id.TVBUY);
sell = itemView.findViewById(R.id.TVSELL);
spread = itemView.findViewById(R.id.TVSpread1);
lowtext = itemView.findViewById(R.id.low);
hightext = itemView.findViewById(R.id.high);
layout = itemView.findViewById(R.id.layout);
layoutbid = itemView.findViewById(R.id.LLBid);
layoutask = itemView.findViewById(R.id.LLAsk);
}
}
public QuoteAdapter(Context context,List<QuoteData> data)
{
this.data = data;
this.context = context;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.quotelist,viewGroup,false);
return new MyViewHolder(view);
}
#SuppressLint("ResourceAsColor")
#Override
public void onBindViewHolder(#NonNull final MyViewHolder myViewHolder, final int i) {
final QuoteData data1 = data.get(i);
myViewHolder.time.setText(data1.dLut);
myViewHolder.symbol.setText(data1.dSymbol);
myViewHolder.sellmax.setText(data1.dBid); //Bid
myViewHolder.selllow.setText(data1.dLow);
myViewHolder.buymax.setText(data1.dAsk); //ask
myViewHolder.buylow.setText(data1.dHigh);
if (newdatabid.size()< data.size())
{
newdatabid.add(data1.dBid); //Insert Value in array for the first time
}
if (olddatabid.size()< data.size())
{
olddatabid.add(data1.dBid); //Insert Value in array for the first time
}
if (newdataask.size()< data.size())
{
newdataask.add(data1.dAsk); //Insert Value in array for the first time
}
if (olddataask.size()< data.size()) //Insert Value in array for the first time
{
olddataask.add(data1.dAsk);
}
newdatabid.set(i,data1.dBid); //Store Value in array
newdataask.set(i,data1.dAsk); //Store Value in array
//Compare and perform Logic
if (Float.valueOf(newdatabid.get(i)) > Float.valueOf(olddatabid.get(i)))
{
myViewHolder.sellmax.setTextColor(Color.BLUE);
}
if (Float.valueOf(newdatabid.get(i)) < Float.valueOf(olddatabid.get(i)))
{
myViewHolder.sellmax.setTextColor(Color.RED);
}
if (Float.valueOf(newdataask.get(i)) > Float.valueOf(olddataask.get(i)))
{
myViewHolder.buymax.setTextColor(Color.BLUE);
}
if (Float.valueOf(newdataask.get(i)) < Float.valueOf(olddataask.get(i)))
{
myViewHolder.buymax.setTextColor(Color.RED);
}
olddatabid.set(i,newdatabid.get(i));
olddataask.set(i,newdataask.get(i));
}
});
}
}
#Override
public int getItemCount() {
return data.size();
}
}
I wish to delete an object from Firebase on Swipe left. Everything works fine now with the swipe and it it removed from the view, but it stays in the database.
I've added the following to my onCreate:
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
Toast.makeText(ListBox.this, "Item removed", Toast.LENGTH_SHORT).show();
//Remove swiped item from list and notify the RecyclerView
}
};
and this is how i populate my ViewHolder.
#Override
protected void populateViewHolder(final BoxViewHolder viewHolder, final Box model, int position) {
viewHolder.setTitle(model.getTitle());
final String boxUniqueKey = model.getBoxkey();
final DatabaseReference postRef = getRef(position);
final String postKey = postRef.getKey();
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Launch BoxItem view
final Intent intent = new Intent(ListBox.this, AddBoxItem.class);
String boxkey = model.getBoxkey();
String boxName = model.getTitle();
startActivity(intent);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(allBoxes);
}
});
}
but how (and where) do I get the position of the item, and how can I send the remove query to the Firebase Database?
I have coded something very similar to what you are trying to achieve. This is one way you could achieve it.
First, extend the ItemTouchHelper.SimpleCallback class to make your own custom class.
public class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback {
private RecyclerAdapter adapter; // this will be your recycler adapter
private DatabaseReference root = FirebaseDatabase.getInstance().getReference();
/**
*
Make sure you pass in your RecyclerAdapter to this class
*/
public CallBack(int dragDirs, int swipeDirs, RecyclerAdapter adapter) {
super(dragDirs, swipeDirs);
this.adapter = adapter;
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition(); // this is how you can get the position
Object object = adapter.getObject(position); // You will have your own class ofcourse.
// then you can delete the object
root.child("Object").child(object.getId()).setValue(null);// setting the value to null will just delete it from the database.
}
Calling viewHolder.getAdapterPosition() returns the position of the view in the adapter. You can use this position to get the Object from the ArrayList contained in your recycler adapter.
In my adapter, I have created a getObject method. This just returns the object from the ArrayList that my adapter has. Once I have the object, I can call the associated Firebase Realtime Database method and delete the object. In my Object class, I have stored the unique key within the object so I can easily delete it. I get the unique id by calling getId(). I pass this to the associated Firebase Realtime Database method and set the value to null which deletes it.
After doing this you can add it to your recycler view like this.
ItemTouchHelper.SimpleCallback swipeToDeleteCallback = new
SwipeToDeleteCallback(0, ItemTouchHelper.RIGHT, choreRecyclerAdapter, getContext()); // Making the SimpleCallback
ItemTouchHelper touchHelper = new ItemTouchHelper(swipeToDeleteCallback);
touchHelper.attachToRecyclerView(recyclerView); // then attach it to your recycler view
First, you make a simple callback and make sure you instantiate the custom class that you extended. Be sure to pass your recycler adapter.
Notice I only support right swipe by passing ItemTouchHelper.Right. You can support left or pass in both left and right.
Then create an ItemTouchHelper object and pass it your simple callback.
Lastly, you attach your touch helper to your recycler view and that's all.
Here's my database:
Database:{
X:{
JK-KDUKSIDKSIIJDSL1:{
text:"hello",
name:"Donald J. Drunk"
}
JK-KDadDFDDIJDSL1:{
name:"Killery Hlinton"
}
}
}
And I want to filter my FirebaseRecyclerAdapter such that only add to my RecyclerView data that contains the key text. How is this possible? How can I add it? Current code:
mAdapter = new FirebaseRecyclerAdapter<Campaign, CampaignHolder>(Campaign.class, R.layout.recyclerview_template, CampaignHolder.class, ref) {
#Override
public void populateViewHolder(final CampaignHolder viewHolder, final Campaign campaign, final int position) {
findViewById(R.id.progress_bar).setVisibility(View.INVISIBLE);
MainActivity.this.holder = viewHolder;
viewHolder.setTitle(campaign.title);
//... Other "set" methods
}
}
You could try overriding the onBindViewHolder method in your FirebaseRecyclerAdapter. Something like this:
mAdapter = new FirebaseRecyclerAdapter<Campaign, CampaignHolder>(Campaign.class, R.layout.recyclerview_template, CampaignHolder.class, ref) {
#Override
public void onBindViewHolder(CampaignHolder viewHolder, int position) {
Campaign model = getItem(position);
if(model.getText() != null){
populateViewHolder(viewHolder, model, position);
}
}
#Override
public void populateViewHolder(final CampaignHolder viewHolder, final Campaign campaign, final int position) {
findViewById(R.id.progress_bar).setVisibility(View.INVISIBLE);
MainActivity.this.holder = viewHolder;
viewHolder.setTitle(campaign.title);
//... Other "set" methods
}
};
With this approach you would still pull all data at the query location but entries without a text attribute just wouldn't be displayed. If that is unsatisfactory and you want to minimize the amount of data you download per query then the only other option I see is closer to what is mentioned in the comments above - meaning you would need to create a separate location that only stores those entries which have a text value.
Is there a way to dynamically insert a new kind of viewType into a RecyclerView.Adapter, let's say I have the following:
//View Types
private static final int HEADER = 0;
private static final int OTHER_ITEM = 1;
And the following getItemViewType method:
#Override
public int getItemViewType(int position) {
if (position == 0)
return HEADER;
else
return OTHER_ITEM;
}
The problem now is that I need to dynamically add a new kind of view type at a random specific place in the adapter. How would I go about accomplishing this?
So there would be another ViewHolder let's call it:
public class DynamicViewholder extends RecyclerView.ViewHolder {
....
}
I would like to insert this randomly at random places in the adapter, how should I do this?