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) {
}
});
}
Related
Need to Do:
Basically i want Firestore => collection "order" => docs having customerid and productid on each doc => onSuccess => add to OrderPOJOList => call getCustomerName() then getProductName() => get Names in order => add to respective ArrayList => in end combine all data from three arraylist (OrderPOJOList, CustomerName, ProductName) to CurrentOrderPOJOList => set to Adapter.
Problem:
the two listeners in getCustomerName() & getProductName() runs asynchronously and adds Name to arrayList randomly... all i want is to show data on Adapter in order but sometimes names get exchange on list due to listners running asynchronously.
What should i do to get my customer and product names from firestore in sequence to display?
public class CurrentOrders extends AppCompatActivity {
private List<CurrentOrdersPOJO> currentOrdersPOJOList;
private List<OrderPOJO> orderPOJOList;
private FirebaseFirestore firebaseFirestore;
private String DocId, Area, cname, pname;
private OrderPOJO orderPOJO;
private CurrentOrdersPOJO currentOrdersPOJO;
private int count = -1, count1 = -1, i;
private RecyclerView recyclerView;
private List<String> customerName, productName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_current_orders);
//Current User Unique ID
DocId = getIntent().getStringExtra("DocumentId");
Area = getIntent().getStringExtra("Area");
Log.w("ReachedCurrentOrders", "Doc Id: " + DocId + "\nArea: " + Area);
currentOrdersPOJOList = new ArrayList<>();
customerName = new ArrayList<String>();
productName = new ArrayList<String>();
orderPOJOList = new ArrayList<>();
recyclerView = findViewById(R.id.activity_current_order_recyclerView);
firebaseFirestore = FirebaseFirestore.getInstance();
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
firebaseFirestore.collection("order")
.whereEqualTo("area", Area)
.whereEqualTo("status", "active")
.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(final QuerySnapshot queryDocumentSnapshots) {
if (!queryDocumentSnapshots.isEmpty()) {
for (final QueryDocumentSnapshot queryDocumentSnapshot : queryDocumentSnapshots) {
count++;
}
for (final QueryDocumentSnapshot queryDocumentSnapshot : queryDocumentSnapshots) {
orderPOJO = queryDocumentSnapshot.toObject(OrderPOJO.class);
orderPOJOList.add(orderPOJO);
Log.d("Tagging", "The Customer UID: " + orderPOJO.getC_uid() + "\nThe Product Doc ID: " + orderPOJO.getP_docid());
count1++;
if (count == count1) {
getCustomerName();
}
}//endof for loop
} else {
Toast.makeText(CurrentOrders.this, "No Orders in Your Area", Toast.LENGTH_SHORT).show();
Log.d("CurrentOrder", "Exception Here");
}
}
});
}//endofOnCreate
public void getCustomerName() {
count1 = -1;
//Getting Customer Name from ID
for (i = 0; i <= count; i++) {
firebaseFirestore.collection("customer").document(orderPOJOList.get(i).getC_uid()).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()) {
cname = documentSnapshot.getString("name");
customerName.add(cname);
count1++;
if (count1 == count) {
getProductName();
}
} else {
Log.d("CurrentOrders", "Exception Here" + documentSnapshot.exists());
}
}
});
}
}//end of function
public void getProductName() {
count1 = -1;
//Product Getting Name
for (i = 0; i <= count; i++) {
firebaseFirestore.collection("product").document(orderPOJOList.get(i).getP_docid()).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()) {
pname = documentSnapshot.getString("name");
productName.add(pname);
count1++;
if (count1 == count) {
callAdapter();
}
} else {
Log.d("CurrentOrders", "Exception Here" + documentSnapshot.exists());
}
}
});
}
}//endofFunction
public void callAdapter() {
for (int i = 0; i <= count; i++) {
currentOrdersPOJO = new CurrentOrdersPOJO(customerName.get(i), orderPOJOList.get(i).getComplete_address(),
productName.get(i), orderPOJOList.get(i).getQuantity(), orderPOJOList.get(i).getStatus(), orderPOJOList.get(i).getArea(), orderPOJOList.get(i).getO_date());
currentOrdersPOJOList.add(currentOrdersPOJO);
}
recyclerView.setAdapter(new CurrentOrdersAdapter(currentOrdersPOJOList, CurrentOrders.this));
}//endofFunction
}//endofclass
[screenshot of an activity showing list that varies everytime][1]
[1]: https://i.stack.imgur.com/X48JF.jpg
A similar question has been asked on another thread, it seems that you can synchronously return data because the method itself is a task, you could try to use the Taks.await(task) method to wait for the operation to end maybe that's the answer you're looking for.
I Have solved this problem by using mentioned solution by #Ricardo above AND combining the solution with using Asynctask(Background Thread) as it was first giving IllegalStateException because of calling Tasks.await(task) on Main UI Thread.
So, Use: Tasks.await(task) on Aysnctask(Background Thread)
Here is my firebase realtime database table. I do have an image stored in the Firebase Storage. I'm planning to use multiple of characters in this table under the character column.
Realtime Database
I don't understand why I can't get the photo_id from the realtime database. The link (photo_id) is "https://firebasestorage.googleapis.com/v0/b/occreations-b6c14.appspot.com/o?name=characterimage%2FWk80hB04oZRMQxK9Ig0DDgoL5n52%20be58f895-8fda-4dd1-9e15-32e4186eae8a&uploadType=resumable&upload_id=AEnB2UrkBecZTlE4kpNypl-1ACjekw1CIM3UsUxXgRGXHLB4DCmyLDI-i70OxqjwKchf7sf3YURhgCFq3KxV7JUPDy55GyZWSg&upload_protocol=resumable"
When I click on this link, it says "Invalid request. X-Goog-Upload-Command header is missing."
But when I tested my code using the link from the URL into the arraylist, it works. But why I can't get the image from my database?
I can't seem to find the problem. I was thinking it could be the arraylist, the photo_id url or the way I upload to the firebase storage/realtime database maybe because I was unable to get the file name as .png or .jpeg and store it as a photo_id?
UPDATE: I change the url link to download url from Firebase Storage, but I am unable to retrieve the link from the DatabaseReference, which leaves nothing was adding into the List
I was following this tutorial.Coding-In-Flow Tutorial
UPDATE2: I have problems with nested data. I wanted to get ONLY the photo_id value (which is the url) from the realtime database, but I get it as a null value. The placeholder image is a null after I changed the recyclerview. How should I retrieve my data only from the character child to the character_id (which is already unretrievable) unless there is a way to do it. I've been searching through other answers on stackoverflow but none of them matches what I'm looking for.
My log cat says
W/ClassMapper: No setter/field for -LQq7dIvsJX7GgNfXeIf found on class com.example.linda.originalcharacterapp.model.CharacterInformation
No setter/field for -LQq7SB5qvcNXdJEzwBh found on class
com.example.linda.originalcharacterapp.model.CharacterInformation
D/TAG: null / null
W/ClassMapper: No setter/field for username found on class
com.example.linda.originalcharacterapp.model.CharacterInformation
No setter/field for email found on class
com.example.linda.originalcharacterapp.model.CharacterInformation
No setter/field for password found on class
com.example.linda.originalcharacterapp.model.CharacterInformation
D/TAG: null / null
Updated Android Screenshot
Android Screenshot
Current Image sitting in Firebase Storage
HomeFragment.class
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager (this.getActivity());
mRecyclerView.setLayoutManager(new GridLayoutManager (this.getActivity(),2));
userOCs = new ArrayList<> ();
//DatabaseReference characterReference = FirebaseDatabase.getInstance().getReference();
reference.child(userid).orderByChild("characters").getRef().addValueEventListener (new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Display images of ocs
for(DataSnapshot characterSnapshot : dataSnapshot.getChildren()){
if (dataSnapshot.exists()) {
String photoid = dataSnapshot.child ("photo_id").getValue (String.class);
String cName = dataSnapshot.child ("characterName").getValue (String.class);
CharacterInformation oc = characterSnapshot.getValue (CharacterInformation.class);
Log.d ("TAG", photoid + " / " + cName);
userOCs.add (oc);
Toast.makeText (getActivity (), "Adding images " + oc.getCharacterName (), Toast.LENGTH_SHORT).show ();
}
}
String file = "https://firebasestorage.googleapis.com/v0/b/occreations-b6c14.appspot.com/o/characterimage%2FWk80hB04oZRMQxK9Ig0DDgoL5n52%2F3aa5daa6-86b7-41e5-b6aa-2dae58a991ef.png?alt=media&token=5a4e9c2a-e1f8-4d05-904a-a1d934524a09";
userOCs.add(new CharacterInformation("12", "23",file, " Linda", "12", "Time ANGEL", "Quirk","Justin", "Flight", "lIVES IN MAIN"));
mAdapter = new RecycleViewAdapter (userOCs, getActivity()); //where the image is inserted
mRecyclerView.setAdapter(mAdapter);
}
CreateCharacter.class
private void uploadOC() {
//String values
nameValue = cName.getText ().toString ().trim ();
ageValue = cAge.getText ().toString ().trim ();
speciesValue = cSpecies.getText ().toString ().trim();
personalityValue = cPersonality.getText ().toString ().trim();
familyValue = cFamily.getText ().toString ().trim();
powerValue = cPowers.getText ().toString ().trim();
bioValue = cBiography.getText ().toString ().trim();
currentUserID = firebaseAuth.getCurrentUser().getUid();
if (!TextUtils.isEmpty (nameValue) && selectedImage != null) {
// StorageReference fileReference = storageReference.child(System.currentTimeMillis()+ "." + getFileExtension(downloadImage));
storageReference = storageReference.child("characterimage").child (currentUserID + "/" + UUID.randomUUID ().toString ());
storageReference.putFile (selectedImage)
.addOnSuccessListener (new OnSuccessListener<UploadTask.TaskSnapshot> () {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
downloadImage = taskSnapshot.getUploadSessionUri ();
String characterId = databaseReference.child("characters").push ().getKey(); //creates unique random id
// String photoName = taskSnapshot.getMetadata().getReference().getDownloadUrl().toString();
CharacterInformation newCharacter = new CharacterInformation (currentUserID, characterId, downloadImage.toString(),nameValue, ageValue, speciesValue,
personalityValue, familyValue, powerValue, bioValue);
Map<String, Object> postValue = newCharacter.toMap();
Map<String, Object> childUpdates = new HashMap<> ();
databaseReference.child("User Account").child(currentUserID).child("character").child(characterId).setValue(newCharacter);
childUpdates.put(nameValue, newCharacter);
databaseReference.updateChildren (childUpdates);
Toast.makeText (getActivity (), "Uploaded", Toast.LENGTH_SHORT).show ();
}
})
.addOnFailureListener (new OnFailureListener () {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText (getActivity (), "Failed " + e.getMessage (), Toast.LENGTH_SHORT).show ();
}
})
.addOnProgressListener (new OnProgressListener<UploadTask.TaskSnapshot> () {
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
double progress = (100.0 * taskSnapshot.getBytesTransferred () / taskSnapshot
.getTotalByteCount ());
}
});
}
else {
Toast.makeText (getActivity (), "Character needs name", Toast.LENGTH_SHORT).show ();
}
}
RecyclerViewAdapter.class
public class RecycleViewAdapter extends RecyclerView.Adapter<RecycleViewAdapter.ViewHolder> {
private List<CharacterInformation> mDataset;
private Context context;
public static class ViewHolder extends RecyclerView.ViewHolder {
private ImageView image;
private Context context;
private ViewHolder(View view) {
super(view);
image = (ImageView) view.findViewById(R.id.recycleImage);
}
}
public RecycleViewAdapter(List<CharacterInformation> myDataset, Context context) {
mDataset = myDataset;
this.context = context;
}
#Override
public RecycleViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_row, parent, false);
ViewHolder vh = new ViewHolder(view);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.image.setScaleType (ImageView.ScaleType.CENTER_CROP);
CharacterInformation oc = mDataset.get(position);
Picasso.get().load(oc.getPhoto_id ())
.into(holder.image);
System.out.println("Binding images...");
Toast.makeText (context,"Binding images" + oc.getCharacterName(), Toast.LENGTH_SHORT).show();
holder.image.setOnClickListener (new View.OnClickListener () {
#Override
public void onClick(View v) {
AppCompatActivity activity = (AppCompatActivity) v.getContext();
DisplayCharacter ocFragment = new DisplayCharacter ();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, ocFragment).addToBackStack(null).commit();
}
});
}
#Override
public int getItemCount() {
return mDataset.size();
}
}
And I already found my answer to this question
This is how I solve my problem, but it's more like I had the no setter field problem and problems calling from the database reference.
W/ClassMapper: No setter/field for class
I had to recall the database reference to get my nested data.
public void retrieveUserOCs() {
System.out.println("Revoke the character reference ");
reference = FirebaseDatabase.getInstance().getReference("User Account");
DatabaseReference characterReference = reference.child(user.getUid()).child("character");
// final Query query = characterReference;
reference.child(user.getUid()).child("character").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
////Loop 1 to go through all the child nodes of characters
for(DataSnapshot characterSnapshot : dataSnapshot.getChildren()){
if (dataSnapshot.getValue() != null ) {
CharacterInformation oc = characterSnapshot.getValue (CharacterInformation.class);
String ocKey = characterSnapshot.getKey ();
System.out.println ("Adding ocs: " + ocKey + " Name: " + oc.getCharacterName ());
Log.d ("TAGGING OCS", ocKey + " / " + oc.getCharacterName ());
userOCs.add (oc);
Toast.makeText (getContext(), "Adding images " + oc.getCharacterName (), Toast.LENGTH_SHORT).show ();
} else { //if user haven't added any characters
break;
}
}
String file2 ="http://ghostfinder101.weebly.com/uploads/1/9/7/3/19737887/published/gear-of-diamond_1.png?1541826567";
userOCs.add(new CharacterInformation("34", "124",file2, "Diamond", "2002", "Diamond Angel", "Narcissistic","Jahara(friend)", "Flight, shard attacks", "lIVES IN MAIN"));
mAdapter = new RecycleViewAdapter (userOCs, getActivity()); //where the image is inserted
mRecyclerView.setAdapter(mAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("Database error");
}
});
}
I am new to android development.I have a recyclerview with Viewholder for displaying photo.I have implement like feature in my app but only problem that I am facing is when I add a like on the photo the like does not show on photo I liked instead it is showing like on another photo that is down below,when I see in firebase database it looks fine but it does not display in the right position in recycler view.
I think it is not updating position how can I solve this?
this is my adapter class
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, final int position) {
// mHolder = holder;
photo = moviesList.get(position);
// final VideoHolder viewHolder2 = (VideoHolder)holder;
int viewType = getItemViewType(holder.getAdapterPosition());
switch ( viewType ) {
case IMAGE_TYPE:
PhotoHolder photoview = (PhotoHolder) holder;
mPhotoHolder = photoview;
getCurrentUsername();
getLikesPhotoString();
final ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.displayImage(getItem(position).getImage_path(),photoview.image);
photoview.mHeart.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
addNewPhotolike(mPhotoHolder);
}
#Override
public void unLiked(LikeButton likeButton) {
removePhotolike(mPhotoHolder);
}
});
photoview.Star.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
}
#Override
public void unLiked(LikeButton likeButton) {
}
});
break;
case VIDEO_TYPE:
final VideoHolder viewHolder2 = (VideoHolder)holder;
mVideoHolder = viewHolder2;
break;
}
}
#Override
public int getItemCount() {
return moviesList.size();
}
public Photo getItem(int position) {
return moviesList.get(position);
}
#Override
public int getItemViewType ( int position ) {
int viewType;
if (moviesList.get(position).getType_post().contains("Photo")) {
viewType = IMAGE_TYPE;
} else{
viewType = VIDEO_TYPE;
}
return viewType;
}
this is were photo like is added to firebase
private void addNewPhotolike(TestAdapter.PhotoHolder holder, final int position){
Log.d(TAG, "addNewlike: adding new like ");
String newLikeID = mReference.push().getKey();
Likes likes = new Likes();
likes.setUser_id(FirebaseAuth.getInstance().getCurrentUser().getUid());
mReference.child(mContext.getString(R.string.dbname_photos))
.child(getItem(position).getPhoto_id())
.child(mContext.getString(R.string.field_likes))
.child(newLikeID)
.setValue(likes);
mReference.child(mContext.getString(R.string.dbname_user_photos))
.child(getItem(position).getUser_id())
.child(getItem(position).getPhoto_id())
.child(mContext.getString(R.string.field_likes))
.child(newLikeID)
.setValue(likes);
holder.mHeartPhoto.setLiked(true);
HashMap<String ,String> notificationData = new HashMap<>();
notificationData.put("from",FirebaseAuth.getInstance().getCurrentUser().getUid());
notificationData.put("type","likes");
notificationData.put("photo_desc",getItem(position).getDescription());
holder.mNotification.child(getItem(position).getUser_id()).push().setValue(notificationData).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// getLikesString(mHolder);
getLikesPhotoString(mPhotoHolder,position);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// getLikesString(mHolder);
getLikesPhotoString(mPhotoHolder,position);
}
});
}
This is my code where like is retrieved from firebase and shown in text.
private void getLikesPhotoString(final TestAdapter.PhotoHolder holder, final int postion){
Log.d(TAG, "getLikesString: getting likes string");
try{
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
reference.keepSynced(true);
Query query = reference
.child(mContext.getString(R.string.dbname_photos))
.child(getItem(postion).getPhoto_id())
.child(mContext.getString(R.string.field_likes));
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
holder.usersPhoto = new StringBuilder();
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference
.child(mContext.getString(R.string.dbname_users))
.orderByChild(mContext.getString(R.string.field_user_id))
.equalTo(singleSnapshot.getValue(Likes.class).getUser_id());
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
Log.d(TAG, "onDataChange: found like: " +
singleSnapshot.getValue(User.class).getUsername());
holder.usersPhoto.append(singleSnapshot.getValue(User.class).getUsername());
holder.usersPhoto.append(",");
}
String[] splitUsers = holder.usersPhoto.toString().split(",");
if( holder.usersPhoto.toString().contains(currentUsername + ",")){
holder.likephotobycurrentUser = true;
}else{
holder.likephotobycurrentUser = false;
}
Log.d(TAG, "onDataChange: likes string: " + holder.mLIkePhotoString);
// setupwidjets();
int length = splitUsers.length;
if(length == 1){
holder.mLIkePhotoString = "Liked by " + splitUsers[0];
}
else if(length == 2){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ " and " + splitUsers[1];
}
else if(length == 3){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ " and " + splitUsers[2];
}
else if(length == 4){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ ", " + splitUsers[2]
+ " and " + splitUsers[3];
}
else if(length > 4){
holder.mLIkePhotoString = "Liked by " + splitUsers[0]
+ ", " + splitUsers[1]
+ ", " + splitUsers[2]
+ " and " + (splitUsers.length - 3) + " others";
}
Log.d(TAG, "onDataChange: likes string: " + holder.mLIkePhotoString);
//setup likes string
// setupLikePhotostring(holder, holder.mLIkePhotoString);
holder.mHeartPhoto.setLiked(true);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
if(!dataSnapshot.exists()){
holder.mLIkePhotoString = "";
holder.likephotobycurrentUser = false;
//setupwidjets();
// setupLikePhotostring(holder,holder.mLIkePhotoString);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
holder.mHeartPhoto.setLiked(false);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}catch (NullPointerException e){
Log.e(TAG, "removeStar: NullPointer"+e.getMessage());
holder.mLIkePhotoString = "";
holder.likephotobycurrentUser = false;
// setupLikePhotostring(mPhotoHolder,holder.mLIkePhotoString);
if (holder.likephotobycurrentUser){
holder.mHeartPhoto.setLiked(true);
}else {
holder.mHeartPhoto.setLiked(false);
}
holder.likes.setText(holder.mLIkePhotoString);
}
}
Change this line
photo = moviesList.get(holder.getAdapterPosition());
to
photo = moviesList.get(position);
where position variable is same as we got in below function
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, final int position);
And also change holder.getAdapterPosition() to position in onBindViewHolder(...) function.
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) {}
});
I have a RideList class that is called from an Activity class that retrieves data from a Firebase database. However, when I debug my program the code within my addValueEventListener is never being reached.
public class RideList {
private ArrayList<Ride> listofRides;
public Firebase myFirebase = new Firebase("https://luminous-torch-1510.firebaseio.com/rides");
Context context;
public RideList(Context context) {
this.context = context;
this.listofRides = new ArrayList <Ride>();
}
public ArrayList<Ride> getRides() {
Firebase.setAndroidContext(context);
// Attach an listener to read the data at our rides reference
Query queryRef = myFirebase.orderByChild("timePosted");
try {
queryRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
System.out.println("There are " + snapshot.getChildrenCount() + " rides");
for (DataSnapshot postSnapshot : snapshot.getChildren()) {
String rideString = postSnapshot.getValue().toString();
String[] rideA = rideString.split(" ");
String value;
for (int i = 0; i < rideA.length - 1; i++) {
rideA[i] = rideA[i].substring(rideA[i].indexOf("=") + 1);
rideA[i] = rideA[i].substring(0, rideA[i].indexOf(","));
}
rideA[rideA.length - 1] = rideA[rideA.length - 1].substring(rideA[rideA.length - 1].indexOf("=") + 1);
rideA[rideA.length - 1] = rideA[rideA.length - 1].substring(0, rideA[rideA.length - 1].indexOf("}"));
double numOfPassengers = Double.valueOf(rideA[6]);
double fare = Double.valueOf(rideA[4]);
double distance = Double.valueOf(rideA[3]);
String origin = rideA[7];
String destination = rideA[2];
double maxPassengers = Double.valueOf(rideA[5]);
String departTime = rideA[1];
String arrivalTime = rideA[0];
String timePosted = rideA[8];
String title = rideA[9];
String type1 = rideA[10];
boolean type;
if (type1.equals("offer"))
type = false;
else
type = true;
Ride ride = new Ride(numOfPassengers, fare, distance, origin, destination, maxPassengers, departTime, arrivalTime,
timePosted, title, type);
listofRides.add(ride);
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println("The read failed: " + firebaseError.getMessage());
}
});
Thread.sleep(2000);
} catch (InterruptedException e) {
return null;
}
return listofRides;
}
}
This code is being called from an OnCreate function of an Activity class. Any idea on why the listener code is never being entered/executed?
Edit: Here is the code on how this function is being called in the activity class.
list = (ListView) findViewById(R.id.showrides_listView);
Firebase.setAndroidContext(this);
RideList rl = new RideList(this);
ArrayList arrayList = rl.getRides();
// Adapter: You need three parameters 'the context, id of the layout (it will be where the data is shown),
// and the array that contains the data
ArrayAdapter adapter = new ArrayAdapter<Ride>(getApplicationContext(), android.R.layout.simple_spinner_item, arrayList){
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView text = (TextView) view.findViewById(android.R.id.text1);
text.setTextColor(Color.BLACK);
return view;
}
};
// Here, you set the data in your ListView
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
FloatingActionButton myFab = (FloatingActionButton) findViewById(R.id.showrides_fab);
myFab.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startCreateRideActivity();
}
});
Your data is being loaded asynchronously (and after that continuously synchronized) from Firebase. Putting a Thread.sleep() in there is not going to change that fact.
You can easily see what happens if you add a few log statements:
public ArrayList<Ride> getRides() {
Query queryRef = myFirebase.orderByChild("timePosted");
try {
System.out.println("Adding listener");
queryRef.addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
// THIS CODE IS CALLED ASYNCHRONOUSLY
System.out.println("Got data from Firebase");
}
public void onCancelled(FirebaseError firebaseError) {
}
});
System.out.println("Starting sleep");
Thread.sleep(2000);
} catch (InterruptedException e) {
return null;
}
System.out.println("Returning rides");
return listofRides;
}
The output is likely:
Adding listener
Starting sleep
Returning rides
Got data from Firebase
You're trying to make an asynchronous process synchronous, which is a recipe for headaches and a bad user experience. Instead of writing up a solution here, I'll link to an answer I wrote 15 minutes ago to the same problem: Retrieving ArrayList<Object> from FireBase inner class