1

I am a newbie. Tried other resources but most of them have discussed on recycler view but for my app I am using view model. Looking forward for help. I want to retrieve the user profile data from firebase cloud store. Following is the code I referred so far.

ProfileViewModel.java

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class ProfileViewModel extends ViewModel {

private MutableLiveData<String> mText;

public ProfileViewModel() {
    mText = new MutableLiveData<>();

    mText.setValue( "Your Profile" );
}

public LiveData<String> getText() {
    return mText;
}

}

ProfileFragment.java

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;

import com.example.parkbookingslot.R;

public class ProfileFragment extends Fragment {

private ProfileViewModel profileViewModel;

public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {
    profileViewModel =
            ViewModelProviders.of( this ).get( ProfileViewModel.class );
    View root = inflater.inflate( R.layout.fragment_profile, container, false );

    final TextView textView = root.findViewById( R.id.text_profile );

    profileViewModel.getText().observe( getViewLifecycleOwner(), new Observer<String>() {
        @Override
        public void onChanged(@Nullable String s) {
            textView.setText( s );
        }
    } );

    return root;
}

}

fragment_profile.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.profile.ProfileFragment">

<TextView
    android:id="@+id/email"
    android:layout_width="84dp"
    android:layout_height="31dp"
    android:layout_marginEnd="164dp"
    android:layout_marginRight="164dp"
    android:layout_marginBottom="182dp"
    android:text="Email"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent" />

<TextView
    android:id="@+id/text_profile"
    android:layout_width="109dp"
    android:layout_height="35dp"
    android:layout_marginEnd="150dp"
    android:layout_marginRight="150dp"
    android:layout_marginBottom="35dp"
    android:text="Your Profile"
    app:layout_constraintBottom_toTopOf="@+id/name"
    app:layout_constraintEnd_toEndOf="parent" />

<TextView
    android:id="@+id/name"
    android:layout_width="84dp"
    android:layout_height="31dp"
    android:layout_marginEnd="164dp"
    android:layout_marginRight="164dp"
    android:layout_marginBottom="34dp"
    android:text="Name"
    app:layout_constraintBottom_toTopOf="@+id/phoneno"
    app:layout_constraintEnd_toEndOf="parent" />

<TextView
    android:id="@+id/phoneno"
    android:layout_width="wrap_content"
    android:layout_height="31dp"
    android:layout_marginEnd="158dp"
    android:layout_marginRight="158dp"
    android:layout_marginBottom="36dp"
    android:text="Phone Number"
    app:layout_constraintBottom_toTopOf="@+id/vehicleno"
    app:layout_constraintEnd_toEndOf="parent" />

<TextView
    android:id="@+id/vehicleno"
    android:layout_width="112dp"
    android:layout_height="35dp"
    android:layout_marginEnd="150dp"
    android:layout_marginRight="150dp"
    android:layout_marginBottom="30dp"
    android:text="Vehicle Number"
    app:layout_constraintBottom_toTopOf="@+id/email"
    app:layout_constraintEnd_toEndOf="parent" />

Edited Code after applying the solution shared;

package com.example.parkbookingslot.ui.profile;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;

import com.example.parkbookingslot.R;
import com.example.parkbookingslot.UserProfile;

public class ProfileFragment extends Fragment {

    private ProfileViewModel profileViewModel;

    public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle  savedInstanceState) {

    final View root = inflater.inflate( R.layout.fragment_profile, container, false );
    profileViewModel = ViewModelProviders.of( this ).get( ProfileViewModel.class );

    profileViewModel.getUserProfile().observe(getViewLifecycleOwner(), new Observer<UserProfile>() {
        @Override
        public void onChanged(UserProfile userProfile) {
            if (userProfile != null) {
                ((TextView) root.findViewById(R.id.name)).setText(userProfile.getName());
                ((TextView) root.findViewById(R.id.phoneno)).setText(userProfile.getPhoneno());
                ((TextView) root.findViewById(R.id.vehicleno)).setText(userProfile.getVehicleno());
                ((TextView) root.findViewById(R.id.email)).setText(userProfile.getEmail());
            }else {
                Toast toast = Toast.makeText(getActivity().getApplicationContext(), "No user information", Toast.LENGTH_SHORT);
                toast.show();
            }
        }
    });
    return root;
}

}

Before the edited code, I get the following screen.
After updating the UI, I get the following screen;

Did I miss something in fragment_profile.xml or it's in ProfileFragment.java?

Edited ProfileViewModel.java

package com.example.parkbookingslot.ui.profile;

import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import com.example.parkbookingslot.UserProfile;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;

public class ProfileViewModel extends ViewModel {
    FirebaseAuth fAuth = FirebaseAuth.getInstance();
    String userId = fAuth.getCurrentUser().getUid();

    public LiveData<UserProfile> getUserProfile() {
     final MutableLiveData<UserProfile> userProfileMutableLiveData =    new MutableLiveData<>();
     FirebaseFirestore db = FirebaseFirestore.getInstance();

     DocumentReference docRef =  db.collection("Users").document(userId);
     docRef.get().addOnCompleteListener(new  OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            if (task.isSuccessful()) {
                DocumentSnapshot documentSnapshot = task.getResult();
                if (documentSnapshot != null &&  documentSnapshot.exists()) {
                    UserProfile userProfile =  documentSnapshot.toObject(UserProfile.class);
                    userProfileMutableLiveData.postValue(userProfile);
                }else {
                    userProfileMutableLiveData.postValue(null);
                }
            }else {
                userProfileMutableLiveData.postValue(null);
            }
        }
    });
    return userProfileMutableLiveData;
}

}

Data in firebase cloudstore

2 Answers2

0

ViewModel

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class ProfileViewModel extends ViewModel {

      public LiveData<UserProfile> getUserProfile(){

        final MutableLiveData<UserProfile> userProfileMutableLiveData = new MutableLiveData<>();
        FirebaseFirestore db = FirebaseFirestore.getInstance();
        DocumentReference docRef = db.collection("users").document("android.dev@gmail.com");
        docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful()) {
                    DocumentSnapshot document = task.getResult();
                    if (document != null && document.exists()) {
                        UserProfile userProfile = document.toObject(UserProfile.class);
                        userProfileMutableLiveData.postValue(userProfile);
                    } else {
                        userProfileMutableLiveData.postValue(null);
                    }
                } else {
                    userProfileMutableLiveData.postValue(null);
                }
            }
        });

        return userProfileMutableLiveData;
    }
}

Fragment

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;

import com.example.parkbookingslot.R;

public class ProfileFragment extends Fragment {

private ProfileViewModel profileViewModel;

public View onCreateView(@NonNull LayoutInflater inflater,
                         ViewGroup container, Bundle savedInstanceState) {

    View root = inflater.inflate( R.layout.fragment_profile, container, false );

    profileViewModel =  ViewModelProviders.of(this).get(ProfileViewModel.class);

    profileViewModel.getUserProfile().observe(getViewLifecycleOwner(),new Observer<UserProfile>(){
         @Override
         public void onChanged(UserProfile userProfile) {
                if(userProfile != null){
                    //UPDATE YOUR UI HERE
                } else {
                    //SHOW ERROR MESSAGE
                }
         }
    });

    return root;
}

User Profile Model

public class UserProfile {
    String fullName, address, gender, phone;

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

Firestore View

enter image description here

JunaidKhan
  • 654
  • 7
  • 15
  • Hi, thank you for quick response. Is the following way the correct approach to update the ui? ((TextView) root.findViewById(R.id.name)).setText(userProfile.getName()); ((TextView)root.findViewById(R.id.phoneno)).setText(userProfile.getPhoneno()); ((TextView)root.findViewById(R.id.vehicleno)).setText(userProfile.getVehicleno()); ((TextView)root.findViewById(R.id.email)).setText(userProfile.getEmail()); –  Mar 17 '20 at 05:58
  • Yes, please following this link for further details https://stackoverflow.com/questions/6495898/findviewbyid-in-fragment – JunaidKhan Mar 17 '20 at 07:41
  • Thank you. I have tried it and also referred the link but I got a blank page without any profile data. What could be the problem? –  Mar 17 '20 at 16:42
  • I posted the edited code above in the question with the screenshot of the screen I got. I still cannot retrieve data from firebase cloud store. Where is it going wrong? –  Mar 17 '20 at 17:54
  • Please debug your code. Also check your firestore query that are you pointing to right database and right document or not. – JunaidKhan Mar 17 '20 at 19:14
  • In the logcat, I can view the data retrieved from the database. Now just the issue is displaying those data in the screen. –  Mar 19 '20 at 11:07
  • I found out that userProfile.getName() in ProfileFragment.java gives null value. That's is why I was getting blank screen. –  Mar 19 '20 at 12:03
  • Is there any other way for using setText() to get the data? –  Mar 19 '20 at 17:41
  • Your fields names in firestore document must match with UserProfile model variables names. – JunaidKhan Mar 19 '20 at 17:56
  • Currently your firestore document field names and userprofile model variable names doesn't match. avoid spaces in field names in firestore document. better to use camel case conventions. – JunaidKhan Mar 19 '20 at 17:58
  • issues arises at the time of mapping response to user profile model. `UserProfile userProfile = documentSnapshot.toObject(UserProfile.class);` – JunaidKhan Mar 19 '20 at 18:03
  • The issue is resolved. The data retrieved from Firestore was not set to the user profile class attribute using setter method in profile view model class. Thank you for you help. –  Mar 20 '20 at 18:12
0

In ProfileViewModel.java:

if (task.isSuccessful()) {
    DocumentSnapshot documentSnapshot = task.getResult();
    if (documentSnapshot != null && documentSnapshot.exists()) {
        //start (this lines of code solved the issue)
        String name = documentSnapshot.getString("Name");
        String phoneno = documentSnapshot.getString("Phone number");
        String vehicleno = documentSnapshot.getString("Vehicle Number");
        String email = documentSnapshot.getString("Email");
        UserProfile userProfile = documentSnapshot.toObject(UserProfile.class);

        userProfile.setName(name);
        userProfile.setPhoneno(phoneno);
        userProfile.setVehicleno(vehicleno);
        userProfile.setEmail(email);
        //end
        userProfileMutableLiveData.postValue(userProfile);
    }else {
        userProfileMutableLiveData.postValue(null);
    }
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92