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

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;

Related

Incorrect behaviour by Firestore whereEqualto() query in android app

My database consists of a collection called songs which has fields: artist, email, link and name. At the moment the email field in all documents is an empty string. Here is a pic of one of the entries.
Here is the query that I'm running in my android app:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_registration);
firebaseAuth = FirebaseAuth.getInstance();
FirebaseFirestore db = FirebaseFirestore.getInstance();
TextView userinfo = (TextView)findViewById(R.id.link);
FirebaseUser userauth = firebaseAuth.getCurrentUser();
db.collection("songs").whereEqualTo("email",userauth.getEmail()).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>(){
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
// Document found in the offline cache
userinfo.setText("User found");
} else {
userinfo.setText("User not found");
}
}
});
}
The TextView is printing User found even though all the email entries are empty strings. The expected behavior is User not found.
If you only check if a Task is successful it doesn't mean that you get results. It means that your query is completed with no errors. If you need to know if the query returns the desired result, then you should check that in code:
if (task.isSuccessful()) {
QuerySnapshot snapshot = task.getResult();
if (snapshot.isEmpty()) {
userinfo.setText("User not found");
} else {
userinfo.setText("User found");
}
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
The "User not found" message will be set to your userinfo TextView.

How to get all data from collection

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();
});

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.

List size goes back to zero for some reason

I am loading data from cloud firestore into a custom recyclerview adapter. According to my log I get the data from firestore just fine and inside of my get method the log shows my list size increasing. Outside of my get method mWorkoutList goes back to size 0. I cannot figure out why this is happening.
public class ViewWorkoutsActivity extends AppCompatActivity implements WorkoutAdapter.WorkoutAdapterOnClickHandler {
private final String TAG = this.getClass().getName();
private FirebaseFirestore db;
private String mUid;
private List<Set> mSetList;
private RecyclerView mRecyclerView;
private WorkoutAdapter mWorkoutAdapter;
private List<OtherWorkout> mWorkoutList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_workouts);
mWorkoutList = new ArrayList<>();
mUid = getIntent().getStringExtra("uid");
db = FirebaseFirestore.getInstance();
initDatabaseData();
mRecyclerView = findViewById(R.id.recycler_view);
LinearLayoutManager linearLayoutManager
= new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setHasFixedSize(true);
mWorkoutAdapter = new WorkoutAdapter(this);
mRecyclerView.setAdapter(mWorkoutAdapter);
Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());
mWorkoutAdapter.setWorkoutData(mWorkoutList);
}
#Override
public void onClick(OtherWorkout workout) {
}
public void initDatabaseData(){
CollectionReference collectionReference2 = db.collection("users").document(mUid).collection("workouts");
collectionReference2.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()){
for (QueryDocumentSnapshot document : task.getResult()){
OtherWorkout workout = document.toObject(OtherWorkout.class);
mWorkoutList.add(workout);
Log.i("LOG", "workout list size: " + mWorkoutList.size());
}
}
}
});
}
}
Hi Allen you are calling initDatabaseData(); in oncreate() method which is making Network Request and fetching data. So it takes roughly around 2-3 seconds to fetch the data. But In that 2-3 seconds your code below initDatabaseData() getting called
LinearLayoutManager linearLayoutManager
= new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setHasFixedSize(true);
mWorkoutAdapter = new WorkoutAdapter(this);
mRecyclerView.setAdapter(mWorkoutAdapter);
Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());
mWorkoutAdapter.setWorkoutData(mWorkoutList);
So till the data has not come the listsize will display 0 and then after you get the data in onComplete() list size will increase(). So basically add a line mWorkoutAdapter.notifyDatasetChanged(); here:-
if(task.isSuccessful()){
for (QueryDocumentSnapshot document : task.getResult()){
OtherWorkout workout = document.toObject(OtherWorkout.class);
mWorkoutList.add(workout);
Log.i("LOG", "workout list size: " + mWorkoutList.size());
}mWorkoutAdapter.notifyDatasetChanged();
}
This will refresh your Adapter with your new values.
You create OtherWorkout as a local object, then add it to the collection.
If your get() function runs out of scope the object will be automatically deleted.
I didn't check but I think the Java garbage collection will take care of the rest and delete the object from the Array.
You should create the objects on the Heap with new so they will persist outside of the scope of that function.
You can check your
Log.i("LOG", "workout list size: " + mWorkoutList.size());
after
Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());
so it means firebase take some some time for fetch all data , in period of this time your rest of code are executed.
so the solution is called initDatabaseData() after set the adapter then adapter.notifydatasetchanged() called. or you can direct notify the adapter in initDatabaseData() method after fetching data.
addOnCompleteListener provides a way to add asynchronous task listener.
When you call initDatabaseData(), you start the task and define a listener. But there is no guarantee that this task is completed when returning from initDatabaseData.
That's why, once you print mWorkoutList size in the onCreate method, the value can be different from the one printed in the listener.
To avoid that, you can change the way your program works either by changing the async mechanism to a sync one, or by the part using the data to the listener onComplete method

#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