In my LogCat I have these details which were pulled up from my firebase database.
06-05 16:14:09.454 D: 3. DataSnapshot VALUE : {familyName=Richardson, children=[Sam, Jin, Peter], fatherName=Daniel, checkInTime=Mon, Jun 05 04:13 PM}
06-05 16:14:09.456 D: 4. DataSnapshot VALUE : {motherName=Alice, checkOutTime=Mon, Jun 05 04:13 PM, familyName=Richardson, children=[Sam, Peter, Jin]}
I used multi-column ListView for displaying the below data. But, the problem here is I'm unable to display the children data as it is an ArrayList. Only the last value of the ArrayList is getting displayed in Children column.
How can I display all the values of an ArrayList in a multi column ListView. Can anyone suggest me?
This is my code:
checkInCheckOutDBReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int i = 0;
for (DataSnapshot ds: dataSnapshot.getChildren()) {
i++;
String fatherNameValue = ds.child("fatherName").getValue(String.class);
String motherNameValue = ds.child("motherName").getValue(String.class);
HashMap < String, String > record = new HashMap < > ();
Log.d(TAG, i + ". DataSnapshot VALUE : " + ds.getValue());
familyNameColumn = ds.child("familyName").getValue(String.class);
record.put(FAMILY_NAME_COLUMN, familyNameColumn);
for (DataSnapshot cds: ds.child("children").getChildren()) {
record.put(CHILD_NAME_COLUMN, cds.getValue().toString());
}
// CHECK IN TIME
checkInTime = ds.child("checkInTime").getValue(String.class);
record.put(CHECKIN_COLUMN, checkInTime);
// CHECKOUT TIME
checkOutTime = ds.child("checkOutTime").getValue(String.class);
record.put(CHECKOUT_COLUMN, checkOutTime);
for (DataSnapshot snap: ds.getChildren()) {
Log.d(TAG, "*Key: " + snap.getKey());
if (snap.getKey().equals("checkInTime")) {
myCheckIn = "1";
myCheckOut = "0";
}
if (snap.getKey().equals("checkOutTime")) {
myCheckOut = "1";
myCheckIn = "0";
}
if (snap.getKey().equals("fatherName")) {
myParent = fatherNameValue;
}
if (snap.getKey().equals("motherName"))
myParent = motherNameValue;
}
if (myCheckIn.equals("1")) {
record.put(PARENT_CHECKIN_COLUMN, myParent);
}
if (myCheckOut.equals("1")) {
record.put(PARENT_CHECKOUT_COLUMN, myParent);
}
list.add(record);
ReportAdapter adapter = new ReportAdapter(GeneratereportActivity.this, list);
reportListView.setAdapter(adapter);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
Put your adapter code outside your for loop,and also create new object for the variable record
ReportAdapter adapter = new ReportAdapter(GeneratereportActivity.this, list);
reportListView.setAdapter(adapter);
like this otherwise, every time the object will overwrite and you will only last value
checkInCheckOutDBReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int i = 0;
for (DataSnapshot ds: dataSnapshot.getChildren()) {
i++;
record = new //your object
String fatherNameValue = ds.child("fatherName").getValue(String.class);
String motherNameValue = ds.child("motherName").getValue(String.class);
HashMap < String, String > record = new HashMap < > ();
Log.d(TAG, i + ". DataSnapshot VALUE : " + ds.getValue());
familyNameColumn = ds.child("familyName").getValue(String.class);
record.put(FAMILY_NAME_COLUMN, familyNameColumn);
for (DataSnapshot cds: ds.child("children").getChildren()) {
record.put(CHILD_NAME_COLUMN, cds.getValue().toString());
}
// CHECK IN TIME
checkInTime = ds.child("checkInTime").getValue(String.class);
record.put(CHECKIN_COLUMN, checkInTime);
// CHECKOUT TIME
checkOutTime = ds.child("checkOutTime").getValue(String.class);
record.put(CHECKOUT_COLUMN, checkOutTime);
for (DataSnapshot snap: ds.getChildren()) {
Log.d(TAG, "*Key: " + snap.getKey());
if (snap.getKey().equals("checkInTime")) {
myCheckIn = "1";
myCheckOut = "0";
}
if (snap.getKey().equals("checkOutTime")) {
myCheckOut = "1";
myCheckIn = "0";
}
if (snap.getKey().equals("fatherName")) {
myParent = fatherNameValue;
}
if (snap.getKey().equals("motherName"))
myParent = motherNameValue;
}
if (myCheckIn.equals("1")) {
record.put(PARENT_CHECKIN_COLUMN, myParent);
}
if (myCheckOut.equals("1")) {
record.put(PARENT_CHECKOUT_COLUMN, myParent);
}
list.add(record);
}
ReportAdapter adapter = new ReportAdapter(GeneratereportActivity.this, list);
reportListView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
Related
I want to get list of LatLng from Firebase database. Previously, I've insert Polygon list by this code, mMarkerPoints.add(new LatLng(latitude, longitude)); and by this databaseReference.child("Area").child(pushId).child("region").setValue(mMarkerPoints); the databse sturcture as,
Now, I want to get this mMarkerPoints from database. for this, I wrote code, List<LatLng> areaRegion = (ArrayList) dataSnapshot.child(key).child("region").getValue();, this code give me exception. How to get this list?
code:
databaseReference.child("Area").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
String key = dataSnapshot1.child(dataSnapshot1.getKey()).getKey();
String areaName = dataSnapshot.child(key).child("name").getValue(String.class);
List<LatLng> areaRegion = (ArrayList<LatLng>) dataSnapshot.child(key).child("region").getValue();
for(int i = 0; i<values.size();i++) {
Log.d("sdfljdjw", values.get(i));
}
Little bit solution:
i got this result {longitude=71.43064320087433, latitude=32.392359285468686} by this code:
Object value = dataSnapshot.child(key).child("region").getValue();
if(value instanceof List) {
List<Object> sdfsd = (List<Object>) value;
for(int i = 0; i<sdfsd.size();i++) {
Log.d("sdfljdjw", sdfsd.get(i)+"");
}
}
else {
Log.d("sdfljdjw", "no");
}
now how to convert this values to LatLng object?
10-10 14:20:30.539
11935-11935/com.example.salesman.salesmantrackingsystem
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.ClassCastException: java.util.HashMap cannot be cast to com.google.android.gms.maps.model.LatLng
at com.example.salesman.salesmantrackingsystem.LoginActivity$1$1$1$1.onDataChange(LoginActivity.java:154)
at com.google.android.gms.internal.zzegf.zza(Unknown Source)
at com.google.android.gms.internal.zzeia.zzbyc(Unknown Source)
at com.google.android.gms.internal.zzeig.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5086)
At a guess (untested), replace:
List<LatLng> areaRegion = (ArrayList<LatLng>) dataSnapshot.child(key).child("region").getValue();
with something like:
List<LatLng> areaRegion = new ArrayList<>();
List<Object> locations = (List<Object>) dataSnapshot.child(key).child("region").getValue();
for (Object locationObj : locations) {
Map<String, Object> location = (Map<String, Object>) locationObj;
LatLng latLng = new LatLng((Double) location.get("latitude")), (Double) location.get("longitude"));
areaRegion.add(latLng);
}
Try something like this
Map<String, Object> td = (HashMap<String,Object>) dataSnapshot.getValue();
List<Object> values = td.values();
2 examples: first example read one object (defined key "clave2") from hashmap( String,Alumno) and second example read all objects from hashmap(String,Alumno) (valid for HashMap/List)
DatabaseReference myRefalumnos1 = database.getReference("alumnoshashmap");
myRefalumnos1.child("clave2").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
Alumno value = dataSnapshot.getValue(Alumno.class);
System.out.println(value.toString());
Log.i( "firebase1", value.toString());
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.i( "firebase1", String.valueOf(error.toException()));
}
});
DatabaseReference myRefalumnos2 = database.getReference("alumnoshashmap");
myRefalumnos2.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
List<String> keys = new ArrayList<String>();
List<Alumno> alumnos = new ArrayList<Alumno>();
for (DataSnapshot keynode : snapshot.getChildren()) {
keys.add(keynode.getKey());
alumnos.add(keynode.getValue(Alumno.class));
}
for (String k : keys) {
System.out.println(k);
Log.i("firebase1", "clave leida " + k);
}
for (Alumno a : alumnos) {
System.out.println(a.toString());
Log.i("firebase1", "alumno leido " + a.toString());
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.i( "firebase1", String.valueOf(error.toException()));
}
});
I don't remember what I am doing wrong because I have fixed this before.
What I am trying to do is retrieve the job post data from firebase and put it in my listview but when I do that, the job posts have duplicates. Any Idea on how to fix this?
I'll add the logs and code below.
here are the logs, I keep count of the logs with a log in the script "getting jobs count first count"
05-28 20:24:06.391 17592-17592/test.com.jobTestApp D/FindWorkFragment: getPhotos: getting photos
getPhotos: getting jobs count first count = 0
05-28 20:24:06.772 17592-17592/test.com.jobTestApp D/FindWorkFragment: onDataChange: getJOBS {job_headline=Website, date_posted=yesterday, user_country=United States, time_frame= 7 days, job_desc=Hello, fullname=Tom, category=Web Development, budget=30}
onDataChange: jobs count = 1
onDataChange: getJOBS {job_headline=Website, date_posted=today, user_country=United States, user_id=QkGIMPFXDoPfpnwnPileLRtyR243, time_frame=6 days, job_desc=stuff, fullname=Odi Ohn, category=Web Development, budget=24}
onDataChange: jobs count = 2
05-28 20:24:06.773 17592-17592/test.com.jobTestApp D/FindWorkFragment: onDataChange: getJOBS {job_headline=Website, date_posted=yesterday, user_country=United States, time_frame= 7 days, job_desc=Hello, fullname=Tom, category=Web Development, budget=30}
onDataChange: jobs count = 3
onDataChange: getJOBS {job_headline=Website, date_posted=today, user_country=United States, user_id=QkGIMPFXDoPfpnwnPileLRtyR243, time_frame=6 days, job_desc=stuff, fullname=Odi Ohn, category=Web Development, budget=24}
onDataChange: jobs count = 4
05-28 20:24:06.776 17592-17592/test.com.jobTestApp D/FindWorkFragment: onDataChange: jobs count = 4
Here is the code :
public class FindWorkFragment extends Fragment implements AdapterView.OnItemSelectedListener{
private static final String TAG = "FindWorkFragment";
private ImageView btnBack;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference myRef;
private ArrayList<PostJob> mJobs;
private ArrayList<PostJob> mPaginatedPhotos;
private ArrayList<String> mJobsinCat;
private ListView mListView;
private JobFeedListAdapter mAdapter;
private int mResults;
private Spinner mSearchCat;
private String searchCat;
private ArrayAdapter<CharSequence> mSearchCategoryAdapter;
public static FindWorkFragment newInstance(int instance) {
Bundle args = new Bundle();
args.putInt("argsInstance", instance);
FindWorkFragment thirdFragment = new FindWorkFragment();
thirdFragment.setArguments(args);
return thirdFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_findwork, container, false);
final Fragment fragment = new FindWorkFragment();
mFirebaseDatabase = FirebaseDatabase.getInstance();
myRef = mFirebaseDatabase.getReference();
btnBack = (ImageView) view.findViewById(R.id.iv_back);
mSearchCat = (Spinner) view.findViewById(R.id.spSearchCat);
mSearchCategoryAdapter = ArrayAdapter.createFromResource(getActivity(), R.array.job_categories, android.R.layout.simple_spinner_item);
mSearchCategoryAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSearchCat.setAdapter(mSearchCategoryAdapter);
mSearchCat.setOnItemSelectedListener(this);
mListView = (ListView) view.findViewById(R.id.joblistview);
mJobsinCat = new ArrayList<>();
mJobs = new ArrayList<>();
getJobsinCat();
btnBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.main_frag_container, new HomeDashboardFragment());
ft.commit();
}
});
return view;
}
private void getJobsinCat(){
Log.d(TAG, "getFollowing: searching for following");
String key = myRef.child("Web Development").push().getKey();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference
.child(getString(R.string.dbname_jobs))
.child("United States")
.child("Web Development");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
Log.d(TAG, "onDataChange: found user: " +
singleSnapshot.getKey());
mJobsinCat.add(singleSnapshot.getKey().toString());
}
//mJobsinCat.add(FirebaseAuth.getInstance().getCurrentUser().getUid());
//get the photos
getPhotos();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void getPhotos(){
Log.d(TAG, "getPhotos: getting photos");
Log.d(TAG, "getPhotos: getting jobs count first count = " + mJobs.size() );
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
for(int i = 0; i < mJobsinCat.size(); i++){
final int count = i;
Query query = reference
.child(getString(R.string.dbname_jobs))
.child("United States")
.child("Web Development")
.orderByKey();
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
PostJob job = new PostJob();
Log.d(TAG, "onDataChange: getJOBS " + singleSnapshot.getValue());
Map<String, Object> objectMap = (HashMap<String, Object>) singleSnapshot.getValue();
//job.setUser_country(objectMap.get("user_country").toString());
job.setJob_headline(objectMap.get("job_headline").toString());
job.setJob_desc(objectMap.get("job_desc").toString());
job.setBudget(objectMap.get("budget").toString());
job.setTime_frame(objectMap.get("time_frame").toString());
//job.setTags(objectMap.get(getString(R.string.field_tags)).toString());
//job.setPhoto_id(objectMap.get(getString(R.string.field_photo_id)).toString());
//job.setUser_id(objectMap.get(getString(R.string.field_user_id)).toString());
//job.setDate_posted(objectMap.get("date_posted").toString());
//job.setImage_path(objectMap.get(getString(R.string.field_image_path)).toString());
/*
// soon going to be the proposals
ArrayList<Comment> comments = new ArrayList<Comment>();
for (DataSnapshot dSnapshot : singleSnapshot
.child(getString(R.string.field_comments)).getChildren()){
Comment comment = new Comment();
comment.setUser_id(dSnapshot.getValue(Comment.class).getUser_id());
comment.setComment(dSnapshot.getValue(Comment.class).getComment());
comment.setDate_created(dSnapshot.getValue(Comment.class).getDate_created());
comments.add(comment);
}
photo.setComments(comments);*/
mJobs.add(job);
}
if(count >= mJobsinCat.size() -1){
//display our photos
displayPhotos();
Log.d(TAG, "onDataChange: jobs count = " + mJobs.size());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
private void displayPhotos(){
mPaginatedPhotos = new ArrayList<>();
if(mJobs != null){
try{
/*
Collections.sort(mJobs, new Comparator<PostJob>() {
#Override
public int compare(PostJob o1, PostJob o2) {
return o2.getDate_posted().compareTo(o1.getDate_posted());
}
});*/
int iterations = mJobs.size();
if(iterations > 10){
iterations = 10;
}
mResults = 10;
for(int i = 0; i < iterations; i++){
mPaginatedPhotos.add(mJobs.get(i));
}
mAdapter = new JobFeedListAdapter(getActivity(), R.layout.layout_jobfeed_listitem, mPaginatedPhotos);
mListView.setAdapter(mAdapter);
}catch (NullPointerException e){
Log.e(TAG, "displayPhotos: NullPointerException: " + e.getMessage() );
}catch (IndexOutOfBoundsException e){
Log.e(TAG, "displayPhotos: IndexOutOfBoundsException: " + e.getMessage() );
}
}
}
public void displayMorePhotos(){
Log.d(TAG, "displayMorePhotos: displaying more photos");
try{
if(mJobs.size() > mResults && mJobs.size() > 0){
int iterations;
if(mJobs.size() > (mResults + 10)){
Log.d(TAG, "displayMorePhotos: there are greater than 10 more photos");
iterations = 10;
}else{
Log.d(TAG, "displayMorePhotos: there is less than 10 more photos");
iterations = mJobs.size() - mResults;
}
//add the new photos to the paginated results
for(int i = mResults; i < mResults + iterations; i++){
mPaginatedPhotos.add(mJobs.get(i));
}
mResults = mResults + iterations;
mAdapter.notifyDataSetChanged();
}
}catch (NullPointerException e){
Log.e(TAG, "displayPhotos: NullPointerException: " + e.getMessage() );
}catch (IndexOutOfBoundsException e){
Log.e(TAG, "displayPhotos: IndexOutOfBoundsException: " + e.getMessage() );
}
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
searchCat = parent.getItemAtPosition(position).toString();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
See the getPhotos() you have added query.addListenerForSingleValueEvent in for loop so it will executed multiple time based on mJobsinCat.size(),pull it out from loop for call it single time
private void getPhotos(){
Log.d(TAG, "getPhotos: getting photos");
Log.d(TAG, "getPhotos: getting jobs count first count = " + mJobs.size() );
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference
.child(getString(R.string.dbname_jobs))
.child("United States")
.child("Web Development")
.orderByKey();
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
PostJob job = new PostJob();
Log.d(TAG, "onDataChange: getJOBS " + singleSnapshot.getValue());
Map<String, Object> objectMap = (HashMap<String, Object>) singleSnapshot.getValue();
//job.setUser_country(objectMap.get("user_country").toString());
job.setJob_headline(objectMap.get("job_headline").toString());
job.setJob_desc(objectMap.get("job_desc").toString());
job.setBudget(objectMap.get("budget").toString());
job.setTime_frame(objectMap.get("time_frame").toString());
//job.setTags(objectMap.get(getString(R.string.field_tags)).toString());
//job.setPhoto_id(objectMap.get(getString(R.string.field_photo_id)).toString());
//job.setUser_id(objectMap.get(getString(R.string.field_user_id)).toString());
//job.setDate_posted(objectMap.get("date_posted").toString());
//job.setImage_path(objectMap.get(getString(R.string.field_image_path)).toString());
/*
// soon going to be the proposals
ArrayList<Comment> comments = new ArrayList<Comment>();
for (DataSnapshot dSnapshot : singleSnapshot
.child(getString(R.string.field_comments)).getChildren()){
Comment comment = new Comment();
comment.setUser_id(dSnapshot.getValue(Comment.class).getUser_id());
comment.setComment(dSnapshot.getValue(Comment.class).getComment());
comment.setDate_created(dSnapshot.getValue(Comment.class).getDate_created());
comments.add(comment);
}
photo.setComments(comments);*/
mJobs.add(job);
}
Log.d(TAG, "onDataChange: jobs count = " + mJobs.size());
if( mJobs.size()>0){
//display our photos
displayPhotos();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
I am please to post this here because I have been wasting 2 days in this error. Actually me have to work with firebase and I don't have much command. I am adding data into array like this method
public void addNewNode(String id, String name,String price){
HashMap<String, String> names = new HashMap<>();
names.put("menu_extra_item_id", id);
names.put("menu_extra_item_name",name);
names.put("menu_extra_item_price",price);
names.put("menu_extra_item_quantity",inc_dec_tv.getText().toString());
ExtraItem.add(names);
mDatabase.child(userId).setValue(new
CalculationModel(userId,restaurant_menu_item_id,
name_,price_,"1","0",ExtraItem));
}
data is adding perfectly but when me need to remove a specific node it gives me a massive trouble. I am trying this code to remove node
public void deleteNewNode(final String id){
dataArray = new ArrayList<>();
DatabaseReference query = mDatabase;
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
//child is each element in the finished list
HashMap<String, String> map = (HashMap<String, String>)
child.getValue();
dataArray.add(map.get("extraItem")) ;
int sizeArray = dataArray.size();
for (int i =0;i<dataArray.size();i++){
HashMap<String, String> map2 = new HashMap<>();
map2.put("value", dataArray.get(i));
// String mapVal = String.valueOf(map2);
try {
JSONObject jsonObject = new JSONObject(map2);
JSONArray jsonArray =
jsonObject.getJSONArray("value");
for (int j = 0;j<jsonArray.length();j++){
JSONObject allJsonObject =
jsonArray.getJSONObject(j);
String val1 =
allJsonObject.optString("menu_extra_item_id");
int sizeBeforRemove = ExtraItem.size();
if(val1.equalsIgnoreCase(id)){
int some = i;
ExtraItem.remove(i);
String extraItemRemaining =
ExtraItem.toString();
int sizeAfterRemove = ExtraItem.size();
mDatabase.child(userId).setValue(new
CalculationModel(userId,restaurant_menu_item_id,
name_,price_,"1","0",ExtraItem));
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
ExtraItem is a grobal array initialized but when I call deleteNode method this gives error
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 at java.util.ArrayList.remove
also here is I am calling both methods.
if (checkBox != null) {
checkBox.toggle();
if (checkBox.isChecked()) {
item.setCheckBoxIsChecked(true);
addNewNode(item.getExtra_item_id(),item.getChild_item_name(), item.getChild_item_price());
} else {
item.setCheckBoxIsChecked(false);
deleteNewNode(item.getExtra_item_id());
}
}
You cannot remove second element when you have only one item in the list.
ArrayList.remove(1) removes second element.
I have this structure in Firebase
"shared_items" : {
"-KgGHdgE3L_m6ppVgn99" : {
"_id" : 14,
"added_date" : "08/Mar/2017",
"shared_with_emails" : "{\"abc#abc*com\":{\"name\":\"Customer Care\"},\"xyz#xyz*com\":{\"name\":\"Customercare\"}}",
"user_display_name" : "Logged in user",
"users_email" : "loggedinUser#gmail.com"
}
}
My questions:
When I am saving JSON data in "shared_with_emails" key then my data is automatically appended with "\" slash. Is this normal or I am doing something wrong here?
How can I get entire node based on email Ids present in this JSON object.
Function to create JSON objects from provided contacts..
public class JsonUtils {
final private static String TAG = JsonUtils.class.getSimpleName();
public String ContactsToJson() {
ArrayList<ContactsModel> listOfContacts = new ArrayList<>();
listOfContacts.add(new ContactsModel("abc#gmail.com", "abc"));
listOfContacts.add(new ContactsModel("xyz#gmail.com", "xyz"));
listOfContacts.add(new ContactsModel("mnop#yahoo.com", "mnop"));
JSONObject jsonObjectChild;
JSONObject jsonObjectRoot = new JSONObject();
for (int i = 0; i < listOfContacts.size(); i++) {
ContactsModel model = (ContactsModel) listOfContacts.get(i);
try {
jsonObjectChild = new JSONObject();
jsonObjectChild.put("name", model.getContactName());
jsonObjectRoot.put(model.getContactMail(), jsonObjectChild);
} catch (JSONException e){
e.printStackTrace();
}
}
System.out.println(jsonObjectRoot.toString());
return jsonObjectRoot.toString();
}
public class ContactsModel {
private int id;
private String mContactName;
private String mContactMail;
public ContactsModel(String contactMail, String contactName) {
this.mContactName = contactName;
this.mContactMail = contactMail;
}
public String getContactName() {
return mContactName;
}
public String getContactMail() {
return mContactMail;
}
}
}
Json data on Firebase
You can use ArrayList<String> to have multiple emails saved under shared_with_email. When you retrieve your data, save it inside an object and search whether the object contains the email.
ArrayList<String> keys = new ArrayList<>;
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(Datasnapshot snap:datasnapshot.getChildren()){
ArrayList<yourObject> current = snap.getValue();
if (current.shared_with_email.contains(someEmail)){
keys.add = snap.getKey(); //Check this, all we need is the key of our object. kd47qjB.... in this case
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Once you have all the keys. Add listeners.
for(String key: keys){
rootRef.child(key).addValueEventListener(new ValueEventListener(){
#override
public void onDataChange(Datasnapshot datasnapshot){
//You successfully added listener to the key where user has its email.
//Do your work here.
}
});
}
You will have to create a class yourObject which resembles the data in your firebase database.
in my android application I create an activity which contains a ListView which is populated with data from Firebase Database.
The JSON Tree of the structure of the database is the following:
{
"companies" : {
"companyX" : {
"address" : "50th avenue, NY",
"name" : "Spare-Tools Ltd."
},
"companyZ" : {
"address" : "50th Broadway, NY",
"name" : "Burgers and Burgers"
}
},
"company-requests" : {
"companyX" : {
"req1" : true
"req2" : true
}
},
"requests" : {
"req1" : {
"destination" : "Upper Tooting 122, Bronx",
"origin" : "Philadelphia",
"time" : "1473593287",
...
}
"req2" : {
...
}
}
}
I want to populate the ListView with the list of requests from the requests node. But I first need to know all requests that belong to a specific company so I first go to the company-requests node and retrieve all the request-keys belonging to the specific company.
The problem I am facing is that the ListView is created before the final data from the database arrived:
public class RequestsListActivity extends AppCompatActivity {
private ListView rListView;
DatabaseReference rootNode = FirebaseDatabase.getInstance().getReference();
#Override
protected void onCreate(Bundle savedInstanceState) {
...
rListView = (ListView) findViewById(R.id.result_list_view);
//First I retrieve all the requests of a specific company
DatabaseReference companyRequests = rootNode.child("company-requests/companyX");
companyRequests.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Then I retrieve all the keys of these requests
...
while (iterator.hasNext()) {
String key = iterator.next().getKey();
//For each key I retrieve its details from the requests node
DatabaseReference currRequest = rootNode.child("requests/" + key);
currRequest.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String time;
time = (String) dataSnapshot.child("time").getValue();
Request request = new Request(time);
allRequests.add(request);
}
...onCancelled...
});
}
//THIS CODE IS EXECUTED TO EARLY: BEFORE WE HAVE ANY DATA FROM FIREBASE
RequestAdapter adapter = new RequestAdapter(RequestsListActivity.this, allRequests);
rListView.setAdapter(adapter);
}
...onCancelled...
});
}
}
How can I insert a wait (spinner?) that waits until the values are loaded from Firebase?
You can use a simple counter to keep track of the number of pending loads:
companyRequests.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
// at the start we need to still load all children
final long[] pendingLoadCount = { dataSnapshot.getChildrenCount() };
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
//For each key I retrieve its details from the requests node
DatabaseReference currRequest = rootNode.child("requests/" + childSnapshot.getKey());
currRequest.addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot dataSnapshot) {
String time;
time = (String) dataSnapshot.child("time").getValue();
Request request = new Request(time);
allRequests.add(request);
// we loaded a child, check if we're done
pendingLoadCount[0] = pendingLoadCount[0] - 1;
if (pendingLoadCount[0] == 0) {
RequestAdapter adapter = new RequestAdapter(RequestsListActivity.this, allRequests);
rListView.setAdapter(adapter);
}
}
...onCancelled...
});
}
}
});
I solved this using a java.util.concurrent.CountDownLatch:
In this example, replace EquityTotalListener with your implementation of ValueEventListener.
private void recalculate() {
final AtomicLong sumUpAll = new AtomicLong();
final CountDownLatch cnt = new CountDownLatch(mapUid2GeoLocation.keySet().size());
for (final String uid : mapUid2GeoLocation.keySet()) {
EquityTotalListener el = mapUid2EquityListener.get(uid);
if (el != null) {
if (logger.isDebugEnabled()) {
logger.debug("Listener for " + uid + " already set up");
cnt.countDown();
}
} else {
el = new EquityTotalListener(database.getDatabase(), uid) {
#Override
public void onCancelled(final DatabaseError databaseError) {
super.onCancelled(databaseError);
cnt.countDown();
}
#Override
protected void valueChanged(final String key, final Object value) {
if (value != null) {
sumUpAll.getAndAdd(Long.parseLong(value.toString()));
cnt.countDown();
}
};
}.attach();
mapUid2EquityListener.put(uid, el);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Waitung for countdown..");
}
try {
final boolean allGood = cnt.await(10, TimeUnit.SECONDS);
if (allGood) {
if (logger.isDebugEnabled()) {
logger.debug("Done waiting, " + uid + " owns " + sumUpAll.get() + " equity");
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("Waiting for read operations ran into timeout");
}
}
} catch (final InterruptedException e) {
if (logger.isErrorEnabled()) {
logger.error(e.getLocalizedMessage(), e);
}
}
}