OnComplete action for button in recyclerview only applied to first position - android

I have a activity where it displays candidate on recyclerview to cardview. All is functioning correctly except the code below greyed the button for only the first position. I will attach the screenshot below.
the output
it should be if only one field value is true on in all documents, all the button should be disabled. But as you can see, only the first button is disabled.
Here is my code:
db.collection("cancol").whereEqualTo(currentuser, true).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
Button btncan= findViewById(R.id.btncandidate);
Toast.makeText(NewVoteMainActivity.this, "You have already used your vote.", Toast.LENGTH_SHORT).show();
adapter.setOnItemClickListener(null);
int disabled = Color.parseColor("#c2c2c2");
btncan.setBackgroundColor(disabled);
}
});
I also tried this but also gives the same result:
db.collection("cancol").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
Toast.makeText(NewVoteMainActivity.this, "Retrieving Documents..." , Toast.LENGTH_SHORT).show();
List<String> list = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()) {
if (document.getBoolean(currentuser) == true) {
Button btncan= findViewById(R.id.btncandidate);
Toast.makeText(NewVoteMainActivity.this, "You have already used your vote.", Toast.LENGTH_SHORT).show();
adapter.setOnItemClickListener(null);
int disabled = Color.parseColor("#c2c2c2");
btncan.setBackgroundColor(disabled);
}
}
How do I make the code apply to every button?

Related

How can we store dropdown selected option string to firestore in android studio

I have String list as shown I want the selected item to be store in Firestore
Can you please tell me how it should be possible?
I have String list as shown I want the selected item to be store in Firestore
Can you please tell me how it should be possible?
public class Student_Register_Activity extends AppCompatActivity {
EditText etRegEmail,etname,etfathername,etRollno,etdepartment,etadress,etphonenmbr,semester,;
EditText etRegPassword;
String[] items={"Shinkiari","Mansehra","Abbottabad","Qalandarabad","Attersheesha","Khaki"};
AutoCompleteTextView autoCompleteText;
Button btnRegister;
ArrayAdapter<String> adapteritems;
FirebaseAuth mAuth;
FirebaseFirestore firestore=FirebaseFirestore.getInstance();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_student_register);
autoCompleteText=findViewById(R.id.auto_complete_txt);
adapteritems=new ArrayAdapter<String>(this,R.layout.list_item,items);
autoCompleteText.setAdapter(adapteritems);
autoCompleteText.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
String item =adapterView.getItemAtPosition(position).toString();
}
});
etRegEmail = findViewById(R.id.etRegEmail);
etRegPassword = findViewById(R.id.etRegPass);
btnRegister = findViewById(R.id.btnRegister);
etname = findViewById(R.id.etname);
etfathername = findViewById(R.id.etfname);
etRollno = findViewById(R.id.etRollno);
etdepartment = findViewById(R.id.etdepartment);
etadress = findViewById(R.id.etadress);
etphonenmbr = findViewById(R.id.etphonenmbr);
mAuth = FirebaseAuth.getInstance();
btnRegister.setOnClickListener(view -> createUser());
}
private void createUser(){
String email = etRegEmail.getText().toString();
String password = etRegPassword.getText().toString();
if (TextUtils.isEmpty(email)){
etRegEmail.setError("Email cannot be empty");
etRegEmail.requestFocus();
}else if (TextUtils.isEmpty(password)){
etRegPassword.setError("Password cannot be empty");
etRegPassword.requestFocus();
}else{
mAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
Toast.makeText(Student_Register_Activity.this, "Student registered successfully", Toast.LENGTH_SHORT).show();
FirebaseUser user = mAuth.getCurrentUser();
DocumentReference df = firestore.collection("Student").document(user.getUid());
//Map is used to store the data
Map<String,Object> userinfo = new HashMap<>();
userinfo.put("Name",etname.getText().toString());
userinfo.put("FName",etfathername.getText().toString());
userinfo.put("Email",etRegEmail.getText().toString());
userinfo.put("Password",etRegPassword.getText().toString());
userinfo.put("semester",etRegPassword.getText().toString());
userinfo.put("Transport", adapteritems.toString();
userinfo.put("Rollno",etRollno.getText().toString());
userinfo.put("Department",etdepartment.getText().toString());
userinfo.put("address",etadress.getText().toString());
userinfo.put("phone",etphonenmbr.getText().toString());
startActivity(new Intent(Student_Register_Activity.this, AdminDashboard.class));
//specify if user is student
userinfo.put("isStudent","1");
df.set(userinfo);
}else{
Toast.makeText(Student_Register_Activity.this, "Registration Error: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
}
}
I think you want to add selected items from list in user object, If that so you can follow below steps:
first declare global variable for selected
String selectedOption;
Then save value in on click of list
autoCompleteText.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
selectedOption =adapterView.getItemAtPosition(position).toString();
}
});
then use that value to save in user object
userinfo.put("city",selectedOption);

White screen appearing when trigger a button

why does every time that I trigger the button it makes my screen white. But the values are getting remove.
Here is my code for it where it throws error.
final String uniqueKey = requestFormArrayList.get(position).getRequestid();
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("ResearchRequest").child(uniqueKey);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
String termsAgreement = snapshot.child("requestStatus").getValue(String.class);
if(termsAgreement.equals("accepted")){
holder.acceptresearch_request.setText("accepted");
holder.acceptresearch_request.setEnabled(false);
holder.deleteresearch_request.setEnabled(false);
holder.publishresearch_request.setEnabled(true);
}
else if (termsAgreement.equals("published")){
holder.acceptresearch_request.setEnabled(false);
holder.deleteresearch_request.setEnabled(false);
holder.publishresearch_request.setText("published");
holder.publishresearch_request.setEnabled(false);
}
else{
holder.acceptresearch_request.setEnabled(true);
holder.deleteresearch_request.setEnabled(true);
holder.publishresearch_request.setEnabled(false);
}
}
the code above makes the button enable/disable depends on the value on the condition. But every time I delete or trigger the delete button it turns the screen white and go back to the MainActivity but it deletes the data without issue, it's just that it turns white instead of toasting and here's my code for it.
holder.deleteresearch_request.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("Delete Research Record");
alert.setMessage("Are you sure you want to delete");
alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final String uniqueKey = requestFormArrayList.get(position).getRequestid();
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("ResearchRequest").child(uniqueKey);
databaseReference.removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (!task.isSuccessful()) {
Log.i("firebase", "Throwing exception");
throw new RuntimeException(task.getException());
}
else {
Toast.makeText(context, "Research has been deleted", Toast.LENGTH_SHORT).show();
}
}
});
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(context, "Cancelled", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
alert.show();
}
});
EDIT: This is the error that throws at me, I've searched about the NullPointerException here. But I don't quite follow
2021-01-07 16:37:28.706 25163-25163/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.citeresearchrepository, PID: 25163
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at com.example.citeresearchrepository.AdminAdapter.AdminRequestFormAdapter$1.onDataChange(AdminRequestFormAdapter.java:60)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
at android.os.Handler.handleCallback(Handler.java:900)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8347)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
Should I add another condition where termsAgreement.isEmpty() ? I think it's on the condition above since when you deleted it, there's no termsAgreement.equals("deleted"); in the database, any idea on for solution with this one?
String termsAgreement = snapshot.child("requestStatus").getValue(String.class);
if(termsAgreement.equals("accepted")){
holder.acceptresearch_request.setText("accepted");
holder.acceptresearch_request.setEnabled(false);
holder.deleteresearch_request.setEnabled(false);
holder.publishresearch_request.setEnabled(true);
}
else if (termsAgreement.equals("published")){
holder.acceptresearch_request.setEnabled(false);
holder.deleteresearch_request.setEnabled(false);
holder.publishresearch_request.setText("published");
holder.publishresearch_request.setEnabled(false);
}
else{
holder.acceptresearch_request.setEnabled(true);
holder.deleteresearch_request.setEnabled(true);
holder.publishresearch_request.setEnabled(false);
}
Here, your termsAgreement is null. Look at top line you wrote that String.class. String is data type. So, how you are calling it? I think that's why you are getting error. Maybe, you actually wanted to write string.class. On .getValue(String.class) you are unable to call value. That's why you are getting error.

the follow button on the itemView is not working properly

I use RecyclerView for searching for users.
the search works fine, but the follow button in the ItemView is not.
Whenever I press the follow button, the text on the button is supposed to change from "follow" to "following". and and when I press it again it supposed to change from "following" to "follow". it was working just fine and suddenly it just stopped working!
Whenever I press the button it changes from "follow" to "following" for a sec and then it return to "follow". I couldn't figure out the reason!
Here is my code.
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
final User user = mUsers.get(position);
isFollowing(user.getId(), holder.btn_follow);
holder.btn_follow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.btn_follow.getText().toString().equals("follow"))
{
FirebaseDatabase.getInstance().getReference().child("Follow").child(firebaseUser.getUid())
.child("following").child(user.getId()).setValue(true);
FirebaseDatabase.getInstance().getReference().child("Follow").child(user.getId())
.child("followers").child(firebaseUser.getUid()).setValue(true);
addNotifications(user.getId());
}
else
{
FirebaseDatabase.getInstance().getReference().child("Follow").child(firebaseUser.getUid())
.child("following").child(user.getId()).removeValue();
FirebaseDatabase.getInstance().getReference().child("Follow").child(user.getId())
.child("followers").child(firebaseUser.getUid()).removeValue();
// FirebaseDatabase.getInstance().getReference("Notifications").child(user.getId()).removeValue();
}
}
});
}
Here is the isFollowing function:
private void isFollowing(final String userid, final Button button) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference()
.child("Follow").child(firebaseUser.getUid()).child("following");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.child(userid).exists()) {
button.setText("following");
button.setBackgroundResource(R.drawable.buttonafter);
} else {
button.setText("follow");
button.setBackgroundResource(R.drawable.buttonbefore);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
It keeps returning to the default "follow" text on the button, so it is not allowing me to follow anyone.
Please help if you know what's causing this problem.
Move your implementation of onClickListener() of your button from onBindViewHolder() method to your ViewHolder class of your RecyclerView. It's not a good idea to implement listeners in onBindViewHolder().

How to save the state of button onced pressed

I just fetch data & load it into recyclerView that can be set on adapter. It contains a button which is able to send data to Firebase.
When I press the button its color and text changes as per requirement
but whenever I reload it again the default button state gets loaded.
So I want that button should save its state once clicked and whenever I reload the same activity it should be in the saved state.
viewHolder.send_req.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
final Integer taggedPosition = viewHolder.getAdapterPosition();
Log.d(TAG,"button click data:"+taggedPosition);
firebaseFirestore.collection("Users").document(u_id).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.getResult().exists()){
name = task.getResult().getString("name");
userID = task.getResult().getString("user_id");
firebaseFirestore.collection("Pets").whereEqualTo("name",name_data).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (final DocumentSnapshot documentSnapshot : task.getResult()){
docID = documentSnapshot.getId();
Log.d(TAG,"selected pet doc id:"+docID);
if (docID!= null){
final Map<String, Object> userMap = new HashMap<>();
final Map<String, Object> userMap1 = new HashMap<>();
userMap.put("doc_id",docID);
userMap.put("pet_id",pet_no);
userMap.put("sender_id",userID);
userMap.put("sender_name",name);
userMap.put("pet_name",name_data);
userMap.put("pet_profile",image_url);
userMap.put("timestamp",FieldValue.serverTimestamp());
//do not place request if data is already exist in document
firebaseFirestore.collection("Send_req").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
List<String> list = new ArrayList<>();
final Button send_req = (Button)v;
if (task.isSuccessful()){
for (DocumentSnapshot document : task.getResult()) {
list.add(document.getString("doc_id"));
list.add(document.getString("sender_id"));
}
if (!(list.contains(docID)&& list.contains(userID))){
send_req.setClickable(true);
Toast.makeText(context,"send request successfully",Toast.LENGTH_SHORT).show();
send_req.setText("Cancel Request");
send_req.setBackgroundColor(Color.RED);
String btnname =send_req.getText().toString();
String button_name = (String)userMap.put("btnName",btnname);
firebaseFirestore.collection("Send_req").add(userMap);
send_req.setClickable(false);
}
else {
if ((list.contains(docID)&& list.contains(userID))){
if(send_req.getText().toString().equals("Send Request") )
Toast.makeText(context,"you already send request",Toast.LENGTH_SHORT).show();
send_req.setText("Cancel Request");
send_req.setBackgroundColor(Color.RED);
send_req.setClickable(false);
notifyDataSetChanged();}
}
}
}
});
}
}
}
}
});
}
}
});
}
});
public class SomeClass {
public static boolean isFeatureSelected = false;
...
}
And you can always invoke it with SomeClass.isFeatureSelected.
If you already have the pojo of the response then you can define a variable in the pojo and change the value on button click on that position. As define by ChrisZ.
But if as you don't have pojo I will suggest you to create a List of Boolean size same as the recyclerView item size with false value. Once you click on the button make the list boolean to true at that position so you can know on which position you already clicked and change the UI with the bool value at that position.
Create a boolean variable such as:
boolean isClicked = false; and int pos = -1;
Then the first time you changed the button background change the boolean to true and pos = position;.
Then in the onBindViewHolder of your RecyclerView do this:
if(isClicked && position == pos){ // check the state of the button and the adapter position.
// change your background here
}

Android studio recylerview in fragment using data from firestore [duplicate]

This question already has an answer here:
How to display data from Firestore in a RecyclerView with Android?
(1 answer)
Closed 4 years ago.
I am currently developing a mobile app in Android Studio. I have a collection in Firebase firestore called Leagues. When I open a fragment from the navigation drawer, the recyclerview is empty. I have two buttons at the top of the layout, both of which open an alert dialog. When I click on either of the buttons and click on the box to start entering text, the leagues magically appear in the recyclerview! Ideally I would like them to appear when the fragment is first opened. To give a bit more context I have a method which fetches the leagues from the collection in Firebase, but having debugged it I've found that this initially returns an empty list. Only when the edittext box in the alert dialog is pressed does the list fill up. Can anyone think why this might be the case?
Thanks in advance
Edit:
public class LeaguesFragment extends Fragment {
Button buttonCreateLeague;
Button buttonJoinLeague;
View view;
FirebaseFirestore firestore;
private String leagueID;
private String userID;
private String leagueName;
private String username;
TextView textViewMyLeagues;
RecyclerView recyclerView;
private List<Leagues> leaguesList;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_leagues, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.leaguesList);
RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(getContext(), leaguesList);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(recyclerViewAdapter);
buttonCreateLeague = (Button) view.findViewById(R.id.buttonCreateLeague);
buttonJoinLeague = (Button) view.findViewById(R.id.buttonJoinLeague);
textViewMyLeagues = (TextView) view.findViewById(R.id.textViewMyLeagues);
firestore = FirebaseFirestore.getInstance();
userID = FirebaseAuth.getInstance().getUid();
firestore.collection("users").document(userID).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if(task.isSuccessful()) {
DocumentSnapshot documentSnapshot = task.getResult();
username = documentSnapshot.getString("name");
}
}
});
buttonCreateLeague.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
leagueID = CreateLeagueID.randomString(6);
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setMessage("Enter league name");
final EditText input = new EditText(getContext());
alert.setView(input);
alert.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
leagueName = input.getText().toString().trim();
createLeague(leagueID, leagueName);
addUserToLeague(leagueID, username);
addLeagueToUser(leagueID, userID, leagueName);
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Cancelled.
}
});
alert.show();
}
});
buttonJoinLeague.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setMessage("Enter league code");
final EditText input = new EditText(getContext());
alert.setView(input);
alert.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
leagueID = input.getText().toString().trim();
firestore.collection("leagues").document(leagueID).collection("members").document(username).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if(task.isSuccessful()) {
DocumentSnapshot documentSnapshot = task.getResult();
if(documentSnapshot.exists()) {
Toast.makeText(getActivity(), "Already part of this league", Toast.LENGTH_SHORT).show();
}
else {
firestore.collection("leagues").document(leagueID).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot documentSnapshot = task.getResult();
if (documentSnapshot.exists()) {
leagueName = documentSnapshot.getString("leagueName");
addUserToLeague(leagueID, username);
addLeagueToUser(leagueID, userID, leagueName);
}
else {
Toast.makeText(getActivity(), "That league does not exist", Toast.LENGTH_SHORT).show();
}
}
}
});
}
}
}
});
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Cancelled.
}
});
alert.show();
}
});
return view;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
leaguesList = new ArrayList<>();
firestore = FirebaseFirestore.getInstance();
userID = FirebaseAuth.getInstance().getUid();
firestore.collection("users").document(userID).collection("leagues").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#javax.annotation.Nullable QuerySnapshot queryDocumentSnapshots, #javax.annotation.Nullable FirebaseFirestoreException e) {
if(e != null) {
Log.d(TAG, "Error : " + e.getMessage());
}
for(DocumentChange doc: queryDocumentSnapshots.getDocumentChanges()) {
if(doc.getType() == DocumentChange.Type.ADDED) {
//leagueID = doc.getDocument().getString("leagueID");
//leagueName = doc.getDocument().getString("leagueName");
Leagues leagues = doc.getDocument().toObject(Leagues.class);
leaguesList.add(leagues);
}
}
}
});
}
having debugged it I've found that this initially returns an empty list.
Yes, this the normal behaviour. You cannot use now something that hasn't been loaded yet. With other words, you cannot simply create the leaguesList variable as global variable and use it outside the onEvent() method because it will always be empty due the asynchronous behaviour of this method. This means that by the time you are trying to use that list outside that method, the data hasn't finished loading yet from the database and that's why is not accessible. A quick solve for this problem would be to use leaguesList list only inside the onEvent() method, otherwise I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.
Maybe the problem is your leaguesList still empty when onCreateView is trigger. And when onEvent from firestore trigger you not notify data set change the adapter.

Categories

Resources