Working on an Android Project using Firebase.
The project is to let users check in and display all logs in a table view.
I have set up the firebase database as follows:
I can't get the entries to show in the table view?
I would like to show the following items per list item:
userCheckIn
username
userLocation
My code:
private ListView mListView;
private DatabaseReference mDatabse;
private ArrayList<String> arrayList = new ArrayList<>();
private ArrayAdapter<String> adapter;
String Date;
Calendar calendar;
SimpleDateFormat simpleDateFormat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account);
mListView = (ListView) findViewById(R.id.database_list_view);
calendar = Calendar.getInstance();
simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Date = simpleDateFormat.format(calendar.getTime());
FirebaseUser currentFirebaseUser = FirebaseAuth.getInstance().getCurrentUser() ;
mDatabse = FirebaseDatabase.getInstance().getReference().child("CheckInOut").child(currentFirebaseUser.getUid()).child(Date).child("userCheckIn");
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList);
mListView.setAdapter(adapter);
mDatabse.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String string = dataSnapshot.getValue(String.class);
arrayList.add(string);
adapter.notifyDataSetChanged();
}
#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) {
}
});
}
I would appreciate any support possible.
To solve this, move the declaration of your ArrayList and ArrayAdapter inside onChildAdded() method. You need also to set the adapter inside onChildAdded() method because this method has an asynchronous behaviour. This means that if you are trying to set the adapter outside onChildAdded() method it will always be empty because at that time you haven't got all the data from the database. So all operation must take place inside that method.
I recomand you also to use FirebaseUI. It will handle all the events for you. If want to read more about how you can get the data outside an asynchronous method, take a look at my answer from this post.
Related
Is there any mistake in code because I am getting the only price in the listview and not the name can anyone help me out? I've tried so many methods to solve it but in last it let me post on StackOverflow to ask you people for the help, I am really stuck in it. I'll be really thankful to you for this help. Model class will also be provided if needed.
private ListView mlistView;
private ArrayList<String>list;
private ArrayAdapter<String> adapter;
private ArrayList<String>Pricelist;
private ArrayAdapter<String> Priceadapter;
private DatabaseReference ref;
private FirebaseDatabase database;
private FoodItemclass fooditem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rice_after_login);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
android.support.v7.app.ActionBar actionBar = getSupportActionBar();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
actionBar.setTitle("Rice");
fooditem = new FoodItemclass();
mlistView = (ListView)findViewById(R.id.listview);
database = FirebaseDatabase.getInstance();
ref = database.getReference("Rice");
list = new ArrayList<>();
Pricelist = new ArrayList<>();
adapter = new ArrayAdapter<String>(this,R.layout.list_item,R.id.ItemNameIds,list);
Priceadapter = new ArrayAdapter<String>(this,R.layout.list_item,R.id.ItemPriceId,Pricelist);
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
fooditem = dataSnapshot.getValue(FoodItemclass.class);
list.add(fooditem.getName());
Pricelist.add(String.valueOf(fooditem.getPrice()));
mlistView.setAdapter(adapter);
mlistView.setAdapter(Priceadapter);
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
you can only set one adapter to your list view so thats why you get the recent assign adapter result
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
fooditem = dataSnapshot.getValue(FoodItemclass.class);
list.add(fooditem.getName()+ " "+String.valueOf(fooditem.getPrice());
mlistView.setAdapter(adapter);
}
NOTE: the space between both name and price value is a separator
Recommend This is a bad approach to do so. you should use RecyclerView to show multiple values
The answer from faiizii has the gist of the problem: you can only have one adapter on a list view, so you should only call setAdapter once. Since onChildAdded will be called for each child, you shouldn't call setAdapter in there (nor in any of the other onChild... methods).
The solution is to move the calls to setAdapter out of the listener:
list = new ArrayList<>();
adapter = new ArrayAdapter<String>(this,R.layout.list_item,R.id.ItemNameIds,list);
mlistView.setAdapter(adapter);
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
fooditem = dataSnapshot.getValue(FoodItemclass.class);
list.add(fooditem.getName()+": "+fooditem.getPrice());
adapter.notifyDataSetChanged();
}
...
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
});
As you'll see we now call notifyDataSetChanged() inside onChildAdded. This lets the adapter know that its data has changed, which in turn then means that it refreshes the list view.
I have an android project where I retrieve data from firebase. everything is working fine but when I delete object in firebase console, it does not reflect back in the app.
Here is the link of the image:
So, suppose I delete david hafiz child node in firebase, it does not delete in the app. I have tried a lot but can't find the correct way. I am new to android programming and I hope somebody can help me. Thank You.
Update
mDatabase = FirebaseDatabase.getInstance();
mReference = mDatabase.getReference().child("Students").child("Marks");
mReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.d("value", "" + dataSnapshot);
fetchData(dataSnapshot);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return view;
}
private void fetchData(DataSnapshot dataSnapshot) {
StudentData value = dataSnapshot.getValue(StudentData.class);
Log.v("StudentData Fragment", "" + dataSnapshot.getValue());
// Get an iterator.
Iterator<StudentData> ite = mMarksList.iterator();
while (ite.hasNext()) {
StudentData iteValue = ite.next();
if (iteValue.equals(value))
ite.remove();
}
mMarksList.add(value);
Collections.sort(mMarksList, new MarksComparator());
String title = mReference.getKey();
// specify an adapter
mAdapter = new MyAdapter(getContext(), mMarksList, title);
mAdapter.notifyDataSetChanged();
mRecyclerView.setAdapter(mAdapter);
}
There are four relevant methods in ``:
onChildAdded
onChildRemoved
onChildChanged
onChildMoved
You only implemented onChildAdded, which is called in two cases:
When you first attach the listener, onChildAdded is called for each existing child.
When a child is later added, onChildAdded is called for that child.
When you delete a node from the Firebase console, the onChildRemoved method is called. But since you left that method empty, your app doesn't do anything when you remove data from the console.
To make your app behave correctly, you'll need to implement onChildRemoved. Typically this involves finding the UI element matching the snapshot and removing it.
You can store keys in order to update or remove it e.g:
ArrayList<String> mKeys = new ArrayList<String>();
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String key = dataSnapshot.getKey();
mKeys.add(key);
adapter.notifyDataSetChanged();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
String key = dataSnapshot.getKey();
int index = mKeys.indexOf(key);
mMarksList.remove(/*index*/); // or data
adapter.notifyDataSetChanged();
}
You might be interested how to update too.
i need to get all data in Childs and show it in ListView
Every Values in Childs!,The main Child is "XXX-Users" and other Childs is about "Model Phones",, i want get All Date of This Childs on ListView
this is my Activity:
public class xxxxxxx extends AppCompatActivity {ListView listView;
ArrayList<String> usernames = new ArrayList<>() ;
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("xxx-Users");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxxxxxxxxxxxx);
listView = (ListView) findViewById(R.id.listview00);
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,usernames);
listView.setAdapter(arrayAdapter);
myRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.getValue(String.class);
usernames.add(value);
arrayAdapter.notifyDataSetChanged();
}
#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) {
}
});
}`**
My Layout
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:id="#+id/listview00" />
As cricket_007 said, your code doesn't match your data structure. Your listener will fire for the nodes immediately under xxx-Users. But your actual URL values are one level deeper.
One simple way to handler this is to loop over those nested children in onChildAdded():
DatabaseReference myRef = database.getReference("xxx-Users");
myRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String value = childSnapshot.getValue(String.class);
usernames.add(value);
}
arrayAdapter.notifyDataSetChanged();
}
...
Im struggling a little with my code. I have searched and tried many methods. My aim is remove the previous entry that Firebase has provided to my app, the firebase data is coming from an embedded device.I want to replace the value in my android app.
Firebase is working ok, The app will display the new value provided by firebase but will not delete the previous entry.
I still have plenty to do but want to fix the basics before moving on.
So basically the OnChildChanged will display new firebase entries, i just want the previous entry deleted from the Android Application when a new value comes in from Firebase.
I have looked into removeValue and setValue with no avail
public class MainActivity extends AppCompatActivity {
DatabaseReference fDatabase;
ListView listview;
ArrayList<String> list = new ArrayList<>();
ArrayAdapter <String> adapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listview);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, list);
listview.setAdapter(adapter);
fDatabase = FirebaseDatabase.getInstance().getReference();
fDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.getValue(String.class);
list.add(value);
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.getValue(String.class);
list.remove(value);
adapter.notifyDataSetChanged();
list.add(value);
adapter.notifyDataSetChanged();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.getValue(String.class);
list.remove(value);
adapter.notifyDataSetChanged();
list.add(value);
adapter.notifyDataSetChanged();
}
Looks like when you assign value it's getting the new entry, so when you call list.remove it isn't removing the old entry since it's actually trying to remove any instance of the new entry.
See if there's any way you can map the old entry to the new entry so the list knows what to remove since the content of value is different between old and new.
I'm using Firebase database and I'm retrieving data from it. When my database has data, addChildEventListener working well but when my database hasn't data, addChildEventListener not working. Bellow, this is my code:
mDatabase = FirebaseDatabase.getInstance().getReference().child("music");
public void getListMusicFromFirebase() {
mDatabase.addChildEventListener(this);
}
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
updateMusic(dataSnapshot);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
updateMusic(dataSnapshot);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
updateMusic(dataSnapshot);
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
private void updateMusic(DataSnapshot dataSnapshot) {
mListMusic.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
String title = snapshot.getValue(Music.class).getTitle();
String artist = snapshot.getValue(Music.class).getArtist();
String year = snapshot.getValue(Music.class).getYear();
String duration = snapshot.getValue(Music.class).getDuration();
String uri = snapshot.getValue(Music.class).getUri();
Music music = new Music(title, artist, year, duration, uri);
mListMusic.add(music);
}
if (mListMusic.size() > 0) {
bindingListMusic();
return;
}
mBinding.tvDataEmpty.setText("No data");
mDialog.dismiss();
}
I check my list. If size of it greater than 0, I will bind it to recyclerview and opposite, I will notify it haven't data, it working well when having data but when I delete all data from Firebase database, my code can't perform updateMusic() method.
Please help.
To initiate your listener you should have the required data in your firebase database. AddChildEvent listener requires a predefined parent where you will attach it on app launch(or whenever you want) . If there is no parent the listener will never be attached or initiated.
This will result in no response when you later add a parent and add childs to it. So, always make sure that the parent to which you adding childEventListener is already present and the value is not null.
Hope this helps.