I am building an Android shopping list app following a Angga Risky tutorial.
Code running Error free, but the list I have created is not being populated by the firebase real-time database it is connected to. Below is the mainactivity
public class MainActivity extends AppCompatActivity {
TextView titlepage, subtitlepage, endpage;
DatabaseReference reference;
RecyclerView ourlist;
ArrayList < MyList > list;
ListAdapter listAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
titlepage = findViewById(R.id.titlepage);
subtitlepage = findViewById(R.id.subtitlepage);
endpage = findViewById(R.id.endpage);
//working with data
ourlist = findViewById(R.id.ourlist);
ourlist.setLayoutManager(new LinearLayoutManager(this));
list = new ArrayList < MyList > ();
//get data from firebase
reference = FirebaseDatabase.getInstance().getReference().child("compshopper3");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//set code to retrieve data and replace layout
for (DataSnapshot dataSnapshot1: dataSnapshot.getChildren()) {
MyList p = dataSnapshot1.getValue(MyList.class);
list.add(p);
}
listAdapter = new ListAdapter(MainActivity.this, list);
ourlist.setAdapter(listAdapter);
listAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// set code to show an error
Toast.makeText(getApplicationContext(), "Dude Where's My Data???", Toast.LENGTH_SHORT).show();
}
});
}
}
Here is look at the firebase data
Here is a shot of the emulator output.
First change the reference to refer to the parent node:
reference = FirebaseDatabase.getInstance().getReference().child("CompShopperApp");
Then remove the for loop inside onDataChange() and make sure that your model class contains the fields price1, price2, price3 and itemtitle:
reference.addValueEventListener( new ValueEventListener () {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
MyList p = dataSnapshot.getValue(MyList.class);
list.add(p);
listAdapter = new ListAdapter(MainActivity.this, list);
ourlist.setAdapter(listAdapter);
listAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// set code to show an error
Toast.makeText(getApplicationContext(), "Dude Where's My Data???", Toast.LENGTH_SHORT).show();
}
In addition to #peter-haddad's answer, make sure your firebase database rules allow you to access the data without authentication, in case you're trying to do that (which we usually do during dev testing).
Firebase console -> Database (Realtime Database) -> Rules ->
{
"rules": {
".read": true,
".write": true
}
}
Related
I initialize a map in my main activity, the problem is that i need this map to initialize some variables in my launch fragment so the fragment is update before the map.
I initialize my map thanks to an event listener to read on my database
MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init_users();
//...
}
public static void init_users(){
// Fill users_map thanks to database
DatabaseReference db_users = FirebaseDatabase.getInstance().getReference().child("users");
// Recovery users : RealTime DataBase
ValueEventListener userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int i = 0;
for (DataSnapshot ds : dataSnapshot.getChildren()) {
User user = ds.getValue(User.class);
User.users_map.put(i, user);
User.usernames[i] = user.getName();
i++;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w("Reading of Database ", "loadPost:onCancelled", databaseError.toException());
}
};
db_users.addValueEventListener(userListener);
}
So my fragment launchs him and use the map to initialize usefull variables
In my Fragment
user1 = User.users_map.get(0);
user2 = User.users_map.get(1);
How can i do to assure the initialization of my map (in the event listener) before the launch of my fragment ?
I would like read data from firebase into spinner, and the spinner should contain data per ID. There is two spinner, color & size, but what I got is all data from all ID. How i can fix this issue?
The firebase data structure like image below :
and here is my code :
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
DatabaseReference AttrReference = reference.child("Products").child("Attribut");
....
private void getAttributProduct() {
AttrReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
list = new ArrayList<>();
colorList = new ArrayList<>();
sizeList = new ArrayList<>();
if (dataSnapshot.exists()) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
for (DataSnapshot child : snapshot.getChildren()) {
AttrProduk attr = child.getValue(AttrProduk.class);
list.add(attr);
colorList.add(attr.getColor());
sizeList.add(attr.getSize());
showSpinnerSize(sizeList);
showSpinnerColor(colorList);
showStock(attr.getStock());
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void showSpinnerSize(List<String> dataSize) {
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_spinner_item, dataSize);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spSize.setAdapter(adapter);
}
private void showSpinnerColor(List<String> dataColor) {
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_spinner_item, dataColor);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spColor.setAdapter(adapter);
}
private void showStock(String data) {
stock.setText(data+" Pcs");
}
And here is what i got, based on database it should get data per ID :
If you want the spinner to show data related to a key, then you need to do a query:
DatabaseReference AttrReference = reference.child("Products").child("Attribut");
Query query=AttrReference.orderByKey().equalTo(key_id);
query.addValueEventListener(new ValueEventListener() {..}
https://firebase.google.com/docs/reference/android/com/google/firebase/database/Query.html#orderByKey()
I'm trying to create a Firebase Realtime database project in which the data stored is either type A or type B, etc. This is how it looks like on the console:
Firebase Database
The user can then add more posts, of which are saved to the database then displayed on a ListView.
My Code
final DatabaseReference room = FirebaseDatabase.getInstance().getReference().getRoot();
chatRoomAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, chatList);
lvChatRoom.setAdapter(chatRoomAdapter);
btnAddChatRoomMa.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
strChatRoomName = etChatRoom.getText().toString();
etChatRoom.setText("");
Map<String, Object> chatMap = new HashMap<>();
chatMap.put(strChatRoomName + " -TYPEA", "");
room.updateChildren(chatMap);
}
});
room.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Iterator iterator = dataSnapshot.getChildren().iterator();
Set<String> set = new HashSet<>();
while (iterator.hasNext()) {
set.add(((DataSnapshot) iterator.next()).getKey());
}
chatList.clear();
chatList.addAll(set);
chatRoomAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I only want to show for instance, TYPEA (on the database), without displaying the rest. How can I achieve this?
If you want to display only the value of the property TYPEA, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = rootRef.child("fruit-TYPEA");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String fruitTYPEA = dataSnapshot.getValue(String.class);
Log.d("TAG", fruitTYPEA);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
ref.addListenerForSingleValueEvent(valueEventListener);
The output will be: orange.
I am trying to fetch data from Firebase database from multiple child in single function. I have two child nodes in Firebase Favorites and Users
I am using RecyclerView to show list of Favorites User but i want to fetch one value name "Online" from Users node.
I add addValueEventListener on Favorites and add addListenerForSingleValueEvent on Users within Favorites addValueEventListener, but my addListenerForSingleValueEvent give null value.
There is my code:
mFavouriteDBRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mList.clear();
if(dataSnapshot.getChildrenCount() > 0){
for(DataSnapshot snap: dataSnapshot.getChildren()){
final Favourites user = snap.getValue(Favourites.class);
final FavouritesList[] holdObj = null;
//if not current user, as we do not want to show ourselves then chat with ourselves lol
try {
if(mAuth.getCurrentUser().getUid().equals(user.getUserId())){
//Firebase Reading data
mUsersDBRef = FirebaseDatabase.getInstance().getReference().child("Users");
mUsersDBRef.child(mAuth.getCurrentUser().getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUsersDBRef.child(mAuth.getCurrentUser().getUid()).child("online").onDisconnect().setValue(false);
String local =dataSnapshot.child(mAuth.getCurrentUser().getUid()).child("online").getValue().toString();
if(local.equals("true")){
holdObj[0] = new FavouritesList(mAuth.getCurrentUser().getUid(),user.getFavouriteId(),user.getFavouriteName(),user.getFavouriteCity(),user.getFavouriteCountry(),user.getFavouriteAge(),user.getFavouriteGender(),user.getFavouriteKeyword(),user.getPushKey(), "true","Link");
}else{
holdObj[0] = new FavouritesList(mAuth.getCurrentUser().getUid(),user.getFavouriteId(),user.getFavouriteName(),user.getFavouriteCity(),user.getFavouriteCountry(),user.getFavouriteAge(),user.getFavouriteGender(),user.getFavouriteKeyword(),user.getPushKey(), "false","Link");
}
mList.add(holdObj[0]);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
populaterecyclerView();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here my populaterecyclerView(); Class
private void populaterecyclerView(){
adapter = new UserFavouritesMeHomeListAdapter(context,mList);
adapter.setClickListener(UserFavouritesMeListHomeFragment.this);
recyclerView.setAdapter(adapter);
}
Thanks
Link of Image:
http://userdata.in/singls/images/profile/WobiUh7Zb2bjszmYN0LofK7Pm0z1_20180124042847_file_cover.jpg
Data want to fetch from while reading Favorite
http://userdata.in/singls/images/profile/WobiUh7Zb2bjszmYN0LofK7Pm0z1_20180124044659_file_cover.jpg
This function is returning no data in spite of receiving snapshots and adding the data in ArrayList in onDataChange() function but in the end, it is returning ArrayList with size 0.
List<ProductEntity> feed_data() {
final List<ProductEntity> feededProducts = new ArrayList<>();
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please wait...");
progressDialog.show();
mDatabase = FirebaseDatabase.getInstance().getReference("/products");
//adding an event listener to fetch values
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
//dismissing the progress dialog
progressDialog.dismiss();
//iterating through all the values in database
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
ProductEntity upload = postSnapshot.getValue(ProductEntity.class);
Log.d("error", "onDataChange: " + upload.about);
feededProducts.add(upload);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("Error", "onCancelled: " + databaseError.getMessage());
NestedScrollView root_layout = findViewById(R.id.category_root_layout) ;
Snackbar.make(root_layout, "Internal Error!!", Snackbar.LENGTH_SHORT).show();
}
});
return feededProducts ;
}
onDataChange(DataSnapshot snapshot) is called asynchrounously. That is will be called when we get data back from Firebase.
Hence your return feededProducts is called before onDataChange(DataSnapshot snapshot) method, so you will be returning empty list everytime.
You will have to call notifydatasetchanged on your adapter inside onDataChange(DataSnapshot snapshot)
You'll need to create an interface which you will call when the data is received.
interface DataReceivedListener{
void onDataReceived(List<ProductEntity> data);
}
void feed_data(DataReceivedListener listener) {
final List<ProductEntity> feededProducts = new ArrayList<>();
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please wait...");
progressDialog.show();
mDatabase = FirebaseDatabase.getInstance().getReference("/products");
//adding an event listener to fetch values
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
//dismissing the progress dialog
progressDialog.dismiss();
//iterating through all the values in database
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
ProductEntity upload =
postSnapshot.getValue(ProductEntity.class);
Log.d("error", "onDataChange: " + upload.about);
feededProducts.add(upload);
}
listener.onDataReceived(feededProducts);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("Error", "onCancelled: " + databaseError.getMessage());
NestedScrollView root_layout =
findViewById(R.id.category_root_layout) ;
Snackbar.make(root_layout, "Internal Error!!",
Snackbar.LENGTH_SHORT).show();
}
});
}
Either implement the DataReceivedListener interface in your Activty and override the 'onDataReceived()' function and pass 'this' to 'feed_data(DataReceivedListener listener)' or create a DataReceivedListener as a variable and pass that variable to 'feed_data(DataReceivedListener listener)'
When the data is received in 'onDataChange(DataSnapshot snapshot)' it calls the function of the interface and then your overridden function will be called or the one you initilazied the 'DataReceivedListener' variable with. Depends on how you did it.
Put your code where you need the data inside the 'onDataReceived(List data)' function.
I just needed to initialize and set the Adapter after adding all the data in my Arralist as pointed out above like this and it solved my problem:
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
ProductEntity upload = postSnapshot.getValue(ProductEntity.class);
productList.add(upload);
}
productsRecyclerAdapter = new ProductsRecyclerAdapter(productList, CategoryActivity.this);
products.setAdapter(productsRecyclerAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
NestedScrollView root_layout = findViewById(R.id.category_root_layout);
Snackbar.make(root_layout, "Internal Error!!", Snackbar.LENGTH_SHORT).show();
}
});