Save Boolean state while restarting the application - java

I have 6 boolean variables which I have initialized as false. There are 6 different imageviews which are associated with these 6 boolean false variables. When the user clicks any of these image, there respective boolean variable is switched to true and when the user again clicks the same image, it will turn to false like on and off. After being satisfied with the selected options, the user can click the done button and the data will be save in the firebase accordingly to whether which options are true and which are false.
My problem is that whenever the application is restarted, all boolean variables are again initialized to false, I understand the fact that, the application restarts for OnCreate class due to which the variables are again false. How can I write a certain code which can save the state of these variables even after application restarts?
Below is my Code:
boolean checkcar = false, checkPickUp = false, checkTruck = false, checkCycle = false, checkBike = false, checkMen = false;
private FirebaseAuth firebaseAuth;
private String currentUserID;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
myTransport = inflater.inflate(R.layout.fragment_transport, container, false);
firebaseAuth = FirebaseAuth.getInstance();
currentUserID = firebaseAuth.getCurrentUser().getUid();
carImage = myTransport.findViewById(R.id.carTransport);
pickUpImage = myTransport.findViewById(R.id.pickUpTransport);
truckImage = myTransport.findViewById(R.id.truckTransport);
cycleImage = myTransport.findViewById(R.id.cyclerTransport);
bikeImage = myTransport.findViewById(R.id.bikeTransport);
menImage = myTransport.findViewById(R.id.menTransport);
done = myTransport.findViewById(R.id.selectUserTransportBtn);
transport = FirebaseDatabase.getInstance().getReference().child("UserProfileDetails").child(currentUserID).child("Transport");
MarkUserRegisteredTransport();
carImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!checkcar) {
carImage.setColorFilter(carImage.getContext().getResources().getColor(R.color.TransportAfterClicked), PorterDuff.Mode.SRC_ATOP);
checkcar = true;
} else {
carImage.setColorFilter(carImage.getContext().getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
checkcar = false;
}
}
});
pickUpImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!checkPickUp) {
pickUpImage.setColorFilter(pickUpImage.getContext().getResources().getColor(R.color.TransportAfterClicked), PorterDuff.Mode.SRC_ATOP);
checkPickUp = true;
} else {
pickUpImage.setColorFilter(pickUpImage.getContext().getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
checkPickUp = false;
}
}
});
truckImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!checkTruck) {
truckImage.setColorFilter(truckImage.getContext().getResources().getColor(R.color.TransportAfterClicked), PorterDuff.Mode.SRC_ATOP);
checkTruck = true;
} else {
truckImage.setColorFilter(truckImage.getContext().getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
checkTruck = false;
}
}
});
cycleImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!checkCycle) {
cycleImage.setColorFilter(cycleImage.getContext().getResources().getColor(R.color.TransportAfterClicked), PorterDuff.Mode.SRC_ATOP);
checkCycle = true;
} else {
cycleImage.setColorFilter(cycleImage.getContext().getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
checkCycle = false;
}
}
});
bikeImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
menImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!checkMen) {
menImage.setColorFilter(menImage.getContext().getResources().getColor(R.color.TransportAfterClicked), PorterDuff.Mode.SRC_ATOP);
checkMen = true;
} else {
menImage.setColorFilter(menImage.getContext().getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
checkMen = false;
}
}
});
here is when user can click done and the information is updated in the firebase with true or false with their res
done.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
HashMap userTransport = new HashMap();
userTransport.put("check Car", checkcar);
userTransport.put("check PickUp", checkPickUp);
userTransport.put("check Truck", checkTruck);
userTransport.put("check Cycle", checkCycle);
userTransport.put("check bike", checkBike);
userTransport.put("check Men", checkMen);
transport.updateChildren(userTransport).addOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()) {
Toast.makeText(getContext(), "Transportation information updated", Toast.LENGTH_LONG).show();
} else {
String message = task.getException().getMessage();
Toast.makeText(getContext(), "Error Occured: " + message, Toast.LENGTH_SHORT).show();
}
}
});
}
});
return myTransport;
}

According to your comment:
well i needed the data to be stored even after the user deletes the application just like instagram and facebook
I would like to tell you that either SharedPreferences nor Bundle won't help in this case. Both tehniques when used, do not persist across application uninstalls. If you reinstall the app, your SharedPreferences or your Bundle will be empty and you will not be able to use any data at all.
To solve this, I recommend you add that data to database and everytime the user wants to update his preferences, change the data in database accordingly. So create six new properties of type boolean under your transport object and set/update them accordingly with user's choice.

You can use onSaveInstanceState to save the boolean values, and fetch the values in onCreate or onRestoreInstanceState.
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("boolean1", booleanValue1);
outState.putString("boolean2", booleanValue2); //and so on
}
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if(savedInstanceState!=null){
if(getString("boolean1") != null){
booleanValue1 = savedInstanceState.getString("boolean1");
}
}
}

Use SharedPreferences, if the application is killed the values saved will not be deleted or reset.
PreferenceManager mManager = PreferenceManager.getDefaultSharedPreferences(context);
//example methods
public static boolean getBool(String resName, boolean defValue) {
return mManager.getBoolean(resName, defValue);
}
public static void setBool(String resName, boolean value) {
mManager.edit()
.putBoolean(resName, value)
.apply();
}
PS: Well, if you uninstall the app or delete the app data (in "Settings", for example) datas will be destroyed

Related

Checkboxes not working correctly in RecyclerView

I am using a RecyclerView to display a list of activities saved in my Firebase database. I have added a checkbox to the layout of the activity view so that the user can select whether they want to add this activity to their audit profile.
When the user clicks the checkbox to select the activity, I want to add this activity to their profile (which is stored in a separate table) and update a field in the original activity table to say that it is now included in the audit profile. When they uncheck the box, it is removed from their profile and the original activity is updated to reflect this.
However, when I try doing this, my checkboxes start behaving incorrectly (such as a checkbox being checked that definitely hasn't been clicked by the user, checkboxes not staying ticked). This only happens when I have both the code to add the activity to the profile and to update the original activity.
Any ideas? I think it might be something to do with state, but I'm not sure how to go about doing this.
My code is as follows
auditAdapter = new FirestoreRecyclerAdapter<Activity, AuditBuilder.AuditViewHolder>(auditBuilder) {
#Override
protected void onBindViewHolder(#NonNull final AuditBuilder.AuditViewHolder auditViewHolder, int i, #NonNull final Activity activity) {
auditViewHolder.aAuditActivityName.setText(activity.getActivity_Name());
auditViewHolder.aAuditActivityType.setText(activity.getActivity_Type());
auditViewHolder.aAuditActivityDate.setText(activity.getActivity_Date());
final String docId = auditAdapter.getSnapshots().getSnapshot(i).getId();
auditViewHolder.auditCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
//ADD DOCUMENT ID TO DATABASE
DocumentReference documentReference = fStore.collection("audits")
.document(user.getUid())
.collection("myAuditActivities")
.document(docId);
Map<String, Object> audit = new HashMap<>();
audit.put("Activity_ID", docId);
audit.put("Activity_Name", activity.getActivity_Name());
audit.put("Activity_Description", activity.getActivity_Description());
audit.put("Activity_Type", activity.getActivity_Type());
audit.put("Activity_Date", activity.getActivity_Date());
audit.put("Activity_Hours", activity.getActivity_Hours());
audit.put("Activity_Mins", activity.getActivity_Mins());
audit.put("Activity_Ref1", activity.getActivity_Ref1());
audit.put("Activity_Ref2", activity.getActivity_Ref2());
audit.put("Activity_Ref3", activity.getActivity_Ref3());
audit.put("Activity_Ref4", activity.getActivity_Ref4());
audit.put("Image_URL", activity.getImage_URL());
audit.put("In_Audit", true);
documentReference.set(audit).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d("TAG", "Activity successfully added to audit");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(AuditBuilder.this, "Error, try again", Toast.LENGTH_SHORT).show();
}
});
//UPDATE BOOLEAN IN_AUDIT IN CPD ACTIVITIES LOCATION IN DATABASE TO TRUE
DocumentReference updateActivity = fStore.collection("cpdActivities")
.document(user.getUid())
.collection("myCPD")
.document(docId);
Map<String, Object> updateBoolean = new HashMap<>();
updateBoolean.put("In_Audit", true);
updateActivity.update(updateBoolean).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d("TAG", "In_Audit successfully updated");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("TAG", "In_Audit update failed");
}
});
} else {
//CHECKBOX UNCHECKED, DELETES FROM AUDIT TABLE
DocumentReference docRef = fStore.collection("audits")
.document(user.getUid())
.collection("myAuditActivities")
.document(docId);
docRef.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d("TAG", "Activity successfully removed from audit");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(AuditBuilder.this, "Error, try again", Toast.LENGTH_SHORT).show();
}
});
//UPDATE BOOLEAN IN_AUDIT IN CPD ACTIVITIES LOCATION IN DATABASE BACK TO FALSE
DocumentReference updateActivity = fStore.collection("cpdActivities")
.document(user.getUid())
.collection("myCPD")
.document(docId);
Map<String, Object> updateBoolean = new HashMap<>();
updateBoolean.put("In_Audit", false);
updateActivity.update(updateBoolean).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d("TAG", "In_Audit successfully updated");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("TAG", "In_Audit update failed");
}
});
}
}
});
auditViewHolder.view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(v.getContext(), ActivityDetails.class);
//DISPLAYS ALL THE ATTRIBUTES OF THE ACTIVITY
i.putExtra("Activity_Name", activity.getActivity_Name());
i.putExtra("Activity_Description", activity.getActivity_Description());
i.putExtra("Activity_Type", activity.getActivity_Type());
i.putExtra("Activity_Date", activity.getActivity_Date());
i.putExtra("Activity_Hours", activity.getActivity_Hours());
i.putExtra("Activity_Mins", activity.getActivity_Mins());
i.putExtra("Activity_Ref1", activity.getActivity_Ref1());
i.putExtra("Activity_Ref2", activity.getActivity_Ref2());
i.putExtra("Activity_Ref3", activity.getActivity_Ref3());
i.putExtra("Activity_Ref4", activity.getActivity_Ref4());
i.putExtra("Image_URL", activity.getImage_URL());
i.putExtra("Activity_ID", docId);
v.getContext().startActivity(i);
}
});
}
#NonNull
#Override
public AuditBuilder.AuditViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.auditbuilder_view_layout, parent,false);
return new AuditViewHolder(view);
}
};
To try fixing this problem, I have added a boolean (In_Audit) to my model as follows:
public class Activity {
private String Activity_Name;
etc
private boolean In_Audit;
public Activity(String name, String date, String hours, String minutes, String description, String ref1, String ref2, String ref3, String ref4, String type, String image_URL, boolean In_Audit){
this.Activity_Name = Activity_Name;
this.Activity_Date = Activity_Date;
this.Activity_Hours = Activity_Hours;
this.Activity_Mins = Activity_Mins;
this.Activity_Description = Activity_Description;
this.Activity_Ref1 = Activity_Ref1;
this.Activity_Ref2 = Activity_Ref2;
this.Activity_Ref3 = Activity_Ref3;
this.Activity_Ref4 = Activity_Ref4;
this.Activity_Type = Activity_Type;
this.Image_URL = Image_URL;
this.In_Audit = false;
}
public boolean isIn_Audit() {
return In_Audit;
}
public void setIn_Audit(boolean in_Audit) {
In_Audit = in_Audit;
}
}
I have then referenced this in my onBindViewHolder like this
auditAdapter = new FirestoreRecyclerAdapter<Activity, AuditBuilder.AuditViewHolder>(auditBuilder) {
#Override
protected void onBindViewHolder(#NonNull final AuditBuilder.AuditViewHolder auditViewHolder, int i, #NonNull final Activity activity) {
auditViewHolder.aAuditActivityName.setText(activity.getActivity_Name());
auditViewHolder.aAuditActivityType.setText(activity.getActivity_Type());
auditViewHolder.aAuditActivityDate.setText(activity.getActivity_Date());
auditViewHolder.auditCheckBox.setSelected(activity.isIn_Audit());
final String docId = auditAdapter.getSnapshots().getSnapshot(i).getId();
auditViewHolder.auditCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
activity.setIn_Audit(true);
} else {
activity.setIn_Audit(false);}});
But I am still having errors with my check boxes, such as without scrolling, my checking my first checkbox and it not staying clicked. I'm not 100% sure I have applied the above logic correctly however.

Android app Tab Switching Crash

I am currently having an error in my app. I have a recyclerview that loads posts from a firebase database and displays them. When I switch fragments and activities I do not get any errors. When I click the home button or tabs button on my phone and then click back into my app there is a crash with the error message,
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{777f444 position=1
id=-1, oldPos=0, pLpos:0 scrap [attachedScrap] tmpDetached no parent}
android.support.v7.widget.RecyclerView{efb45c8 VFED..... .F......
0,0-1080,1497 #7f0900c2 app:id/postList},
adapter:com.sender.hp.sender.DashboardFragment$2#efd661,
layout:android.support.v7.widget.LinearLayoutManager#9760586,
context:com.sender.hp.sender.MainActivity#720f0fa
Whenever I hit the back button on my phone and my app gets closed, If I go into my tabs and hit back into my app it works fine. I don't have an onBackPressed listener.
Here is my code,
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<postsGetInfo, postsGetInfoViewHolder>(postsGetInfo.class, R.layout.posts_layout,postsGetInfoViewHolder.class,postRef) {
#Override
protected void populateViewHolder(final postsGetInfoViewHolder viewHolder, postsGetInfo model, int position) {
TextView txtUpvote = (TextView) viewHolder.myView.findViewById(R.id.txtUpvoteCount);
final String postKey = getRef(position).getKey();
viewHolder.setUsername(model.getUsername());
viewHolder.setTime(model.getTime());
viewHolder.setDate(model.getDate());
viewHolder.setDescription(model.getDescription());
viewHolder.setProfileImage(model.getProfileimage());
viewHolder.setImage(model.getImage());
viewHolder.setDisplayvotes(model.getDisplayvotes());
viewHolder.myView.findViewById(R.id.imgDownvote).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
UpdateTheDisplayVotes(postKey);
++getDownvotes;
--getDisplayVotes;
String txtDisplayVotes = Integer.toString(getDisplayVotes);
postRef.child(postKey).child("downvotes").setValue(getDownvotes);
postRef.child(postKey).child("displayvotes").setValue(txtDisplayVotes);
}
});
viewHolder.myView.findViewById(R.id.imgUpvote).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
UpdateTheDisplayVotes(postKey);
++getUpvotes;
++getDisplayVotes;
String txtDisplayVotes = Integer.toString(getDisplayVotes);
postRef.child(postKey).child("upvotes").setValue(getUpvotes);
postRef.child(postKey).child("displayvotes").setValue(txtDisplayVotes);
}
});
viewHolder.myView.findViewById(R.id.imgPost).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent editIntent = new Intent((getActivity()),postEdit.class);
editIntent.putExtra("PostKey",postKey);
startActivity(editIntent);
}
});
}
};
postList.setAdapter(firebaseRecyclerAdapter);
}
private void UpdateTheDisplayVotes(final String key) {
VoteListener = postRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
if (dataSnapshot.hasChild("displayvotes")){
displayvotes = dataSnapshot.child(key).child("displayvotes").getValue().toString();
getDisplayVotes = Integer.parseInt(displayvotes);
}
if (dataSnapshot.hasChild("upvotes")){
upvotes = dataSnapshot.child(key).child("upvotes").getValue().toString();
getUpvotes = Integer.parseInt(upvotes);
}
if (dataSnapshot.hasChild("downvotes")){
downvotes = dataSnapshot.child(key).child("downvotes").getValue().toString();
getDownvotes = Integer.parseInt(downvotes);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onStart() {
super.onStart();
firebaseRecyclerAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
if (firebaseRecyclerAdapter != null){
firebaseRecyclerAdapter.cleanup();
}
}
Anyone know how to fix? Thanks for any answers!
This error occurs when the adapter or list in the adapter is cleared.
Call notifyDataSetChanged() when adapter is cleared.
#Override
public void onStop() {
super.onStop();
if (firebaseRecyclerAdapter != null){
firebaseRecyclerAdapter.cleanup();
firebaseRecyclerAdapter.notifyDataSetChanged();
}
}

Keep user logged in but exit android app on double pressing back

I am using Firebase to sign in the user and have implemented the code to exit the app on double click. But the problem is the same screen is popping up again.
I tried a workaround setting a SharedPreference and then checking that in mAuthListner. But it did not work.
Here are the relevant sections of the code:
mAuthListener = new FirebaseAuth.AuthStateListener(){
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
SharedPreferences d= getSharedPreferences("backPressed", Context.MODE_PRIVATE);
Boolean t = d.getBoolean("back",false);
if (firebaseAuth.getCurrentUser() != null && !t) {
startActivity(new Intent(MainActivity.this, Second.class));
}
if (t) {
d.edit().putBoolean("back",false);
}
}
};
Code for back button pressed:
boolean doubleBackToExitPressedOnce = false;
private Handler mHandler = new Handler();
private final Runnable mRunnable = new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
};
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
SharedPreferences d= getSharedPreferences("backPressed",Context.MODE_PRIVATE);
d.edit().putBoolean("back",true);
finish();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
mHandler.postDelayed(mRunnable, 2000);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mHandler != null) { mHandler.removeCallbacks(mRunnable); }
}
How can I exit the app on back pressed twice while keeping the user logged in?
This is not a Firebase issue as Firebase will not log out until you specifically call the "Log Out" method.
You do not need SharedPreferences. Just set an Activity level variable BackOnce to False then set it in the OnBackPressed as necessary.
boolean BackOnce = false;
#Override
public void onBackPressed() {
if (BackOnce) {
finish();
} else {
BackOnce = true;
Snackbar sb = Snackbar.make(myView, "Press back again to close app", Snackbar.LENGTH_SHORT);
sb.addCallback(new Snackbar.Callback() {
#Override
public void onDismissed(Snackbar snackbar, int event) {
super.onDismissed(snackbar, event);
BackOnce = false;
}
});
sb.show();
}
}

Firebase getUid() function only returns NULL

PostListFragment is extended by other fragments in my app. I need the uid of the current user, but it always returns null. When I try to run my app, I always get the error:
FATAL EXCEPTION: main
Process: com.example.cleeg.squad, PID: 8524
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
at com.example.cleeg.squad.fragments.PostListFragment.getUid(PostListFragment.java:162)
at com.example.cleeg.squad.fragments.MyPostsFragment.getQuery(MyPostsFragment.java:19)
at com.example.cleeg.squad.fragments.PostListFragment.onActivityCreated(PostListFragment.java:76)
I've tried to find out why this is online, but I just get more confused and I don't really know how to fix it.
The function getUid() is at the bottom of the code.
public abstract class PostListFragment extends Fragment {
private static final String TAG = "PostListFragment";
private DatabaseReference mDatabaseReference;
private FirebaseRecyclerAdapter<Post, PostViewHolder> mAdapter;
private RecyclerView mRecycler;
private LinearLayoutManager mManager;
public PostListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.fragment_all_posts, container, false);
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
mRecycler = (RecyclerView) rootView.findViewById(R.id.messages_list);
mRecycler.setHasFixedSize(true);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Set up Layout Manager, reverse layout
mManager = new LinearLayoutManager(getActivity());
mManager.setReverseLayout(true);
mManager.setStackFromEnd(true);
mRecycler.setLayoutManager(mManager);
// Set up FirebaseRecyclerAdapter with the Query
Query postsQuery = getQuery(mDatabaseReference);
mAdapter = new FirebaseRecyclerAdapter<Post, PostViewHolder>(Post.class, R.layout.item_post,
PostViewHolder.class, postsQuery) {
#Override
protected void populateViewHolder(final PostViewHolder viewHolder, final Post model, final int position) {
final DatabaseReference postRef = getRef(position);
// Set click listener for the whole post view
final String postKey = postRef.getKey();
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Launch PostDetailActivity
Intent intent = new Intent(getActivity(), PostDetailActivity.class);
intent.putExtra(PostDetailActivity.EXTRA_POST_KEY, postKey);
startActivity(intent);
}
});
// Determine if the current user has liked this post and set UI accordingly
if (model.stars.containsKey(getUid())) {
viewHolder.starView.setImageResource(R.drawable.ic_toggle_star_24);
} else {
viewHolder.starView.setImageResource(R.drawable.ic_toggle_star_outline_24);
}
// Bind Post to ViewHolder, setting OnClickListener for the star button
viewHolder.bindToPost(model, new View.OnClickListener() {
#Override
public void onClick(View starView) {
// Need to write to both places the post is stored
DatabaseReference globalPostRef = mDatabaseReference.child("posts").child(postRef.getKey());
DatabaseReference userPostRef = mDatabaseReference.child("user-posts").child(model.uid).child(postRef.getKey());
// Run two transactions
onStarClicked(globalPostRef);
onStarClicked(userPostRef);
}
});
}
};
mRecycler.setAdapter(mAdapter);
}
private void onStarClicked(DatabaseReference postRef) {
postRef.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
Post p = mutableData.getValue(Post.class);
if (p == null) {
return Transaction.success(mutableData);
}
if (p.stars.containsKey(getUid())) {
// Unstar the post and remove self from stars
p.starCount = p.starCount - 1;
p.stars.remove(getUid());
} else {
// Star the post and add self to stars
p.starCount = p.starCount + 1;
p.stars.put(getUid(), true);
}
// Set value and report transaction success
mutableData.setValue(p);
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b,
DataSnapshot dataSnapshot) {
// Transaction completed
Log.d(TAG, "postTransaction:onComplete:" + databaseError);
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
if (mAdapter != null) {
mAdapter.cleanup();
}
}
public String getUid() {
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
public abstract Query getQuery(DatabaseReference databaseReference);
}
The crash is because of no user is linked, i.e., getCurrentUser() is null. Please make user you have the user before fetching the userid.
if (FirebaseAuth.getInstance().getCurrentUser() != null) {
mUserID = FirebaseAuth.getInstance().getCurrentUser().getUid();
} else {
//login or register screen
}
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is authenticated and now you can access uesr's properties as followings
mUserID = user.getUid();
} else {
// User is authenticated. So, let's try to re-authenticate
AuthCredential credential = EmailAuthProvider
.getCredential("user#example.com", "password1234");
// Prompt the user to re-provide their sign-in credentials
user.reauthenticate(credential)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Log.d(TAG, "User re-authenticated.");
}
});
}
You can get details on it in this firebase document: https://firebase.google.com/docs/auth/android/manage-users

CheckBox state inside RecyclerView

I created a Checkbox, however, whenever I click a few Items random checkboxes become clicked. I have a recycler view, and I have an adapter class as well. Here is my CheckBox method can anyone tell me the problem?
public void CheckBox(View view) {
final CheckBox checkBox = (CheckBox)view;
if (checkBox.isChecked()) {
System.out.println("SET TO CHECKED");
//Input instance of selected course(CHECKED)
// TODO: 2/5/16 Need to pass in Persisted ID
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
CharSequence ID_PUT_COURSES = ((TextView) ((RelativeLayout) view.getParent()).getChildAt(1)).getText();
System.out.println(PUT);
String URL_PUT_COURSES = "URL"+ID_PUT+"\n";
System.out.print(PUT);
StringRequest UrlPut = new StringRequest(Request.Method.PUT, URL_PUT, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response + "reponse");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
System.out.println("************Answer" + error + "error");
}
});
mRequestQueue.add(UrlPutCourses);
System.out.println("Added");
}
else{
System.out.println("SET TO UNCHECKED");
//delete instance of selected course(UNCHECKED)
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
// TODO: 2/5/16 Need to pass in Persisted ID
CharSequence DELETE = ((TextView) ((RelativeLayout) view.getParent()).getChildAt(1)).getText();
System.out.print(ID_PUT_COURSES);
String UR_DELETE = "URL"+ DELETE;
StringRequest UrlDeleteCourses = new StringRequest(Request.Method.DELETE, UR_DELETE, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response + "reponse");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
System.out.println("************Answer" + error + "error");
}
});
mRequestQueue.add(UR_DELETE);
System.out.println("Deleted");
}
}
ublic class AdapterSearch extends RecyclerView.Adapter<AdapterSearch.ViewSearch>{
private LayoutInflater mLayoutInflater;
private ArrayList<Search> ListSearch=new ArrayList<>();
public AdapterSearch(Context context){
mLayoutInflater=LayoutInflater.from(context);
}
public void setListSearch(ArrayList<Search> ListSearch){
this.ListSearch=ListSearch;
notifyItemRangeChanged(0,ListSearch.size());
}
#Override
public ViewSearch onCreateViewHolder(ViewGroup parent, int viewType) {
View view= mLayoutInflater.inflate(R.layout.custom_search,(ViewGroup)null);
ViewSearch holder=new ViewSearch(view);
return holder;
}
#Override
public void onBindViewHolder(ViewSearch holder, int position) {
Search currentSearch=ListSearch.get(position);
holder.mSearchText.setText(currentSearch.getMtitle());
holder.mAnswerPointsSearch.setText(currentSearch.getMkey());
holder.mSearchId.setText(currentSearch.getMid());
holder.mCourseId.setText(currentSearch.getCourseId());
}
#Override
public int getItemCount() {
return ListSearch.size();
}
public void setFilter(ArrayList<Search> Search) {
ListSearch = new ArrayList<>();
ListSearch.addAll(Search);
notifyDataSetChanged();
}
static class ViewSearch extends RecyclerView.ViewHolder{
private TextView mSearchText;
private TextView mAnswerPointsSearch;
private TextView mSearchId;
private TextView mCourseId;
public ViewSearch (View view){
super(view);
mSearchText=(TextView)itemView.findViewById(R.id.SearchText);
mAnswerPointsSearch=(TextView)itemView.findViewById(R.id.AnswerPointsSearch);
mSearchId=(TextView)itemView.findViewById(R.id.SearchId);
mCourseId=(TextView)itemView.findViewById(R.id.CourseTextView);
}
}
}
Better late then never I'd say, it might help other people stumbling upon this issue later, so here goes.
This might not be the best solution ever, but it should work.
In your Search class, you have some variables like title and key. Add the boolean isChecked to it, and make it false by default. Also create the matching getter and setter. (I'm using isChecked() & setChecked() in this example)
In your onBindViewHolder() method, add the following lines:
CheckBox checkBox = (CheckBox) itemView.findViewById(R.id.CheckBoxID);
// Instantiating the checkbox
holder.checkBox.setChecked(currentSearch.isChecked());
// Every time the holder (one list item) is shown, this gets called.
// It sets the checked state based on what's stored in currentSearch.
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (checkBox.isChecked()) {
currentSearch.setChecked(true)
} else {
currentSearch.setChecked(false);
}
});
}
// This listens for clicks on the checkbox, and changes the checked state of
// the boolean in currentSearch to the correct state based on
// what it already was on.
Please be aware that I haven't worked with checkboxes before, so some things (like setting the checked state) might be done slightly differently from what I've described above, but this should be a working base.
You also probably want the checkboxes to only persevere until you click a button or something like that, and then have them reset. You might want to add a simple for loop for that, something like:
public void resetAllCheckBoxes() {
for (Search s : ListSearch) {
s.setChecked(false);
}
}

Categories

Resources