Gettin the child "sonyTV" in the Firebase Recycler View.
the problem : this child is not a direct child of "Users"
Got the name and the date ,but not "sonyTV"
#Override
protected void onBindViewHolder(#NonNull UsersViewHolder usersViewHolder, int i, #NonNull ALL_USERS all_users) {
usersViewHolder.setName(all_users.getName());
usersViewHolder.setDate(all_users.getDate());
usersViewHolder.setUserSoldItems(all_users.getUserSoldItems());
setUserSoldItems method
public void setUserSoldItems(ALL_USERS.UserSoldItems userSoldItems) {
TextView SonyTvView = mView.findViewById(R.id.showTVsony);
SonyTvView.setText("Sony TV : "+userSoldItems);
}
ALL_USERS class
public class ALL_USERS {
private String name;
private long date;
private UserSoldItems userSoldItems;
public ALL_USERS() {}
public ALL_USERS(String name, long date, UserSoldItems userSoldItems) {
this.name = name;
this.date = date;
this.userSoldItems = userSoldItems;
}
public String getName() { return name; }
public long getDate() { return date; }
public UserSoldItems getUserSoldItems() { return userSoldItems; }
public class UserSoldItems {
private long sonyTV;
public UserSoldItems() {}
public UserSoldItems(long sonyTV) {
this.sonyTV = sonyTV;
}
public long getSonyTV() { return sonyTV; }
}
}
but it gives me null values, although you can check it in my database its not null
This is how i post to child("sonyTV")
users.child(user.getUid()).child("UserSoldItems").child("sonyTV").runTransaction(new Transaction.Handler() {
#NonNull
#Override
public Transaction.Result doTransaction(#NonNull MutableData mutableData) {
Long value = mutableData.getValue(Long.class);
if (value == null) {
mutableData.setValue(0);
}
else {
mutableData.setValue(value + 1);
}
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
}
});
According to your question:
Dear Alex i have one more thing i cant get the child sonyTV in the RecyclerView ,is it beacause its not a direct child of Users node ??!!!
Now seeing what you are trying to achieve, the simplest solution I can think of is to add an extra property of type UserSoldItems in your User class. So your User class should look like this:
public class ALL_USERS {
private String name;
private long date;
private UserSoldItems userSoldItems;
public ALL_USERS() {}
public ALL_USERS(String name, long date, UserSoldItems userSoldItems) {
this.name = name;
this.date = date;
this.userSoldItems = userSoldItems;
}
public String getName() { return name; }
public long getDate() { return date; }
public UserSoldItems getUserSoldItems { return userSoldItems; }
}
And the UserSoldItems should look like this:
public UserSoldItems {
private long sonyTV;
public UserSoldItems() {}
public UserSoldItems(int sonyTV) {
this.sonyTV = sonyTV;
}
public long getSonyTV() { return sonyTV; }
}
Or even simpler:
public UserSoldItems {
public long sonyTV;
}
And please note, the name of the node should be UserSoldItems and not User Sold Items in order to make it work. So it should not contains any spaces. So when adding data, please add it without any space. In the end, just clear the actual data from the database and add fresh one.
So we introduced a new UserSoldItems level in your JSON tree, so you we can ensure that your Java classes reflect that.
Related
I want to pass data RC_1 to RC_2. How can I do this(cat, info, orderid) RecyclerView to RecyclerView?Examp.pic_1
My firebase node is like as to picture.
My firebase node
//RC_1 Struct
public class Name_Struct {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//RC_2 Struct
public class Detail_Struct {
private String cat;
private String info;
private String orderid;
public String getCat() {
return cat;
}
public void setCat(String cat) {
this.cat = cat;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getOrderid() {
return orderid;
}
public void setOrderid(String orderid) {
this.orderid = orderid;
}
RC_1 for;
//Myactivity_1
private void rc_1_get_name(){
Query query = FirebaseDatabase.getInstance().getReference()
.child(“Pro_”);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
mName.clear();
for(DataSnapshot snp : snapshot.getChildren()){
Name_Struct names = snp.getValue(Name_Struct.class);
for (DataSnapshot recipeSnapshot: snp.child(“basket”).getChildren()) {
mName.add(names);
}
}
mName_adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
RC_1 for;
//Myadapter_ 1
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, #SuppressLint("RecyclerView") int position) {
final Name_Struct names = mName.get(position);
holder.name_.setText(names.getName()));
holder.relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(mContext, RC_2.class);
???
mContext.startActivity(intent);
}
}
As I see in your screenshot, the "Pro_" node contains a name that has the value of "Mike". This means that you can map that node into an object of type Name_Struct. And you are doing that successfully. Under the same node, there is however another node called "Basket". That node is represented by a Map object, where the keys are represented by those IDs (ID_1, ID_2, etc) and the value by Detail_Struct objects. To be able to map the data under the "Basket" node, you have to add a new property in your Name_Struct class called basket like this:
public class Name_Struct implements Serializable {
private String name;
private Map<String, Object> basket;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#PropertyName("Basket")
public Map<String, Object> getBasket() {
return basket;
}
public void setBasket(Map<String, Object> basket) {
this.basket = basket;
}
}
Now to pass the data to the second activity, you have to add iterate the Map and create a List<Detail_Struct> that can be added to the Intent so it can be read in the second activity.
I have an order collection. A user can request and cancel the order and receive the order.
There were three statuses here:
- Requested Order
- Canceled Order
- Received Order
I will explain the question with codes. as follows:
Order Model Class:
public class Order {
private String userId;
private String productId;
#OrderStatus
private int status;
#ServerTimestamp
private Date requestedAt;
private Date canceledAt;
private Date receivedAt;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public Date getRequestedAt() {
return requestedAt;
}
public void setRequestedAt(Date requestedAt) {
this.requestedAt = requestedAt;
}
public Date getCanceledAt() {
return canceledAt;
}
public void setCanceledAt(Date canceledAt) {
this.canceledAt = canceledAt;
}
public Date getReceivedAt() {
return receivedAt;
}
public void setReceivedAt(Date receivedAt) {
this.receivedAt = receivedAt;
}
}
Status Enum:
public #interface OrderStatus {
int OS_REQUESTED = 0;
int OS_USER_CANCELED = 1;
int OS_RECEIVED = 2;
}
when the user requests an order:
public static void requestOrder(String userId, String productId) {
Order order = new Order();
order.setUserId(userId);
order.setProductId(productId);
order.setStatus(OrderStatus.OS_REQUESTED);
FirebaseFirestore.getInstance()
.collection("orders")
.add(order);
}
Up to now, the requestedDate has been successfully filled with the server timestamp.
But when the user cancels the order:
public static void cancelOrder(String orderId, #NonNull Order order) {
order.setStatus(OrderStatus.OS_CANCELED);
order.setCanceledAt(new Date()); // how to use FieldValue.serverTimestamp() here?
FirebaseFirestore.getInstance()
.collection("orders")
.document(orderId)
.set(order);
}
Of course I can do it using Update. in that:
public static void cancelOrder(String orderId) {
Map<String, Object> data = new HashMap<>();
data.put("status", OrderStatus.OS_CANCELED);
data.put("canceledAt", FieldValue.serverTimestamp());
FirebaseFirestore.getInstance()
.collection("orders")
.document(orderId)
.update(data);
}
But I want to use POJO/Model.
If i add #ServerTimetamp annotation to the CancelledAt property then it will be filled in when the order is requested. So:
public class Order {
...
#ServerTimestamp
private Date requestedAt;
#ServerTimestamp // <-- will be filled in the order request if added
private Date canceledAt;
#ServerTimestamp
private Date receivedAt;
...
}
If I change its type to Timestamp, how do I assign FieldValue.serverTimestamp()?
Thanks in advance.
If you want to use a server timestamp as the value of a POJO property, you will need to use the #ServerTimetamp annotation. I believe the value should be of Timestamp type.
This is the model for my RealmObject class :
public class ARDatabase extends RealmObject
{
#PrimaryKey
private String uid;
private String namex;
private String desc;
private boolean isVideo;
private boolean isDeleted;
private String urlImg;
private String urlApp;
private int updates;
private boolean isDownloaded;
private String location;
public ARDatabase(){}
public String getUid()
{
return uid;
}
public void setUid(String uid)
{
this.uid = uid;
}
public String getNamex()
{
return namex;
}
public void setNamex(String namex)
{
this.namex = namex;
}
public String getDesc()
{
return desc;
}
public void setDesc(String desc)
{
this.desc = desc;
}
public boolean getIsVideo()
{
return isVideo;
}
public void setIsVideo(boolean isVideo)
{
this.isVideo = isVideo;
}
public boolean getIsDeleted()
{
return isDeleted;
}
public void setIsDeleted(boolean isDeleted)
{
this.isDeleted = isDeleted;
}
public String getUrlImg()
{
return urlImg;
}
public void setUrlImg(String urlImg)
{
this.urlImg = urlImg;
}
public String getUrlApp()
{
return urlApp;
}
public void setUrlApp(String urlApp)
{
this.urlApp = urlApp;
}
public int getUpdates()
{
return updates;
}
public void setUpdates(int updates)
{
this.updates = updates;
}
public boolean getIsDownloaded()
{
return isDownloaded;
}
public void setIsDownloaded(boolean isDownloaded)
{
this.isDownloaded = isDownloaded;
}
public String getLocation()
{
return location;
}
public void setLocation(String location)
{
this.location = location;
}
}
And this is how I search for the uid from my default realm:
final ARDatabase db = mRealm.where(ARDatabase.class).equalTo("uid",imageTitles.get(result)).findFirst();
Now, the question is: Considering I have 10-100 objects inside my realm, how fast would the search be?
The use case is for an image recognition app. When the app recognizes an image it returns the uid, and based on the uid I need to provide an overlay on the screen with the information associated with the uid ASAP.
Now since I have around 10-100 objects, would a linear search O(n) or a generic binary search O(log n) would be faster than the Realm search I've used above? Or is it possible to tweak Realm to get faster results? (in case it's not performing the fastest way now).
Doing the search in Realm will always be faster since you can execute the entire search inside the C++ core. Doing the search yourself will mean you occur the overhead of going back and forth between Java and C++.
The only requirement for doing fast searching for single elements is that you have an #Index annotation on the field, but in your case you already have #PrimaryKey which automatically applies the #Index annotation as well.
So your query is as fast as it can be. Besides, for 10-100 objects, no matter what you do, it will probably appear instantaneous to the user.
This is the structure of my Realm database:
public class ARDatabase extends RealmObject
{
#PrimaryKey
private String uid;
private String namex;
private String desc;
private boolean isVideo;
private boolean isDeleted;
private String urlImg;
private String urlApp;
private int updates;
private boolean isDownloaded;
private String location;
public ARDatabase(){}
public String getUid()
{
return uid;
}
public void setUid(String uid)
{
this.uid = uid;
}
public String getNamex()
{
return namex;
}
public void setNamex(String namex)
{
this.namex = namex;
}
public String getDesc()
{
return desc;
}
public void setDesc(String desc)
{
this.desc = desc;
}
public boolean getIsVideo()
{
return isVideo;
}
public void setIsVideo(boolean isVideo)
{
this.isVideo = isVideo;
}
public boolean getIsDeleted()
{
return isDeleted;
}
public void setIsDeleted(boolean isDeleted)
{
this.isDeleted = isDeleted;
}
public String getUrlImg()
{
return urlImg;
}
public void setUrlImg(String urlImg)
{
this.urlImg = urlImg;
}
public String getUrlApp()
{
return urlApp;
}
public void setUrlApp(String urlApp)
{
this.urlApp = urlApp;
}
public int getUpdates()
{
return updates;
}
public void setUpdates(int updates)
{
this.updates = updates;
}
public boolean getIsDownloaded()
{
return isDownloaded;
}
public void setIsDownloaded(boolean isDownloaded)
{
this.isDownloaded = isDownloaded;
}
public String getLocation()
{
return location;
}
public void setLocation(String location)
{
this.location = location;
}
}
And I can successfully add objects to the database.
The problem comes when I need to update an object.
This is what I tried:
private void downloadUpdateDatabase(String uid,String location_address) throws RealmException
{
mRealm.beginTransaction();
ARDatabase db = new ARDatabase();
db.setUid(uid);
db.setIsDownloaded(true);
db.setLocation(location_address);
mRealm.copyToRealmOrUpdate(db);
mRealm.commitTransaction();
Log.e("TAG","DOWNLOAD UPDATE COMPLETED");
}
The problem here is when I invoke this method. The mentioned fields get updated, but the not mentioned fields in this method become null or zero.
Of course I can set values for all fields by invoking their setters, however from where I invoke this method, I can't get all the field values.
So, the Question is: How do I update my realm database in such a way that the existing fields don't become null ?
P.S.:
My Realm version is :0.84.1, compile 'io.realm:realm-android:0.84.1'
the field that are mentioned gets updated, however the fields that are not mentioned in this method becomes null or zero
Well, yes, all fields are their defaults at this point.
ARDatabase db = new ARDatabase();
Have you tried to query for the current record, then update the fields, then put that object back?
In other words, you have String uid, so something like
private void downloadUpdateDatabase(String uid,String location_address) throws RealmException
{
mRealm.beginTransaction();
ARDatabase db = mRealm.where(ARDatabase.class).equalTo("uid", uid).findFirst();
db.setIsDownloaded(true);
db.setLocation(location_address);
mRealm.copyToRealmOrUpdate(db);
mRealm.commitTransaction();
}
Or, probably better in async fashion.
private void downloadUpdateDatabase(final String uid, final String location_address) throws RealmException
{
mRealm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
ARDatabase db = realm.where(ARDatabase.class).equalTo("uid", uid).findFirst();
db.setIsDownloaded(true);
db.setLocation(location_address);
}
}, new Realm.Transaction.OnSuccess() {
#Override
public void onSuccess() {
// Transaction was a success.
}
}, new Realm.Transaction.OnError() {
#Override
public void onError(Throwable error) {
// Transaction failed and was automatically canceled.
}
});
}
Instead of
mRealm.beginTransaction();
ARDatabase db = new ARDatabase();
db.setUid(uid);
db.setIsDownloaded(true);
db.setLocation(location_address);
mRealm.copyToRealmOrUpdate(db);
mRealm.commitTransaction();
Log.e("TAG","DOWNLOAD UPDATE COMPLETED");
There should be
mRealm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
ARDatabase db = realm.where(ARDatabase.class).equalTo("uid", uid).findFirst();
if(db == null) {
db = realm.createObject(ARDatabase.class, uid);
}
db.setIsDownloaded(true);
db.setLocation(location_address);
}
});
Log.e("TAG","DOWNLOAD UPDATE COMPLETED");
In my Android app I use Backendless to store my data online. I want to do something when a new Point object is saved but the beforeCreate event never gets triggered.
Bootstrap.java
public class Bootstrap implements IBackendlessBootstrap
{
#Override
public void onStart()
{
Backendless.setUrl( "https://api.backendless.com" );
Backendless.initApp( "XXXXXXXXXXXXXXXX", "XXXXXXXXXXXXX","v1");
Backendless.Persistence.mapTableToClass( "Point", Point.class );
}
#Override
public void onStop()
{
}
}
PointTableEventHandler.java:
#Asset( "Point" )
public class PointTableEventHandler extends com.backendless.servercode.extension.PersistenceExtender<Point>
{
#Override
public void beforeCreate( RunnerContext context, Point point) throws Exception
{
System.out.println("enter beforeCreate");
point.setPhoneNumber("12345");
System.out.println("exit beforeCreate");
}
}
Point.java
public class Point extends BackendLessObject {
private String phoneNumber;
public Point() {
super();
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
BackendlessObject.java
public class BackendLessObject {
protected String objectId;
protected Date created;
protected Date updated;
protected String ownerId;
public BackendLessObject() {
}
public String getObjectId() {
return objectId;
}
public void setObjectId( String objectId )
{
this.objectId = objectId;
}
public Date getCreated()
{
return created;
}
public void setCreated( Date created )
{
this.created = created;
}
public Date getUpdated()
{
return updated;
}
public void setUpdated( Date updated )
{
this.updated = updated;
}
public String getOwnerId() {
return ownerId;
}
#Override
public String toString() {
return objectId;
}
}
The event is enabled and deployed to production. When I run my app the point is created with all the data provided, but the PhoneNumber is not set - so the event did not run. Debugging it also shows that it was never called.
In my Android app I call
newPoint.save();
This is fixed in the latest version of the library. Make sure to grab a copy from the github repository.