My app has two categories of users shop owner and buyers.
When shop owner adds a shop I use his UID and then pushkey to add a shop like this:
In the Image "83yV" and "FmNu" are the shop owners and they add 2 and 1 shop respectively.
Now for buyers, I want to show the whole list of shops in a Recycler View.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_shops_avtivity);
shopsDB = FirebaseDatabase.getInstance().getReference().child("shops");
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Shop,ShopViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Shop, ShopViewHolder>(
Shop.class,
R.layout.shop_single_layout,
ShopViewHolder.class,
shopsDB)
}
The problem is when I point my Firebase Recycler Adapter to shopDB, it returns two empty cardView like this:
When I point it to specific child like
shopsDB = FirebaseDatabase.getInstance().getReference().child("shops").child("83yV24a3AmP15XubhPGApvlU7GE2");
It returns shops add by "83yV".
How can I get the shops added by other owners also? Preferably without altering current DB or creating one DB with all shops in it within on child.
To achieve this, you need to use getChildren() method twice, once to get all the users and second to get all the shops.
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference shopsRef = rootRef.child("shops");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
for(DataSnapshot dSnapshot : ds.getChildren()) {
String name = dSnapshot.child("name").getValue(String.class);
Log.d("TAG", name);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
shopsRef.addListenerForSingleValueEvent(eventListener);
Using this code, you'll be able to display all shop names to the buyers.
Related
How to get the data under foods (product Name)?
I can get the data (with the check icon).
I want to get the data from the wrong icon.
Here is my MainActivity code for database reference
// getting Firebase Database reference to communicate with firebase database
private final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
// creating List of MyItems to store user details
private final List<MyItems> myItemsList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// getting RecyclerView from xml file
final RecyclerView recyclerView = findViewById(R.id.recyclerView);
// setting recyclerview size fixed for every item in the recyclerview
recyclerView.setHasFixedSize(true);
// setting layout manager to the recyclerview. Ex. LinearLayoutManager (vertical mode)
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
// clear old items / users from list to add new data/ users
myItemsList.clear();
// getting all children from users root
for (DataSnapshot Requests : snapshot.child("Requests").getChildren()) {
// to prevent app crash check if the user has all the details in Firebase Database
if (Requests.hasChild("askfor") && Requests.hasChild("tablet") && Requests.hasChild("total")) {
// getting users details from Firebase Database and store into the List one by one
final String getaskfor = Requests.child("askfor").getValue(String.class);
final String gettablet =Requests.child("tablet").getValue(String.class);
final String gettotal =Requests.child("total").getValue(String.class);
// final String getproductName =Requests.child("productName").getValue(String.class);
// creating user item with user details
MyItems myItems = new MyItems(getaskfor, gettablet, gettotal);
The foods node in your database looks like an array, so if you get its value in Java code you'll get a List.
So you can loop over the food children just as you do already for the requests children:
if (Requests.hasChild("foods") {
for (DataSnapshot foodSnapshot : Requests.child("foods").getChildren()) {
String productName = foodSnapshot.child("productName").getValue(String.class);
...
}
}
Unrelated: since your onDataChange implementation on seems to process the Requests node, it is more efficient to only load that node from the database, instead of loading the entire database.
So:
// 👇 Add here
databaseReference.child("Requests").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
// clear old items / users from list to add new data/ users
myItemsList.clear();
// getting all children from users root
// 👇 Remove here
for (DataSnapshot Requests : snapshot.getChildren()) {
...
I am trying to retrieve data from Firebase Realtime Database and add this data to a listview. When I call push() firebase generates two children (one inside the other) with the same unique key. This is the structure of my database:
database
That is how I save the data:
RunningSession runningSession = new RunningSession(date, activityTime, pace, timeElapsed,
finalDistance, image, tipe);
DatabaseReference reference = databaseReference.child("users").child(userUid).child("activities").push();
Map<String, Object> map = new HashMap<>();
map.put(reference.getKey(),runningSession);
reference.updateChildren(map);
This is how i retrieve the data (results in a null pointer exception):
DatabaseReference reference = databaseReference.child("users").child(userId).child("activities");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
list.clear();
for (DataSnapshot snpshot : snapshot.getChildren()) {
RunningSession run = snpshot.getValue(RunningSession.class);
list.add(run);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
ListViewAdapter adapter = new ListViewAdapter(this, list);
ListView activityItems = (ListView) findViewById(R.id.activityList);
activityItems.setAdapter(adapter);
You are getting duplicate push IDs because you are adding them twice to your reference. If you only need one, then simply use the following lines of code:
RunningSession runningSession = new RunningSession(date, activityTime, pace, timeElapsed, finalDistance, image, tipe);
DatabaseReference reference = databaseReference.child("users").child(userUid).child("activities");
String pushedId = reference.push().getKey();
reference.child(pushedId).setValue(runningSession);
The code for reading that may remain unchanged.
Here is my firebase database
Here is the info.class
Here is the insert
I want to get all the data from firebase to List View
How can i get all data under "information" data list ?
please help
db = FirebaseDatabase.getInstance();
ref = db.getReference("infomation");
protected void onStart() {
super.onStart();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
infoList.clear();
for (DataSnapshot infoSnapshot : dataSnapshot.getChildren()){
info info = infoSnapshot.getValue(info.class);
infoList.add(info);
}
InfoList adapter = new InfoList(Welcome.this, infoList);
listViewInfo.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
In your insertion part, you need to change it like below,
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("information");
ref.child( FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(in);
but if you want to save data like save the data like
information >uid> random value > then the data
that use change data retrieving part like below
for (DataSnapshot infoSnapshot : dataSnapshot.getChildren().getChildren()){
info info = infoSnapshot.getValue(info.class);
infoList.add(info);
}
So I have a set up where I want to get data from the Database on Firebase, I can get the URL back fine but I can't get data from it. When I try to debug it reads in query.addValueEventListener but after that it just goes straight to my list adapter. I don't know it's not getting the data. I have a similar set up on my node server which works perfectly fine, but won't work on Android for some reason
final DatabaseReference database = FirebaseDatabase.getInstance().getReference();
Query query = database.child("exercises");
Log.i("Database query", database.child("exercises").toString());
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot exerciseSnapshot: dataSnapshot.getChildren())
{
List<ExerciseList> exercises = new ArrayList<ExerciseList>();
ExerciseList exerciseList = exerciseSnapshot.getValue(ExerciseList.class);
Log.i("description/name", exerciseList.getDescription() + " " + exerciseList.getName());
exercises.add(exerciseList);
adapter = new ExerciseLoadListAdapter(mActivity, exercises);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mListView.setAdapter(adapter);
its go to adapter directly because addValueEventListener() is Asynchronous listeners , its run in background !
Try this code , it may be help you !
final DatabaseReference database = FirebaseDatabase.getInstance().getReference();
//Query query = database.child("exercises");
//Log.i("Database query", database.child("exercises").toString());
database.child("exercises").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot exerciseSnapshot: dataSnapshot.getChildren())
{
List<ExerciseList> exercises = new ArrayList<ExerciseList>();
ExerciseList exerciseList = exerciseSnapshot.getValue(ExerciseList.class);
Log.i("description/name", exerciseList.getDescription() + " " + exerciseList.getName());
exercises.add(exerciseList);
}
adapter = new ExerciseLoadListAdapter(mActivity, exercises);
mListView.setAdapter(adapter)
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The Firebase do NOT get the data in the debug mode in real time. If you need some object from your firebase database you will need to get the object before. I face this problem a several times, thats why in some cases I use SQLite to store data from Firebase before i take any action. But, in a fragment you can not do that, you need the data in realtime. So you need to store the listener in a variable and use it after. Here in my Github page I have a fragment working fine.
ContatsFragment.java
[]'s
I am not sure if I am understanding some of the literature correctly. Android documentation says don't create unecessary objects. This article (Are Firebase queries scalable) mentions scalability with DB queries is ok, but I've also read its better to store your Query into an ArrayList and search through that instead of querying a large DB.
In my case I am using Firebase Realtime Database for Android and I'm wondering if I get a Child Node that has maybe 200 examples/child nodes, should I put each of these snapshots into a Model Class and then Add each of those to an ArrayList which can then be displayed in a RecyclerView? Or Should I run .getValue() on the fields and store them in another way?
I am specifically looking to see which Company ID's an Employer is associated to, and then go to the Companies node and Get the Business Names and Business Cities for that Employer
DB:
Here is my section of code in the activity:
companiesRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()) {
Log.i("companiesSnap", ds.toString());
Log.i("KEYs", ds.getKey());
companyIDKey = ds.getKey();
//For each company ID in the Arraylist
for (int i = 0; i < myCompanyIDsList.size(); i++) {
//IF the IDs in arraylist from employee matches CompanyID from Companies node
if(myCompanyIDsList.get(i).equals(companyIDKey)) {
//IF THE ID matches, then get the associated company info
Log.i("city", ds.child("businessCity").getValue().toString());
Log.i("name", ds.child("businessName").getValue().toString());
Businesses business = new Businesses(ds);
myBusinessListItems.add(business);
mAdapter.updateDataSet(myBusinessListItems);
}
}
Entire Class:
public class BusinessesActivity extends Activity {
private Context mContext;
LinearLayout mLinearLayout;
private RecyclerView mRecyclerView;
private MyAdapterBusiness mAdapter = new MyAdapterBusiness(this);
private RecyclerView.LayoutManager mLayoutManager;
ArrayList<Businesses> myBusinessListItems;
ArrayList<String> myCompanyIDsList;
DatabaseReference employeesRefID, companiesRef;
FirebaseDatabase database;
String currentUser, companyIDKey;
TextView getData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_businesses);
//RECYCLERVIEW STUFF
mRecyclerView = (RecyclerView) findViewById(R.id.b_recycler_view);
mContext = getApplicationContext(); // Get the application context
// Define a layout for RecyclerView
mLayoutManager = new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false); //mLayoutManager = new LinearLayoutManager(mContext);
mRecyclerView.setLayoutManager(mLayoutManager);
// Initialize a new instance of RecyclerView Adapter instance
mRecyclerView.setAdapter(mAdapter);
//ARRAY List to Store EACH Company ID
myCompanyIDsList = new ArrayList<String>();
myBusinessListItems = new ArrayList<Businesses>();
currentUser =
FirebaseAuth.getInstance().getCurrentUser().getUid();
database = FirebaseDatabase.getInstance();
getData = (TextView) findViewById(R.id.getData);
companiesRef = database.getReference("Companies").child("CompanyIDs");
final DataSnapshotCallback callback = new DataSnapshotCallback() {
#Override
public void gotDataSnapshot(DataSnapshot snapshot) {
EmployeeUser employee = new EmployeeUser(snapshot);
//myCompanyIDsList.add(employee);
try {
for (DataSnapshot ds : snapshot.getChildren()) {
//WITHIN each UserId check the PushID
Log.i("TAG", "checkIfIDExists: datasnapshot: " + ds);
myCompanyIDsList.add(ds.getValue(EmployeeUser.class).getID());
Log.i("arrayList", myCompanyIDsList.toString());
//}
}
//GO THROUGH EACH COMPANY ID AND FIND INFORMATION
companiesRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()) {
Log.i("companiesSnap", ds.toString());
Log.i("KEYs", ds.getKey());
companyIDKey = ds.getKey();
//For each company ID in the Arraylist
for (int i = 0; i < myCompanyIDsList.size(); i++) {
//IF the IDs in arraylist from employee matches CompanyID from Companies node
if(myCompanyIDsList.get(i).equals(companyIDKey)) {
//IF THE ID matches, then get the associated company info
Log.i("city", ds.child("businessCity").getValue().toString());
Log.i("name", ds.child("businessName").getValue().toString());
Businesses business = new Businesses(ds);
myBusinessListItems.add(business);
mAdapter.updateDataSet(myBusinessListItems);
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("Cancelled", databaseError.toString());
}
}); //END COMPANIES EVENT LISTENER
//} //END FOR
} //END TRY
catch (Exception e) {
Log.i("FNull?", e.toString());
}
//mAdapter.updateDataSet(myListItems);
}
};
getData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
employeesRefID = database.getReference("Employees").child(currentUser).child("Companies"); //SEE HOW ADD EMPLOYEES checks
employeesRefID.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
callback.gotDataSnapshot(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("Cancelled", databaseError.toString());
}
}); //END EMPLOYEE EVENT LISTENER
Log.i("OutsideEvent", myCompanyIDsList.toString());
}
}); //END ONCLICK
Log.i("OutsideonClick", myCompanyIDsList.toString());
}
interface DataSnapshotCallback {
void gotDataSnapshot(DataSnapshot snapshot);
}
}
The trick to reducing memory usage when using Firebase is to only load data that you're going to display to the user.
If you need a list of just business names, create a nodes with just the business names in the database and display that. That way you've reduce both the bandwidth and the memory used, since you're not loading the other properties of the company.
You'll typically have one "master list" with all properties of each company (or other entity type). And then you may have one or more "display lists" that contain only the information of the business that you need to display in certain areas. This duplicated data is quite common in NoSQL databases, and is known as denormalization.
For a better introduction, read Denormalizing Your Data is Normal, NoSQL data modeling, and watch Firebase for SQL developers.