Pointyhat
Pointyhat

Reputation: 507

RecyclerView shows 3 items but only the last entry of my DB

I have a firestore db, which I am getting and saving to the device when the user logs in.

When the Fragment kicks in the Adapter is set and the ViewModel calls the Adapter passing a list of artists. My firestore db contains 3 artists, which means I should see 3 items in my RecyclerView. 3 items are showing up but it repeats the last entry 3 times.

    public class ArtistsRvAdapter extends RecyclerView.Adapter<ArtistsRvAdapter.ArtistViewHolder> {
    private List<Artist> mArtists;
    private Context mContext;
    private SharedPreferences preferences;

    public ArtistsRvAdapter(Context c){
        mContext=c;
    }

    @NonNull
    @Override
    public ArtistsRvAdapter.ArtistViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        int layoutIdForListItem = R.layout.artist_list_item;
        LayoutInflater inflater = LayoutInflater.from(mContext);
        boolean shouldAttachToParentImmediately = false;
        View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
        ArtistViewHolder viewHolder = new ArtistViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ArtistViewHolder artistViewHolder, int position) {
        Artist artist = this.mArtists.get(position);
        Log.d("rv adapter ", "artist img " + artist.getArtistImageUrl());
        String image = artist.getArtistImageUrl();

        Picasso.get()
                .load(image)
                .placeholder(R.drawable.ic_launcher_background)
                .error(R.drawable.ic_launcher_foreground)
                .into(artistViewHolder.artistImage);
            artistViewHolder.artistName.setText(artist.getArtistName());
        Log.d("rv adapter ", "artist name " + artist.getArtistName());
            artistViewHolder.artistGenre.setText(artist.getArtistGenre());
            artistViewHolder.concertDate.setText(artist.getConcertDate());
            artistViewHolder.concertLocation.setText(artist.getConcertLocation());
    }

    @Override
    public int getItemCount() {
        return (null != mArtists ? mArtists.size() : 0);
    }

    public class ArtistViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        ImageView artistImage;
        TextView artistName;
        TextView artistGenre;
        TextView concertLocation;
        TextView concertDate;

        public ArtistViewHolder(View itemView){
            super(itemView);
                artistImage = itemView.findViewById(R.id.artist_image);
                artistName = itemView.findViewById(R.id.artist_name);
                artistGenre = itemView.findViewById(R.id.artist_genre);
                concertLocation = itemView.findViewById(R.id.concert_location);
                concertDate = itemView.findViewById(R.id.concert_date);
        }

        @Override
        public void onClick(View v) {


        }
    }

    public void setArtists(List<Artist> artists){
        mArtists = artists;
        Log.d("rv " , "list artists " + mArtists);
        notifyDataSetChanged();
    }
}

This is the ViewModel class:

    public class DetailsViewModel extends AndroidViewModel {

    private static final String LOG_TAG = DetailsViewModel.class.getSimpleName();
    private LiveData<List<Artist>> mArtists;

    public DetailsViewModel(@NonNull Application application) {
        super(application);

        AppDatabase database = AppDatabase.getInstance(this.getApplication());
        Log.d(LOG_TAG, "Actively retrieving artists from DB " );
        mArtists = database.myDao().loadAllArtists();
    }

    public LiveData<List<Artist>> getArtists(){
        return mArtists;
    }
}

And this is the Fragment:

public class BaseFragment extends Fragment {

private ArtistsRvAdapter mAdapter;
private LiveData<List<Artist>> mArtists;
private String LOG_TAG = BaseFragment.class.getSimpleName();
private View mRootView;
@BindView(R.id.rv)
RecyclerView recyclerView;
private Context mContext;
private AppDatabase mDb;

public BaseFragment(){}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

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

    mRootView= inflater.inflate(R.layout.base_fragment, container, false);
    ButterKnife.bind(this, mRootView);
    mContext = getActivity().getApplicationContext();
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);

    mDb = AppDatabase.getInstance(getActivity());

    mAdapter = new ArtistsRvAdapter(mContext);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(mAdapter);
    setupViewModel();

    return mRootView;
}

private void setupViewModel(){
    Log.d(LOG_TAG, "getting artists from DB");
    DetailsViewModel viewModel = ViewModelProviders.of(getActivity()).get(DetailsViewModel.class);
    viewModel.getArtists().observe(this, new Observer<List<Artist>>() {
        @Override
        public void onChanged(List<Artist> artists) {
            mAdapter.setArtists(artists);
            Log.d(LOG_TAG, "inside viewmodel" + mArtists);
        }

    });
}}

enter image description hereenter image description hereenter image description here

log from when inserting to db and then populating the rv

public class SignInActivity extends BaseActivity implements
    View.OnClickListener {

private static final String TAG = "GoogleActivity";
private static final int RC_SIGN_IN = 9001;

// [START declare_auth]
private FirebaseAuth mAuth;
// [END declare_auth]

private GoogleSignInClient mGoogleSignInClient;
private TextView mStatusTextView;
private TextView mDetailTextView;
private List<Artist> list = new ArrayList<>();
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private FirebaseUser currentUser;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_sign_in);

    // Views
    mStatusTextView = findViewById(R.id.status);
    mDetailTextView = findViewById(R.id.detail);

    // Button listeners
    findViewById(R.id.signInButton).setOnClickListener(this);
    findViewById(R.id.signOutButton).setOnClickListener(this);
    findViewById(R.id.disconnectButton).setOnClickListener(this);

    // [START config_signin]
    // Configure Google Sign In
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .build();
    // [END config_signin]

    mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

    // [START initialize_auth]
    // Initialize Firebase Auth
    mAuth = FirebaseAuth.getInstance();
    // [END initialize_auth]
}

// [START on_start_check_user]
@Override
public void onStart() {
    super.onStart();
    // Check if user is signed in (non-null) and update UI accordingly.
    currentUser = mAuth.getCurrentUser();
    updateUI(currentUser);

}
// [END on_start_check_user]

// [START onactivityresult]
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == RC_SIGN_IN) {
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        try {
            // Google Sign In was successful, authenticate with Firebase
            GoogleSignInAccount account = task.getResult(ApiException.class);

            firebaseAuthWithGoogle(account);
        } catch (ApiException e) {
            // Google Sign In failed, update UI appropriately
            Log.w(TAG, "Google sign in failed", e);
            // [START_EXCLUDE]
            updateUI(null);
            // [END_EXCLUDE]
        }
    }
}
// [END onactivityresult]

//ToDo: Find out how to upload csv to firebase


// [START auth_with_google]
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
    Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());
    // [START_EXCLUDE silent]
    showProgressDialog();
    // [END_EXCLUDE]

    AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithCredential:success");
                        FirebaseUser user = mAuth.getCurrentUser();
                        updateUI(user);

                        getDataFromFirestoreDBandSaveToRoomDB();

                        Intent i = new Intent(getApplicationContext(), MainActivity.class);
                        i.putExtra(Constants.USER_SIGNED_IN, user);
                        startActivity(i);
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                        Snackbar.make(findViewById(R.id.main_layout), "Authentication Failed.", Snackbar.LENGTH_SHORT).show();
                        updateUI(null);
                    }

                    // [START_EXCLUDE]
                    hideProgressDialog();
                    // [END_EXCLUDE]
                }
            });
}

private void getDataFromFirestoreDBandSaveToRoomDB() {
    db.collection("artists").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {

                list = task.getResult().toObjects(Artist.class);
                Log.d(TAG, "list i got from firestore " +  list.toString());
                final AppDatabase mDb = AppDatabase.getInstance(getApplicationContext());

                Artist artist_temp = new Artist();
                for(int i=0; i<list.size();i++){
                    artist_temp.setArtistName(list.get(i).getArtistName());
                    Log.d("saving to db ", "artist name to db " + artist_temp.getArtistName());
                    artist_temp.setArtistImageUrl(list.get(i).getArtistImageUrl());
                    artist_temp.setArtistGenre(list.get(i).getArtistGenre());
                    artist_temp.setConcertDate(list.get(i).getConcertDate());
                    artist_temp.setConcertName(list.get(i).getConcertName());
                    artist_temp.setConcertTime(list.get(i).getConcertTime());
                    artist_temp.setConcertLocation(list.get(i).getConcertLocation());
                    artist_temp.setConcertLineup(list.get(i).getConcertLineup());
                    if(currentUser!=null){
                    artist_temp.setUserName(currentUser.getDisplayName());
                    artist_temp.setUserMail(currentUser.getEmail());}
                    AppExecutors.getInstance().diskIO().execute(new Runnable() {
                        @Override
                        public void run() {
                            mDb.myDao().insertData(artist_temp);
                        }
                    });
                }
            } else {
                Log.d(TAG, "Error getting documents: ", task.getException());
            }
        }
    });


}
// [END auth_with_google]

// [START signin]
private void signIn() {
    Intent signInIntent = mGoogleSignInClient.getSignInIntent();
    startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signin]

public void signOut() {
    // Firebase sign out
    mAuth.signOut();

    // Google sign out
    mGoogleSignInClient.signOut().addOnCompleteListener(this,
            new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    updateUI(null);
                }
            });
}

private void revokeAccess() {
    // Firebase sign out
    mAuth.signOut();

    // Google revoke access
    mGoogleSignInClient.revokeAccess().addOnCompleteListener(this,
            new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    updateUI(null);
                }
            });
}

private void updateUI(FirebaseUser user) {
    hideProgressDialog();
    if (user != null) {
        mStatusTextView.setText(getString(R.string.google_status_fmt, user.getEmail()));
        mDetailTextView.setText(getString(R.string.firebase_status_fmt, user.getUid()));

        findViewById(R.id.signInButton).setVisibility(View.GONE);
        findViewById(R.id.signOutAndDisconnect).setVisibility(View.VISIBLE);
    } else {
        mStatusTextView.setText(R.string.signed_out);
        mDetailTextView.setText(null);

        findViewById(R.id.signInButton).setVisibility(View.VISIBLE);
        findViewById(R.id.signOutAndDisconnect).setVisibility(View.GONE);
    }
}

@Override
public void onClick(View v) {
    int i = v.getId();
    if (i == R.id.signInButton) {
        signIn();
    } else if (i == R.id.signOutButton) {
        signOut();
    } else if (i == R.id.disconnectButton) {
        revokeAccess();
    }
}

}

Upvotes: 0

Views: 137

Answers (1)

Milan Kundacina
Milan Kundacina

Reputation: 319

Check the line where you insert artist to database in getDataFromFirestore, you will notice that artist variable is purple. That means that you are not using local artist variable (one inside method) but the class level artist variable. If you change local variable name and put it in insert() method it will work fine.

Upvotes: 2

Related Questions