RecyclerView показывает 3 элемента, но только последнюю запись моей БД - PullRequest
0 голосов
/ 29 октября 2019

У меня есть база данных firestore, которую я получаю и сохраняю на устройстве, когда пользователь входит в систему.

Когда установлен Fragment кик в Adapter и ViewModel вызываетAdapter прохождение списка художников. Моя база данных firestore содержит 3 артиста, что означает, что я должен увидеть 3 элемента в моем RecyclerView. Показывается 3 элемента, но он повторяет последнюю запись 3 раза.

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

Это класс ViewModel:

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

И это 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();
    }
}

}

1 Ответ

2 голосов
/ 29 октября 2019

Проверьте строку, где вы вставляете Artist в базу данных в getDataFromFirestore, вы заметите, что переменная Artist фиолетовая. Это означает, что вы используете не локальную переменную Artist (один внутри метода), а переменную Artist уровня класса. Если вы измените имя локальной переменной и поместите его в метод insert(), он будет работать нормально.

...