Retrieve a ListView from Firebase - android

I want to get data from a Firebase database in a list view. When I open the page, it appears as follows:
When I go back and open it again, it now appears like this:
The database contains the following data:
My two problems are:
It takes a lot of time to retrieve the data
More data is retrieved than expected - it is repeated in the listview.
My code:
public class CustomAdapter extends BaseAdapter{
Context c;
ArrayList<Doctor> doctors;
public CustomAdapter(Context c, ArrayList<Doctor> doctors) {
this.c = c;
this.doctors = doctors;
}
#Override
public int getCount() {
return doctors.size();
}
#Override
public Object getItem(int position) {
return doctors.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView==null)
{
convertView= LayoutInflater.from(c).inflate(R.layout.model,parent,false);
}
TextView nameTxt= (TextView) convertView.findViewById(R.id.nameTxt);
TextView propTxt= (TextView) convertView.findViewById(R.id.propellantTxt);
TextView descTxt= (TextView) convertView.findViewById(R.id.descTxt);
final Doctor s= (Doctor) this.getItem(position);
nameTxt.setText(s.getDoctorName());
propTxt.setText(s.getSpecialist());
descTxt.setText(s.getAdress());
//ONITECLICK
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(c,s.getDoctorName(),Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
and this for model class
public class Doctor {
String doctorName,specialist,adress;
public Doctor() {
}
public String getDoctorName() {
return doctorName;
}
public String getSpecialist() {
return specialist;
}
public String getAdress() {
return adress;
}
The Activity:
public class DoctorsActivity extends AppCompatActivity {
DatabaseReference db;
FirebaseHelper helper;
CustomAdapter adapter;
ListView lv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_doctors);
lv = (ListView) findViewById(R.id.lv);
db = FirebaseDatabase.getInstance().getReference().child("Doctor");
helper = new FirebaseHelper(db);
adapter = new CustomAdapter(this, helper.retrieve());
lv.setAdapter(adapter);
}
Firebase Helper:
public class FirebaseHelper {
DatabaseReference db;
Boolean saved;
ArrayList<Doctor> doctors = new ArrayList<>();
public FirebaseHelper(DatabaseReference db) {
this.db = db;
}
//IMPLEMENT FETCH DATA AND FILL ARRAYLIST
private void fetchData(DataSnapshot dataSnapshot) {
doctors.clear();
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Doctor doctor = dataSnapshot.getValue(Doctor.class);
doctors.add(doctor);
}
}
//RETRIEVE
public ArrayList<Doctor> retrieve() {
db.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
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 doctors;
}

Related

how to retrive data from getters in another activity in android

I am creating an android app in which I store in firebase and show a list with subitems in one activity and access that list in another activity by clicking a button. I have stored and showed the data in firebase and in my first activity, but I can't fetch that list in the other activity.
My code:-
Main Activity:-
public class MainActivity extends AppCompatActivity {
EditText getName, getNum;
Button btn,btnNext;
TextView textView;
ListView listView;
DatabaseReference fb;
List<Contact> contactList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getName = findViewById(R.id.ed1);
getNum = findViewById(R.id.ed2);
textView = findViewById(R.id.text);
btn = findViewById(R.id.btn);
btnNext = findViewById(R.id.btnNext);
listView = findViewById(R.id.listView);
fb = FirebaseDatabase.getInstance().getReference("Contacts");
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
finish();
}
});
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addContacts();
}
});
fb.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Contact contact = dataSnapshot.getValue(Contact.class);
contactList.add(contact);
listadapter list = new listadapter(MainActivity.this,contactList);
listView.setAdapter(list);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
notify();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
public void addContacts() {
String name = getName.getText().toString();
String num = getNum.getText().toString();
String id = fb.push().getKey();
Contact contact = new Contact(name,num);
fb.child(id).setValue(contact);
}
}
Contact getters class
public class Contact {
String contact;
String name;
public Contact() { }
public Contact(String name, String contact) {
this.name = name;
this.contact = contact;
}
public String getName() {
return name;
}
public String getContact() {
return contact;
}
}
custom adapter class
public class listadapter extends ArrayAdapter<Contact> {
private Activity context;
private List<Contact> contactList;
public listadapter(Activity context, List<Contact> contactList) {
super(context,R.layout.list,contactList);
this.context = context;
this.contactList = contactList;
}
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View listViewItem = inflater.inflate(R.layout.list, null, true);
TextView textViewName = listViewItem.findViewById(R.id.name);
TextView textViewContact = listViewItem.findViewById(R.id.num);
Contact contact = contactList.get(position);
textViewName.setText(contact.getName());
textViewContact.setText(contact.getContact());
return listViewItem;
}
}
Activity in which i'm trying to fetch
public class Main2Activity extends AppCompatActivity {
Button getSub;
List<Contact> list = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
getSub = findViewById(R.id.getSub);
getSub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(),"Num : "+list.get(0).getContact(),Toast.LENGTH_LONG).show();
}
});
}
}
Solution:- I fetched the list directly from firebase and it works
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
call = findViewById(R.id.call);
db = FirebaseDatabase.getInstance().getReference("Trusted contacts");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
msgAll();
for(int i=0;i<ex.size();i++) {
getNum = "tel: "+ex.get(i).getmText2();
callAll(getNum);
}
}
}, 500);
}
#Override
protected void onStart() {
super.onStart();
db.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
ExampleItem contact = dataSnapshot.getValue(ExampleItem.class);
ex.add(contact);
}
#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) {
}
});
}
In Main2Activity you have created the reference variable list as new ArrayList<>() but you have never added anything to it.
If you want to be able to access the data, you'll need to either pass it from one Actvity to another, or store a reference to it in a static variable that you can access from both classes.

Firebase not writing to expected child, updating it on next child in Android

Tried answers found on the internet, actually there is no change to the code as it seem correct but can't find where is the error.
My Input Parameters:
JSON RETURNED:
(I expected a "clocation" child and value but it won't even write that to the tree. Plus, the value of clocation is written to cbudget)
Project Class:
public class Project {
String ctitle, cdetail, clocation, cbudget;
public Project() {
}
public String getCtitle() {
return ctitle;
}
public void setCtitle(String ctitle) {
this.ctitle = ctitle;
}
public String getCdetail() {
return cdetail;
}
public void setCdetail(String cdetail) {
this.cdetail = cdetail;
}
public String getClocation() {
return clocation;
}
public void setClocation(String clocation) {
this.clocation = clocation;
}
public String getCbudget() {
return cbudget;
}
public void setCbudget(String cbudget) {
this.cbudget = cbudget;
}
MyViewHolder
public MyViewHolder(View itemView) {
super(itemView);
titleTxt = (TextView) itemView.findViewById(R.id.titleTxt);
detailTxt = (TextView) itemView.findViewById(R.id.detailTxt);
locationTxt = (TextView) itemView.findViewById(R.id.locationTxt);
budgetTxt = (TextView) itemView.findViewById(R.id.budgetTxt);
itemView.setOnClickListener(this);
}
MyAdapter
public MyAdapter(Context c, ArrayList<Project> projects) {
this.c = c;
this.projects = projects;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(c).inflate(R.layout.model,parent,false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final Project s = projects.get(position);
holder.titleTxt.setText(s.getCtitle());
holder.detailTxt.setText(s.getCdetail());
holder.locationTxt.setText(s.getClocation());
holder.budgetTxt.setText(s.getCbudget());
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onItemClick(int pos) {
//OPEN DETAIL ACTIVITY
openDetailActivity(s.getCtitle(),s.getCdetail(),s.getClocation(),s.getCbudget());
}
});
}
#Override
public int getItemCount() {
return projects.size();
}
//OPEN DETAIL ACTIVITY
private void openDetailActivity(String...details)
{
Intent i=new Intent(c,DetailActivity.class);
i.putExtra("TITLE_KEY",details[0]);
i.putExtra("DETAIL_KEY",details[1]);
i.putExtra("LOCATION_KEY",details[2]);
i.putExtra("BUDGET_KEY",details[3]);
c.startActivity(i);
}
FirebaseHelper
public class FirebaseHelper {
DatabaseReference db;
Boolean saved = null;
ArrayList<Project> projects=new ArrayList<>();
public FirebaseHelper(DatabaseReference db) {
this.db = db;
}
//WRITE IF NOT NULL
public Boolean save(Project project)
{
if(project==null)
{
saved=false;
}
else
{
try
{
db.child("Project").push().setValue(project);
saved=true;
}catch (DatabaseException e)
{
e.printStackTrace();
saved=false;
}
}
return saved;
}
//IMPLEMENT FETCH DATA AND FILL ARRAYLIST
private void fetchData(DataSnapshot dataSnapshot)
{
projects.clear();
for (DataSnapshot ds : dataSnapshot.getChildren())
{
Project project = ds.getValue(Project.class);
projects.add(project);
}
}
//READ THEN RETURN ARRAYLIST
public ArrayList<Project> retrieve() {
db.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
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 projects;
}
}
Receive and Bind Data:
//RECEIVE DATA
String title = i.getExtras().getString("TITLE_KEY");
String detail = i.getExtras().getString("DETAIL_KEY");
String location = i.getExtras().getString("LOCATION_KEY");
String budget = i.getExtras().getString("BUDGET_KEY");
//BIND DATA
titleTxt.setText(title);
detailTxt.setText(detail);
locationTxt.setText(location);
budgetTxt.setText(budget);
The problem in your code is that you are declaring the ArrayList<Project> projects=new ArrayList<>(); outside onChildAdded() and onChildChanged() methods. This means that your projects ArrayList is null, due the asyncronious behaviour of those methods, which are called before even you add those objects to the list.
To solve this, you need to declare that ArrayList inside fetchData() method right before that for loop.
This change will solve your problem.

How can I get data properly from firebase database?

I am developing application which keeps user expenses, I wrote CustomAdapter
public class CustomAdapter extends BaseAdapter{
Context c;
ArrayList<Income> incomes;
public CustomAdapter(){}
public CustomAdapter(Context c,ArrayList<Income> incomes){
this.incomes=incomes;
this.c=c;
}
#Override
public int getCount() {
return incomes.size();
}
#Override
public Object getItem(int position) {
return incomes.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView==null){
convertView= LayoutInflater.from(c).inflate(R.layout.model,parent,false);
}
TextView nameTxt= (TextView) convertView.findViewById(R.id.nameTxt);
TextView propTxt= (TextView) convertView.findViewById(R.id.aciklama);
TextView descTxt= (TextView) convertView.findViewById(R.id.descTxt);
Income s= (Income) this.getItem(position);
nameTxt.setText(s.getName());
propTxt.setText(s.getType());
descTxt.setText((String.valueOf(s.getMiktar())));
return convertView;
}
and implemented on the activity
public class ExpenseActivity extends Activity{
DatabaseReference db;
FloatingActionButton fab;
ExpenseAdapter adapter;
ListView lv;
Boolean saved;
EditText nameEditTxt, propTxt, descTxt;
ArrayList<Expense> expenselist = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.expense_content);
//Toolbar toolbar=(Toolbar)findViewById(R.id.toolbar);
// setSupportActionBar(toolbar);
lv = (ListView) findViewById(R.id.listview);
db = FirebaseDatabase.getInstance().getReference();
//isa
adapter = new ExpenseAdapter(ExpenseActivity.this, getExpenses());
lv.setAdapter(adapter);
adapter.notifyDataSetChanged();
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
displayInput();
}
});
}
public Boolean save(Expense expense){
if(expense==null){
saved=false;
}else{
try{
db.child("Expense").push().setValue(expense);
saved=true;
}catch (Exception ex){
ex.printStackTrace();;
saved=false;
}
}
return saved;
}
public void fetchData(DataSnapshot dataSnapshot)
{
expenselist.clear();
for (DataSnapshot ds : dataSnapshot.getChildren())
{
Expense expense=ds.getValue(Expense.class);
expenselist.add(expense);
adapter.notifyDataSetChanged();
}
}
public ArrayList<Expense> getExpenses(){
db.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
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 expenselist;
}
private void displayInput() {
final Dialog d=new Dialog(this);
d.setTitle("Gelir Girin");
d.setContentView(R.layout.expense_layout);
nameEditTxt = (EditText) d.findViewById(R.id.name);
propTxt = (EditText) d.findViewById(R.id.kategori);
descTxt = (EditText) d.findViewById(R.id.miktar);
Button saveBtn = (Button) d.findViewById(R.id.saveBtn);
saveBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name = nameEditTxt.getText().toString();
String type = propTxt.getText().toString();
String amount= String.valueOf(descTxt.getText().toString());
Expense expense=new Expense(name,type,amount);
if (name != null && name.length() > 0) {
//THEN SAVE
if (save(expense)) {
//IF SAVED CLEAR EDITXT
d.cancel();
nameEditTxt.setText("");
propTxt.setText("");
descTxt.setText("");
}
} else {
Toast.makeText(ExpenseActivity.this, "Name Must Not Be Empty", Toast.LENGTH_SHORT).show();
}
}
});
d.show();
}
but even I have some data saved in firebase it returns null and passes null to fields(textview) at first but when I add new item it show existing data in the Firebase. One of my friend said that I am calling data asnychronously but I didn't understand it.I want to data be shown directly whenever activity is opened. Any help is appreciated,Thanks
When I open activity:
After I add new data:
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
fetchdata();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This will fetch appropriate data
Your problem is that your are initializing your adapter before fetching the data from the db.
adapter = new ExpenseAdapter(ExpenseActivity.this, getExpenses());
The getExpenses() method is performing an asynchronous operation
Try passing instead the list directly and call the getExpenses method as well
adapter = new ExpenseAdapter(ExpenseActivity.this, expenselist);
getExpenses()
Then when the notifyDatasetChanged is called in the fetchData method it will update the list.

Android - Update and delete data in Firebase database

I'm trying to update and delete data in Firebase database.
SectionDetails model
public class SectionDetails {
private String sectionCode;
private String sectionSeats;
private String sectionKey;
public SectionDetails() {
}
public SectionDetails(String sectionCode, String sectionSeats) {
this.sectionCode = sectionCode;
this.sectionSeats = sectionSeats;
}
#Exclude
public String getSectionKey() {
return sectionKey;
}
public String getSectionCode() {
return sectionCode;
}
public String getSectionSeats() {
return sectionSeats;
}
}
FirebaseHelper class
public class FirebaseHelper {
DatabaseReference db;
ArrayList<SectionDetails> sectionDetailsArrayList = new ArrayList<>();
public FirebaseHelper(DatabaseReference db) {
this.db = db;
}
private void fetchData(DataSnapshot dataSnapshot) {
SectionDetails sectionDetails = dataSnapshot.getValue(SectionDetails.class);
sectionDetailsArrayList.add(sectionDetails);
adapter.notifyDataSetChanged();
}
public ArrayList<SectionDetails> retrieve() {
db.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
adapter.notifyDataSetChanged();
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return sectionDetailsArrayList;
}
}
CustomAdapter class
public class CustomAdapter extends BaseAdapter {
DatabaseReference updateRef;
String key;
Context c;
ArrayList<SectionDetails> sectionDetailsArrayList;
public CustomAdapter(Context c, ArrayList<SectionDetails> sectionDetailsArrayList) {
this.c = c;
this.sectionDetailsArrayList = sectionDetailsArrayList;
}
#Override
public int getCount() {
return sectionDetailsArrayList.size();
}
#Override
public Object getItem(int position) {
return sectionDetailsArrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final SectionDetails sd = (SectionDetails) this.getItem(position);
updateRef = FirebaseDatabase.getInstance().getReference().child(Constants.FIREBASE_COURSES).child("sections");
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Dialog d = new Dialog(CustomAdapter.this);
d.setContentView(R.layout.section_custom_dialog);
Button btnUpdate = (Button) d.findViewById(R.id.btnUpdate);
Button btnDelete = (Button) d.findViewById(R.id.btnDelete);
btnUpdate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String code = "1B";
final String seats = "20";
updateRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
SectionDetails updateSD = snapshot.getValue(SectionDetails.class);
if (sd.getSectionCode().equals(updateSD.getSectionCode())) {
key = snapshot.getKey().toString();
}
}
SectionDetails newSD = new SectionDetails(code, seats);
updateRef.child(key).setValue(newSD);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
btnDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
SectionDetails deleteSD = snapshot.getValue(SectionDetails.class);
if (sd.getSectionCode().equals(deleteSD.getSectionCode())) {
updateSectionRef.child(snapshot.getKey().toString()).removeValue();
break;
}
}
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
d.show();
}
});
return convertView;
}
}
MainActivity class
public class MainActivity extends AppCompatActivity {
DatabaseReference mRef;
FirebaseHelper helper;
CustomAdapter adapter;
ListView lvSectionsListOne;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvSectionsListOne = (ListView) findViewById(R.id.lvSectionsList);
mRef = FirebaseDatabase.getInstance().getReference().child(Constants.FIREBASE_COURSES).child("sections");
helper = new FirebaseHelper(mRef);
adapter = new CustomAdapter(this, helper.retrieve());
lvSectionsListOne.setAdapter(adapter);
}
}
The data is deleted from database as expected, but the data that gets deleted remains inside the listview. I added adapter.notifyDataSetChanged() but still the listview is not updating.
The data is also updated as expected, but when update button is clicked, the data is updated infinitely. I can see the listview as well as the database keep on appending the data, and can only be stopped by closing the app.
I have tried to move SectionDetails newSD = new SectionDetails(code, seats) and updateRef.child(key).setValue(newSD) to outside for loop but the data doesn't get updated because the key is not passed to the path outside the for loop.
I haven't thoroughly looked at all the code you posted and may not understand your processing completely. There are two things that might be causing some of the problems you described.
In FirebaseHelper, method onChildChanged() calls fetchData(), which adds the changed section details to the array list. Shouldn't you be updating the existing section details instead of adding them again? Also, in onChildRemoved(), the section details are not removed from the array list. Don't they need to be removed?
In CustomAdapter the click listeners for your buttons add anonymous ValueEventListeners. Because they are anonymous, you have no way of removing them when they are no longer needed. ValueEventListeners added with addValueEventListener() remain active until removed. If your goal is to get the data once, use addListenerForSingleValueEvent().

Android - Display data in ListView from Firebase database

I have a custom listview to display data from Firebase database.
SectionDetails model
public class SectionDetails {
private String sectionCode;
private String sectionSeats;
public SectionDetails() {
}
public SectionDetails(String sectionCode, String sectionSeats) {
this.sectionCode = sectionCode;
this.sectionSeats = sectionSeats;
}
public String getSectionCode() {
return sectionCode;
}
public String getSectionSeats() {
return sectionSeats;
}
public void setSectionCode(String sectionCode) {
this.sectionCode = sectionCode;
}
public void setSectionSeats(String sectionSeats) {
this.sectionSeats = sectionSeats;
}
}
FirebaseHelper class
public class FirebaseHelper {
DatabaseReference db;
Boolean saved;
ArrayList<SectionDetails> sectionDetailsArrayList = new ArrayList<>();
public FirebaseHelper(DatabaseReference db) {
this.db = db;
}
public Boolean save(SectionDetails sectionDetails) {
if (sectionDetails == null) {
saved = false;
} else {
try {
db.push().setValue(sectionDetails);
saved = true;
adapter.notifyDataSetChanged();
} catch(DatabaseException e) {
e.printStackTrace();
saved = false;
}
}
return saved;
}
private void fetchData(DataSnapshot dataSnapshot) {
sectionDetailsArrayList.clear();
SectionDetails sectionDetails = dataSnapshot.getValue(SectionDetails.class);
sectionDetailsArrayList.add(sectionDetails);
}
public ArrayList<SectionDetails> retrieve() {
db.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
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 sectionDetailsArrayList;
}
}
CustomAdapter class
public class CustomAdapter extends BaseAdapter {
Context c;
ArrayList<SectionDetails> sectionDetailsArrayList;
public CustomAdapter(Context c, ArrayList<SectionDetails> sectionDetailsArrayList) {
this.c = c;
this.sectionDetailsArrayList = sectionDetailsArrayList;
}
#Override
public int getCount() {
return sectionDetailsArrayList.size();
}
#Override
public Object getItem(int position) {
return sectionDetailsArrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(c).inflate(R.layout.sections_custom_listview, parent, false);
}
TextView lvTvSectionCode = (TextView) convertView.findViewById(R.id.lvTvSectionCode);
TextView lvTvSectionSeats = (TextView) convertView.findViewById(R.id.lvTvSectionSeats);
final SectionDetails sd = (SectionDetails) this.getItem(position);
lvTvSectionCode.setText(sd.getSectionCode());
lvTvSectionSeats.setText("allocated seats: " + sd.getSectionSeats());
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(c, sd.getSectionCode(), Toast.LENGTH_LONG).show();
}
});
return convertView;
}
}
MainActivity class
public class AddSection extends AppCompatActivity implements View.OnClickListener {
DatabaseReference mRef;
FirebaseHelper helper;
CustomAdapter adapter;
Button btnCreateSection;
ListView lvSectionsListOne;
String getFullSection, seats;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_section);
lvSectionsListOne = (ListView) findViewById(R.id.lvSectionsList);
mRef = FirebaseDatabase.getInstance().getReference().child(Constants.FIREBASE_COURSES).child("sections");
helper = new FirebaseHelper(mRef);
adapter = new CustomAdapter(this, helper.retrieve());
lvSectionsListOne.setAdapter(adapter);
btnCreateSection = (Button) findViewById(R.id.btnCreateSection);
btnCreateSection.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v == btnCreateSection) {
getFullSection = "section 1A";
seats = "20";
SectionDetails sectionDetails = new SectionDetails(getFullSection, seats);
if (helper.save(sectionDetails)) {
adapter = new CustomAdapter(AddSection.this, helper.retrieve());
lvSectionsListOne.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
}
}
I posted a similar question here, but this problem is different. When first data is added, nothing is shown in the listview. When second data is added, first data is shown in listview. And when third data is added, first data is replaced by second data, and second data is shown in listview. I have tried adding adapter.notifyDataSetChanged(), but still the same result.
Data is retrieved (and synchronized) from the Firebase Database to your app asynchronously. This means that your sectionDetailsArrayList may be modified at any time. When you modify the data, you need to tell the adapter about it, so that it can update the view.
private void fetchData(DataSnapshot dataSnapshot) {
sectionDetailsArrayList.clear();
SectionDetails sectionDetails = dataSnapshot.getValue(SectionDetails.class);
sectionDetailsArrayList.add(sectionDetails);
// tell the adapter that we changed its data
adapter.notifyDataSetChanged();
}
This should update the view. But since you clear out the list for every child that gets added or changed, the app will only show the latest added/modified item.
Setting up a synchronized array in Firebase is somewhat involved, since you have to deal with all event types and with the fact that evens can happen in any order. For that reason we create the FirebaseUI library, which contains adapters from the Firebase Database to a ListView and RecyclerView.

Categories

Resources