How to get all data from collection - java

I am trying to get all the data from the first document and move to the next document and do the same.
CollectionReference fstore = fs.collection("Diagnostics").document(email).collection("Date");
fstore.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshot) {
if(!documentSnapshot.isEmpty()){
for (DocumentSnapshot documentSnapshots : documentSnapshot) {
String date = documentSnapshots.getId();
String faultcodes = documentSnapshots.getString("Code");
String description = documentSnapshots.getString("Description");
TroubleCodes pastsc = new TroubleCodes(date,faultcodes,description);
pastscan.add(pastsc);
pastscansdpt.setAdapter(new PastScanAdapter(pastscan, PastScanpage.this));
}
}
else{
TroubleCodes nosc = new TroubleCodes("No Diagnosis Scans",null, null);
pastscan.add(nosc);
pastscansdpt.setAdapter(new PastScanAdapter(pastscan, PastScanpage.this));
}
}
});

Instead of creating and setting adapter for RecyclerView or ListView for each document over and over again, create your adapter and set it for RecyclerView or ListView with empty pastscan List just only one time. Then get your data, add in to list and notify the adapter.
pastscansdpt.setAdapter(new PastScanAdapter(pastscan, PastScanpage.this));
CollectionReference fstore = fs.collection("Diagnostics/" + email + "/Date");
fstore.get().addOnSuccessListener(queryDocumentSnapshots -> {
//Clear your list otherwise whenever this method triggers it'll add same documents over and over again.
pastscan.clear();
if (!queryDocumentSnapshots.isEmpty()) {
for (DocumentSnapshot document : queryDocumentSnapshots) {
if (document.exists()) {
//According to your codes your document data structure is same as TroubleCodes.
//So you don't need to get all fields one by one.
TroubleCodes pastsc = document.toObject(TroubleCodes.class);
//Add each document in to your list.
pastscan.add(item);
}
}
} else {
TroubleCodes nosc = new TroubleCodes("No Diagnosis Scans", null, null);
pastscan.add(nosc);
}
//Notify your adapter.
adapter.notifyDataSetChanged();
});

Related

Cant Add value Into Array In OnSuccess()

I'm really new at android development, and trying to make app with firebase. I made signup with profile photo and pushed photo name into Database. And file to FireStore. At the bottom Code mImageUrls.add(uri.toString()); line doesn't work. But it makes toast in OnSuccess(), just I can't add data into array. I initialized Array in OnCreateView(final ArrayList<String> mImageUrls = new ArrayList<>();) like other arrays too. I need your help.
lv = (ListView) rootview.findViewById(R.id.lv_main);
final ArrayAdapter adapter = new MyAdapter(getActivity(), name_list,date,imgs);
myref = FirebaseDatabase.getInstance().getReference().child("MusiciansNonSensitive");
final ArrayList<String> mImageUrls = new ArrayList<>();
final StorageReference storageReference = FirebaseStorage.getInstance().getReference();
myref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
String name_value = postSnapshot.child("name").getValue().toString();
String province_value = postSnapshot.child("province").getValue().toString();
final String url_path = postSnapshot.child("photourl").getValue().toString();
StorageReference photo_url = storageReference.child("uploads/"+url_path);
photo_url.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
mImageUrls.add(uri.toString()); // I tried to add Log.d and it adds value every for loop, but after loop it being empty array again.
}
});
//mImageUrls.add("A");
name_list.add(name_value);
date.add(province_value);
}
Log.d("LOGGOGOGOOG",mImageUrls.toString()); // Here being empty
//Toast.makeText(getContext(),list.toString(),Toast.LENGTH_LONG).show();
lv.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
addOnSuccessListener is asynchronous and returns immediately. The callback is invoked some time later, even after the loop completes and your call to setAdapter. You're going to have to rewrite the code to only set the adapter after all the URLs have been fetched asynchronously. You can wait for a bunch of tasks to complete by using Tasks.whenAll() to get a new Task that will complete after the list of tasks you provide are fully complete.

recyclerview with gridview getting repeated the items twice with different index number

I have a retrieve function which gets the data from the firebase database and the code as following:
FirebaseFirestore.getInstance().collection("products")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (int i=0; i<task.getResult().size(); i++){
Products p = new Products();
String Userid = task.getResult().getDocuments().get(i).getData().get("UserID").toString();
Log.d(TAG, "onComplete: "+Userid);
if (Userid.equals(FirebaseAuth.getInstance().getCurrentUser().getUid())){
String price = task.getResult().getDocuments().get(i).getData().get("productPrice").toString();
String Image = task.getResult().getDocuments().get(i).getData().get("UrlImage0").toString();
String title = task.getResult().getDocuments().get(i).getData().get("productName").toString();
// add all these data to the product class
Log.d(TAG, "onComplete: "+price+ title+Image);
p.setTitle(title);
p.setPrice(price);
p.setProductImage(Image);
viewProduct.onSuccess(p);
}
viewProduct.onSuccess(p);
}
}else {
viewProduct.onError("Something went wrong");
}
}
});
and my loading the data into recyclerview with gridview and the code as following:
ListDataView.setLayoutManager(new GridLayoutManager(this, 2));
ListDataView.setHasFixedSize(true);
ListOutDateAdapter = new productAdapter(this, OutDateTrip);
ListDataView.setAdapter(ListOutDateAdapter);
// ListDataView.invalidate();
ListDataView.setHasFixedSize(true);
ListDataView.addItemDecoration(new DividerItemDecoration(ListDataView.getContext(), DividerItemDecoration.VERTICAL));
The issue
*It keeps loading the data as showing on the image *
I already check the following post but It did not address up my issue
enter link description here
I have reviewed a code, again and again, the issue I have to add the items twice to the product's list so I have removed one and everything is fine;

How to change recycler view item dynamically?

I have created a RecyclerView to show each node that I have connected. In the RecyclerView I have added two buttons and one TextView. The TextView will show the current status of the node i.e. whether the node in currently on or off. The nodes are sending their current status over MQTT, I am able to detect the current status of every node on my app but I am unable to update the TextView according to it. How can I update the TextView?
I have tried adding new item and deleting the previous one, but none of them works for me. I have added the code where I am detecting from which node the status message is coming.
//From this section I am getting details of my all node stored into the database
public void addData()
{
pumpList = new ArrayList<>();
StringRequest stringRequest = new StringRequest(Request.Method.GET, REQUEST_URL,
new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
try
{
JSONArray pumpData = new JSONArray(response);
for(int i = 0; i < pumpData.length(); i++)
{
JSONObject pump = pumpData.getJSONObject(i);
String name = pump.getString("name");
String device_id = pump.getString("device_id");
String stat = pump.getString("stat");
Log.d("HTTP",String.valueOf(name));
Log.d("HTTP",String.valueOf(device_id));
Log.d("HTTP",String.valueOf(stat));
pumpList.add(new pumpData(name,device_id,stat));
}
pumpAdapter adapter = new pumpAdapter(getActivity(),pumpList);
recyclerView.setAdapter(adapter);
progressDialog.dismiss();
}
catch (JSONException e)
{
e.printStackTrace();
progressDialog.dismiss();
}
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
Toast.makeText(getActivity(),error.getMessage(),Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
});
Volley.newRequestQueue(getActivity()).add(stringRequest);
}
//When I get a message over MQTT then I am showing from which device the MQTT Message is Coming from
public void changeDataByFiltering(String MQTT_TOPIC, String MQTT_PAYLOAD)
{
for(pumpData pD: pumpList)
{
insertStringSubscribe INSSUB = new insertStringSubscribe();
String mqtt_topic_from_list = INSSUB.insertString(pD.getDeviceID());
if(mqtt_topic_from_list.trim().toLowerCase().equals(MQTT_TOPIC.trim().toLowerCase()))
[enter image description here][1]{
if(MQTT_PAYLOAD.trim().toLowerCase().equals(payloadON.trim().toLowerCase()))
{
Toast.makeText(mCtx, pD.getName()+": ON",Toast.LENGTH_SHORT).show();
}
if(MQTT_PAYLOAD.trim().toLowerCase().equals(payloadOFF.trim().toLowerCase()))
{
Toast.makeText(mCtx, pD.getName()+": OFF",Toast.LENGTH_SHORT).show();
}
}
}
}
I assume that we have a List<String> data as our data source and we have rvadapter which is our RecyclerView.Adapter . and we will do as below to update an item:
data.set(position,"newdata");
rvadapter.notifyItemChanged(position);
Also, you can change the range of items. and insert new item or delete item but have to call notify... related function in rvadapter
but if you recreate the data for example :
data = new ... then you have to use notifydatasetchanged;

Firebase Scalability - Query DB vs Custom Object ArrayList?

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.

#Askfirebase Get the previous item values(POJO) in firebase recycler adapter in android

AskFirebase How to get the previous item values(POJO) in firebase recycler adapter without using database query.
// Set up FirebaseRecyclerAdapter with the Query
Query postsQuery = getQuery(mDatabase);
mAdapter = new FirebaseRecyclerAdapter<Post, PostViewHolder>(Post.class, R.layout.item_post,
PostViewHolder.class, postsQuery) {
#Override
protected void populateViewHolder(final PostViewHolder viewHolder, final Post model, final int position) {
final DatabaseReference postRef = getRef(position);
Log.e(TAG, "populateViewHolder: " + position);
// Set click listener for the whole post view
final String postKey = postRef.getKey();
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Launch PostDetailActivity
Intent intent = new Intent(getActivity(), PostDetailActivity.class);
intent.putExtra(PostDetailActivity.EXTRA_POST_KEY, postKey);
startActivity(intent);
}
});
// Determine if the current user has liked this post and set UI accordingly
if (model.stars.containsKey(getUid())) {
viewHolder.starView.setImageResource(R.drawable.ic_toggle_star_24);
} else {
viewHolder.starView.setImageResource(R.drawable.ic_toggle_star_outline_24);
}
// Bind Post to ViewHolder, setting OnClickListener for the star button
viewHolder.bindToPost(model, new View.OnClickListener() {
#Override
public void onClick(View starView) {
// Need to write to both places the post is stored
Log.e(TAG, "new: ");
DatabaseReference globalPostRef = mDatabase.child("posts").child(postRef.getKey());
DatabaseReference userPostRef = mDatabase.child("user-posts").child(model.uid).child(postRef.getKey());
// Run two transactions
onStarClicked(globalPostRef);
onStarClicked(userPostRef);
}
});
}
};
mRecycler.setAdapter(mAdapter);
Suppose their are five cell list whenever i am facing second cell in the list that time i want to put a condition based on first cell value. So how i can fatch the value of first cell?
I already try to using arraylist to store the POJO of Post . But the problem is whenever some item is deleted from firebase table that item onDataChange call but populateViewHolder doesn't call. Their is also a way to get previous data using database query that is
DatabaseReference ref = getRef(position-1);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Log.e(TAG, "CHild exist: ");
} else {
Log.e(TAG, "no CHild exist: ");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
But i don't want to use this database query is their any other way?
The Design Firebase data structure for topic Answer and Comment its like your problem.
gdtdg6765rf and hjgdhs567hd are unique key get by firebase
hjgdhs567hd is answer
gdtdg6765rf is comment to answer hjgdhs567hd
created is -1*UNIX Timestamp for ordering
date, time and toanswer was saved in comments by answer belong to
if to delete answer set all flags "deleted=1" where child "toanswer=deleted answer key" to populate again
#eurosecom above image is my layout where their is a recycler view which populate through FirebaseRecyclerAdapter . Now those green cell is my single cell. you see a red circle which denote the date. in case of position==0 I just simple visible the layout, and in case of position>0 i want to put the condition based on previous item date.
Now in my FirebaseRecyclerAdapter i have to put the condition so i have to fetch the previous position date. So as i am already doing a network oparetion using Query to fetch the msg list i don't want to put addListenerForSingleValueEvent in the populateview again as because it will again fetch the val from database. So is their any other way to get the previous item?

Categories