我有一个Firestore数据库,我在用户登录时将其存储并保存到设备中。
当Fragment
插入Adapter
时,ViewModel
呼叫Adapter
并传递艺术家列表。我的firestore数据库包含3位艺术家,这意味着我应该在RecyclerView
中看到3个项目。显示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);
}
});
}}
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();
}
}
}
答案 0 :(得分:2)
在split_part(regexp_replace(columnyoudoregexon , '[^. 0-9]', '', 'g'), ' ', 1)
中检查将歌手插入数据库的行,您会注意到歌手变量为紫色。这意味着您不是在使用本地艺术家变量(一个内部方法),而是在类级别的艺术家变量。如果您更改局部变量名称并将其放在split_part()
方法中,它将可以正常工作。