How to save multiple checked checkbox of recycler view in firebase? - android

`
public class moodspojo {
private int moodimg;
private String mood;
private boolean moodcheck;
public moodspojo(int moodimg, String mood,boolean moodcheck) {
this.moodimg = moodimg;
this.mood = mood;
this.moodcheck=moodcheck;
}
public int getMoodimg() {
return moodimg;
}
public String getMood() {
return mood;
}
public boolean isMoodcheck() {
return moodcheck;
}
}
I have two activities as shown below for which I have used recycler view. I want to save all the values to firebase which are checked by the user when user click on image button in the top right corner.
I want to save those checkbox values along with its image and name.

You can have boolean variable for check box in model, and use the value from model to check and unCheck checkBox in the RecyclerView.
When click on check box just flip the value in model also.

Add a public default constructor to your class public moodspojo(){/* No code needed */} and change the name of isMoodcheck() to getMoodcheck()
And then to store it into firebase, use this code
FirebaseDatabase.getInstance().getReference().setVaue(moodspojo.class);
You can read more about how to read and write to firebase realtime database over here https://firebase.google.com/docs/database/android/read-and-write
PS: Please follow convention. First letter of class should be capital
Thanks

Related

Cannot read country code selected in a spinner Android

I am working on an app in which users have to select a country code, i was successful in creating a spinner for the said purpose as shown in this link:
Creating a spinner for choosing country code
But i am getting problem in reading the value selected in the spinner.
{
String abc = onCountryPickerClick();//abc is always null
}
public String onCountryPickerClick (){
ccp.setOnCountryChangeListener(new CountryCodePicker.OnCountryChangeListener() {
#Override
public void onCountrySelected() {
selected_country_code = ccp.getSelectedCountryCodeWithPlus();
}
});
return selected_country_code;
}
When String abc = onCountryPickerClick(); is being invoked, the selected_country_code value will be assigned to abc.
When your CountryCodePicker.OnCountryChangeListener's onCountrySelected() method is being invoked, the ccp.getSelectedCountryCodeWithPlus();'s value gets assigned to selected_country_code. Since String is immutable, changing selected_country_code's value won't change the value of abc, nor the return selected_country_code; will be invoked.
One of possible solutions would be to change your CountryCodePicker.OnCountryChangeListener anonymous implementation to assign the selected country value to abc e.g.
#Override
public void onCountrySelected() {
selected_country_code = ccp.getSelectedCountryCodeWithPlus();
abc = selected_country_code
}
Callbacks are not synchronous. Unfortunately, you cannot simply do String abc = onCountryPickerClick(); because what you are returning is something that is not yet set. Let's go through your code:
ccp.setOnCountryChangeListener(
new CountryCodePicker.OnCountryChangeListener() {
#Override
public void onCountrySelected() {
selected_country_code = ccp.getSelectedCountryCodeWithPlus();
}
});
The code seems to say that when the country is selected in the spinner, you assign the value of selected_country_code. Assuming this is an action triggered by the user, when you call String abc = onCountryPickerClick();, how can you be sure the user has selected anything? This is the issue. You cannot be sure that the user has already selected the option and returning the value is not enough.
You can solve this in many ways. You can for example keep propagating the callback:
public void onCountryPickerClick(OnCountryChangeListener listener){
ccp.setOnCountryChangeListener(listener);
}
// Anywhere you call this
onCountryPickerClick(new CountryCodePicker.OnCountryChangeListener() {
#Override
public void onCountrySelected() {
// Here do whatever you want with the selected country
}
});
The above approach is not very different than what you have now. There are other options. You could use java observables i.e.:
class CountryCodeObservable extends Observable {
private String value;
public CountryCodeObservable(String value) {
this.value = value;
}
public void setCountryCode(String countryCode) {
value = countryCode;
setChanged();
notifyObservers(value);
}
}
public CountryCodeObservable onCountryPickerClick(){
CountryCodeObservable retValue = new CountryCodeObservable("");
ccp.setOnCountryChangeListener(
new CountryCodePicker.OnCountryChangeListener() {
#Override
public void onCountrySelected() {
retValue.setCountryCode(ccp.getSelectedCountryCodeWithPlus());
}
});
return retValue;
}
// Then when calling this method you can do something like:
CountryCodeObservable observable = onCountryPickerClick();
observable.addObserver((obj, arg) -> {
// arg is the value that changed. You'll probably need to cast it to
// a string
});
The above example lets you add more than one observable. It might be too much for your use case, I just thought it illustrates another approach and also the asynchronicity of this situation.
Again, there are even more ways to solve this, the key is that you can't simply return a string and hope it changes when the user selects anything.

manage null boolean with RxJava2 PublishSubject

I'm implementing the MVP design pattern. My presenter receives the new values from the view. I want to manage the state of a next button by automatically check if everything is valid when values are updated on the view.
In my form I have an optional part which is displayed only if the user select the correct option.
In this optional part I have a binary question. If the part is not displayed I need to set the value of the question to null on the Presenter side.
For example, the user select the option and the optional part is displayed. The user select the answer. Then the user change the option and the optional part is hidden. In that case I need to set the answer to the optional question to null, for the answer to not be already selected if the user display the optional part again.
To do so, I call a method on the Presenter with a null value instead of true/false.
Here is the code:
private final PublishSubject<Boolean> mObsOptionalAnswer = PublishSubject.create();
public MyPresenter(){
// Combine all the values together to enable/disable the next button
Observable.combineLatest(
// ... other fields
// I need this to return false if the optional part is
// displayed but nothing is selected
mObsOptionalAnswer.map(this::isValid),
(...) -> ...
).subscrible(enable ->{
mView.enableBtn(enable);
});
}
public void myFunction(Boolean isSomething){
// ... some code
mObsOptionalAnswer.onNext(isSomething);
}
private boolean isValid(Boolean value){
return value != null;
}
The problem is, since RxJava 2, null values are not allowed in the onNext() method.
So, how am I supposed to manage that?
If you want to be able to send a null value, you can use a wrapper. In this configuration, you send the wrapper, which isn't null even if the value itself is.
public class BooleanWrapper {
public final Boolean value;
public BooleanWrapper(Boolean value) {
this.value = value;
}
}
Your PublishSubject<Boolean> becomes a PublishSubject<BooleanWrapper> and you just have to create the wrapper and de-reference your Boolean when needed :
mObsOptionalAnswer.onNext(new BooleanWrapper(isSomething));
and
mObsOptionalAnswer.map(wrapper -> this.isValid(wrapper.value))
If you need to do that more than once in your code, you can create a generic wrapper (as described by this tutorial) :
public class Optional<M> {
private final M optional;
public Optional(#Nullable M optional) {
this.optional = optional;
}
public boolean isEmpty() {
return this.optional == null;
}
public M get() {
return optional;
}
}
you could use a constante Boolean object
public static final Boolean RESET_VALUE = new Boolean(false);
and you can emit this instead of emitting null. The receiver would have to check against this instance and behaving accordingly. Eg.
.subscrible(enable ->{
if (enable != RESET_VALUE) {
mView.enableBtn(enable);
}
});

MvvmCross Dynamic ListView with Groups

I'm developing an app for Android using Xamarin & MvvmCross. A simple version of View Models might look something like this:
public abstract class PersonViewModelBase
{
public string Name { get; set; }
}
public interface ICanRemove
{
MvxCommand RemoveCommand { get; }
}
public class LonelyPersonViewModel : PersonViewModelBase, ICanRemove
{
public bool IsHappy { get; set; }
public MvxCommand RemoveCommand { get { return new MvxCommand(() => RemoveFriend())); } }
private void RemoveFriend()
{
// Sends msg to remove a friend (using IMvxMessenger)
}
}
public class TiredPersonViewModel : PersonViewModelBase, ICanRemove
{
public int HoursSleepNeeded { get; set; }
// [ICanRemove implementation]
}
public class FriendlyPersonViewModel : PersonViewModelBase
{
public List<PersonViewModelBase> Friends { get; set; }
public MvxCommand AddFieldCommand
{
get
{
return new MvxCommand(
() => AddFriend());
}
}
private void AddFriend()
{
}
}
public class FriendsViewModel : MvxViewModel
{
public void Init()
{
Friends.Add(new LonelyPersonViewModel { Name = "Friend 1" });
Friends.Add(new TiredPersonViewModel { Name = "Friend 2" });
var friend3 = new FriendlyPersonViewModel { Name = "Friend 3" };
friend3.Friends.Add(new LonelyPersonViewModel { Name = "SubFriend 1" });
friend3.Friends.Add(new TiredPersonViewModel { Name = "SubFriend 2" });
Friends.Add(friend3);
Friends.Add(new LonelyPersonViewModel { Name = "Friend 4" });
var friend5 = new FriendlyPersonViewModel { Name = "Friend 5" };
var conjoinedFriend1 = new ConjoinedPersonViewModel { Name = "MultiPerson 1" };
conjoinedFriend1.CoPeople.Add(new TiredPersonViewModel { Name = "Jim" });
conjoinedFriend1.CoPeople.Add(new LonelyPersonViewModel { Name = "Nancy" });
friend5.Friends.Add(conjoinedFriend1);
Friends.Add(friend5);
}
public ObservableCollection<PersonViewModelBase> Friends { get; set; } = new ObservableCollection<PersonViewModelBase>();
}
The Friends view will be a ListView that displays the Friends as either a flat item or another list of friends. So it could look like this:
Friend 1
Friend 2
Friend 3 [Add]
SubFriend 1 [Del]
SubFriend 2 [Del]
Friend 4
Friend 5 [Add]
MultiPerson 1 [Del]
Jim
Nancy
The [Add] and [Del] are buttons that bind to the Add/Delete commands on the ViewModels. Currently, I'm using the CustomAdapter from the PolymorphicListView example, so each ViewModel is mapped to a custom layout. However, I don't currently have the full info displaying for FriendlyPersonViewModel or ConjoinedPersonViewModel.
I'm torn on how to continue:
I looked into doing nested listviews and found that it's not a good UX and I didn't go down through actually connecting the custom adapter to the child listviews.
I started the work to flatten the lists manually and having the Friends collection in the FriendsListView handle the Add/Remove. However, I need the subfriends to show up under the proper friend and they are currently just showing up at the bottom of the list, which is not idea, as the actual ViewModels are slightly more complex and would cause quite a bit of redundancy due to the FriendlyPeople names being repeated for each Friend added.
I looked at the old GroupedListView example from the Conference example, but each friend won't actually be in a group, some will be displayed alone.
Below is how I've got my current app working so far. The first Dark Blue section with the "Add" button was used to add the later dark blue sections; same for the Green sections. As I mentioned above, I'd like to have the later Dark Blue sections show up with the first Dark Blue section when I hit Add. I'd like for the first blue/green section to essentially be a header and have the next blue/green section directly below it; then hit add and have the next proper color show up under the right section without another header.
Does anyone have any suggestions or guidance on how to achieve this with Xamarin.Android with MVVMCross?
Thanks!
-g
Afterthought: It looks like there is an InsertItem on ObservableCollection, if I find the location of the last item added for the secrion I want to add the next PersonBase to, will the UI update properly? (Already left desk, or I'd check.)
UPDATE
Simply inserting the item using Insert(idx,item) will in fact update the UI properly and display the new item in the correct location. The next step would be, how do you style the items such that they are obviously a "group"?

Android: Using spinner to update an RealmObject

I have two RealmObjects, something like,
public class Dog extends RealmObject {
#Required
private String name;
private int age;
}
public class Person extends RealmObject {
#Required
private String name;
private Dog dog; // A person has only one dog (a relationship)
}
In one of the activities, I want to let the user select the dog for the given person.
I thought I will use a spinner.
I also got a sample code from Realm-Examples, that did similar stuff for the ListView.
public class DogListAdapter extends RealmBaseAdapter<Dog> implements SpinnerAdapter
So far everything works fine. The spinner list automatically updates to reflect changes in the realm.
But, when I have to first display the GUI, I want to set the selected item to the current Person.dog.name.
What is the best way to do this?
I am doing something like this in onResume():
dogNameSpinner.setSelection(RealmUtils.resultIndexOf(dogsResult, person.getDog()));
where, the RealmUtils.resultIndexOf is a small utility function:
public static int resultIndexOf(RealmResults results, RealmObject obj) {
for(int i=0; i < results.size(); i++ ) {
if(results.get(i) == obj) {
return i;
}
}
return 0;
}
This does not work. I suspect may be because the realm.changeListeners get called and the spinner resets to the first item whenever items are updated.. ??
I suppose there could be a better way to do this as it should be a common model-view use case.

Button Text and Booleans (Simple Android App)

I'm build the Fun Facts app on the Android Development Track. I decided to take a exploratory detour and try to create a very basic introductory message to the user. I changed the factTextView text to "You can click the button below to see a new fact!" and changed the showFactButton text to "Try it out!"
From there, I changed the final line onClick object (is that an object?) to the following:
public void onClick(View view) {
String fact = mFactBook.getFact();
// Update the label with our dynamic fact
factLabel.setText(fact);
// Set button text to new fact prompt
showFactButton.setText("Show another fun fact.");
This seems to work fine. However, I feel like "updating" the button text to the same new string on every press isn't always the best practice, even if it is easy and readable. I tried to add a boolean that will check the text of the button, and update it only if it has not already been updated. This is what I've come up with so far:
View.OnClickListener listener = new View.OnClickListener() {
#Override
public String launchText = getResources().getString(R.string.start_text);
public String nextText = getResources().getString(R.string.next_text);
public String buttonText = (String) showFactButton.getText();
public boolean updateLaunchText() {
if (buttonText.equals(launchText)) {
buttonText.replaceAll(launchText, nextText);
return true;
}
else {
return true;
}
}
public void onClick(View view) {
String fact = mFactBook.getFact();
// Update the label with our dynamic fact
factLabel.setText(fact);
}
};
With the following added to strings.xml:
<string name="start_text">Try it out!</string>
<string name="next_text">Show another Fun Fact!</string>
No errors, but the button text stays on "Try it out!" I'm sure that all the extra objects are totally unnecessary compared to the first, working method for the scope of this app, but I'd still like to figure it out since I don't really have any idea what I'm doing with the boolean.
Questions: 1) What am I missing in the longer boolean approach? 2) What's the actual most efficient approach to accomplish this task?
Did you connect the listener to the button object?Without that connection no logic is applied to a button click.It goes like this:
buttonName.setOnClickListener(...)
You'd have to initialize the button object first though :)
Where r u call to method updateLaunchText() ?
you should change the objects to global object (not to create the into the listener):
private String launchText = getResources().getString(R.string.start_text);
private String nextText = getResources().getString(R.string.next_text);
private String buttonText = (String) showFactButton.getText();
and take the method updateLaunchText() out of the listener too.
and then into the onClick(View view) call to updateLaunchText() like this:
public void onClick(View view) {
updateLaunchText();
String fact = mFactBook.getFact();
// Update the label with our dynamic fact
factLabel.setText(fact);
}

Categories

Resources