-1

I am working on an function that adds strings from firebase database into an existing spinner. At the moment I have 2 spinners with the first spinner taking froms from strings.xml file and the other spinner takes item from firebase. The problem is that when I select either of them they overwirte each other and the sharedPreferneces are also overwritten. My question is how would I implement adding the firebase array "array" of keys into the spinner that has the strings.xml? Thanks in advance

PS. another problem is onPause and onResume and onBackpressed clears te saredPrefs

Update:

public class HomeActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener{


private ZXingScannerView scannerView;
private final int permission_code = 1;

String [] selectedProfile;
Spinner spinner;
ArrayAdapter<CharSequence> adapter;


Spinner spinnerUser;
Map<String,Object> map;

private String userID;
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    mAuth = FirebaseAuth.getInstance();
    mFirebaseDatabase = FirebaseDatabase.getInstance();
    myRef = mFirebaseDatabase.getReference();
    FirebaseUser user = mAuth.getCurrentUser();
    userID = user.getUid();

    if(mAuth.getCurrentUser() == null){
        finish();
        startActivity(new Intent(this, MainActivity.class));
    }

    startSpinner();

}

    public void startSpinner(){

    //built in Profiles
    spinner = (Spinner) findViewById(R.id.spinnerProfiles);
    adapter = ArrayAdapter.createFromResource(this, R.array.restrictions, android.R.layout.simple_spinner_item);

    myRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // This method is called once with the initial value and again
            // whenever data at this location is updated.
            map = (Map<String, Object>) dataSnapshot.child("users").child(userID).getValue();
            ArrayList<String> array  = new ArrayList<>();
            int x = 16;
            for (Map.Entry<String,Object> entry : map.entrySet()) {
                // key contains Profile Name
                String key = entry.getKey();
                adapter.insert(key, x);
                x++;
            }
            adapter.setDropDownViewResource(android.R.layout.simple_list_item_1);
            spinner.setAdapter(adapter);
            spinner.setOnItemSelectedListener(HomeActivity.this);
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {
            //Auto Generated Method
        }
    });
}

//restores spinner object
public void restoreSpinner(){
    SharedPreferences sharedPref = getSharedPreferences("Preferences",MODE_PRIVATE);
    int profileVal = sharedPref.getInt("userProfile",-1);
    if(profileVal != -1) {
        spinner.setSelection(profileVal);
    }
}

//selects an item from the spinner and passes it to InformationActivity
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

    //Saves spinner value
    int profileVal = spinner.getSelectedItemPosition();
    SharedPreferences sharedPref = getSharedPreferences("Preferences", 0);
    SharedPreferences.Editor prefEditor = sharedPref.edit();
    prefEditor.putInt("userProfile", profileVal);
    prefEditor.apply();

    switch (profileVal) {
        case 0:
            break;
        case 1:
            selectedProfile = getResources().getStringArray(R.array.Wheat);
            break;
        case 2:
            selectedProfile = getResources().getStringArray(R.array.Crustaceans);
            break;
        case 3:
            selectedProfile = getResources().getStringArray(R.array.Eggs);
            break;
        default:
            String text = spinner.getSelectedItem().toString();
            map.get(text);

            ArrayList<String> array  = new ArrayList<>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                //Key contains Profile name
                String key = entry.getKey();
                if (key.equals(text)) {
                    // value is the corresponding list
                    Object value = entry.getValue();
                    array.addAll((ArrayList) value);
                }
            }
            //set the selected profile
            selectedProfile = array.toArray(new String[0]);
    }

}


}
  • 1
    add your crash log – Gaurav Feb 14 '18 at 11:55
  • I dont have a crash log at the moment because I changed it to 2 spinners, Im not sure how to implement it into 1 spinner –  Feb 14 '18 at 11:57
  • 1
    You say, "problem is that when I select either of them they overwirte each other" and then you are asking, "how would I implement adding the firebase array "array" of keys into the spinner that has the strings.xml". But you are already doing this. Can you be more concrete about what you are looking for? – Alex Mamo Feb 14 '18 at 12:21
  • @AlexMamo I want to have 1 spinner instead of 2 containing an array from strings.xml and firebase array keys added to the end of that spinner –  Feb 14 '18 at 19:34
  • You are asking too many questions in a single post. You might want to narrow down your question for this post to get an appropriate answer. – Karan Sharma Feb 16 '18 at 05:36

2 Answers2

1

You can create local boolean field to determine what type of data is shown in spinner. It will allow you to use one spinner view

public class HomeActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {

    String[] selectedProfile;
    Spinner spinner;
    ArrayAdapter<String> adapter;
    Map<String, Object> map = new HashMap<>();

    private String userID;
    private FirebaseDatabase mFirebaseDatabase;
    private FirebaseAuth mAuth;
    private FirebaseAuth.AuthStateListener mAuthListener;
    private DatabaseReference myRef;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        mAuth = FirebaseAuth.getInstance();
        mFirebaseDatabase = FirebaseDatabase.getInstance();
        myRef = mFirebaseDatabase.getReference();
        FirebaseUser user = mAuth.getCurrentUser();
        userID = user.getUid();

        startSpinner();
    }

    //creates spinner objects
    public void startSpinner() {
        map.clear();
        map.put(getString(R.string.Wheat), Arrays.asList(getResources().getStringArray(R.array.Wheat)));
        map.put(getString(R.string.Crustaceans), Arrays.asList(getResources().getStringArray(R.array.Crustaceans)));
        map.put(getString(R.string.Eggs), Arrays.asList(getResources().getStringArray(R.array.Eggs)));

        //built in Profiles
        spinner = findViewById(R.id.spinnerProfiles);
        adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, new ArrayList<>(map.keySet()));
        adapter.setDropDownViewResource(android.R.layout.simple_list_item_1);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(this);

        //User Profiles
        myRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                // This method is called once with the initial value and again
                // whenever data at this location is updated.
                Map<String, Object> usersMap = (Map<String, Object>) dataSnapshot.child("users").child(userID).getValue();
                ArrayList<String> array = new ArrayList<>();
                for (Map.Entry<String, Object> entry : usersMap.entrySet()) {
                    map.put(entry.getKey(), entry.getValue());
                    // key contains Profile Name
                    String key = entry.getKey();
                    array.add(key);
                }
                adapter.addAll(array);
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                //Auto Generated Method
            }
        });
    }

    //restores spinner object
    public void restoreSpinner() {
        SharedPreferences sharedPref = getSharedPreferences("Preferences", MODE_PRIVATE);
        String profileVal = sharedPref.getString("userProfile", null);
        if (profileVal != null) {
            for (int i = 0; i < adapter.getCount(); i++) {
                String item = adapter.getItem(i);
                if (profileVal.equals(item)) {
                    spinner.setSelection(i);
                    break;
                }
            }
        }
    }

    //selects an item from the spinner and passes it to InformationActivity
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        String text = spinner.getSelectedItem().toString();

        ArrayList<String> array = new ArrayList<>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            //Key contains Profile name
            String key = entry.getKey();
            if (key.equals(text)) {
                // value is the corresponding list
                Object value = entry.getValue();
                array.addAll((List) value);
            }
        }
        //set the selected profile
        selectedProfile = array.toArray(new String[0]);

        SharedPreferences sharedPref = getSharedPreferences("Preferences", 0);
        SharedPreferences.Editor prefEditor = sharedPref.edit();
        prefEditor.putString("userProfile", text);
        prefEditor.apply();
    }

    // other methods
}
Deni Erdyneev
  • 1,779
  • 18
  • 26
  • The issue I have is that I need the spinner to show both, array from strings.xml and firebase keys at the end of that spinner, is that possible? –  Feb 14 '18 at 19:35
  • @zarrexx yes, sure. I've updated a code above. Now local default strings puts first and then when Firebase user profiles comes, they added to spinner. Also I change save selected item logic – Deni Erdyneev Feb 16 '18 at 05:33
0

In order to have a single spinner that contains strings from both, strings.xml and Firebase database, you need to use a single adapter and a single ArrayList that contains combined values. In order to achieve this, you need to add those strings from the database and those string from the strings.xml to the ArrayList inside the onDataChange method. All the code regarding the spinner should be moved also inside onDataChange method. The adapter should also be set inside, otherwise the ArrayList will contains only the strings from strings.xml. I recommend you do in this way because onDataChange has an asynchronous behaviour and you cannot simply use that outside that method. This line of code, adapter.addAll(array); will never work because by the time the adapter is created, you didn't finished getting the data from the database. So the best solution is to move all your logic inside onDataChange method. See more details here about asynchronous methods.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Could you look at my update please, for some reason the app crashes i put the adapter.add(key) into the onDatachange, and set the adapter after ondatachange so It should perform fine –  Feb 15 '18 at 16:26
  • Those lines of code are inside the method but NOT inside the `onDataChange` method. You need to move them inside `onDataChange' method and outside the for loop. – Alex Mamo Feb 15 '18 at 16:39
  • I editited it again as seen above, but for some reason I get the same error –  Feb 15 '18 at 16:50
  • java.lang.UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:148) at android.widget.ArrayAdapter.insert(ArrayAdapter.java:255) at .onDataChange(HomeActivity.java:121) –  Feb 15 '18 at 16:52
  • I gave you a solution but I don't understand why are still 2 lists in your code. This error is not related to Firebase is related the to list you are using. Try to implement only what I have suggested you. – Alex Mamo Feb 15 '18 at 16:57
  • There are 2 lists because i have an inbuilt array and I need to import an array from firebase(if it exists) and put them together into a spinner.this is because not every user will have an array on firebase and might use inbuilt ones –  Feb 15 '18 at 17:00