2

I can't solve the problem with my spinner setSelection() method. I'm writing a program to save data, which I have from some kind of a table, in the DB. When the user opens a program it loads data from the DB and adds 3 empty "table" rows so the user can fill them and save them. When data from the DB is loaded, I need to set the selections of spinners correctly, but when I'm trying my code it just doesn't work and all the spinners on the screen appear with the 0 items selected. Here is my code.
OnCreate() method:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.data);
    
    dbHelper = new DBHelper(this);
    content = (LinearLayout) findViewById(R.id.content);
    inflater = getLayoutInflater();
    
    Calendar c = Calendar.getInstance(); 
    cur_year = c.get(Calendar.YEAR);
    cur_month = c.get(Calendar.MONTH);
    cur_day = c.get(Calendar.DAY_OF_MONTH);
    
    load_array();
    load_database();

    for (int i = 0; i < EMPTY_LINES_TO_DRAW; i++) {
        draw();
    }
}

load_array() is a function that load array "suppliers" (from file) which i then put in my spinner adapter.
load_database() function:

private void load_database() {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    Cursor c = db.query("mytable", null, null, null, null, null, null);
    
    if (c.moveToFirst()) {

        int date_1_Index = c.getColumnIndex("date_1");
        int key_Index = c.getColumnIndex("key_field");
        int supp_Index = c.getColumnIndex("supplier");
        int sum_Index = c.getColumnIndex("summ_field");
        int check_Index = c.getColumnIndex("check_field");
        int date_2_Index = c.getColumnIndex("date_2");

        do {
          draw(c.getString(date_1_Index), c.getString(key_Index), c.getString(supp_Index), c.getInt(sum_Index), c.getInt(check_Index), c.getString(date_2_Index));
        } while (c.moveToNext());
      }
      c.close();
}

draw() function:

public void draw(String date_1_string, String key_string, String supp_string, Integer sum_int, Integer check_int, String date_2_string) {
    View item = inflater.inflate(R.layout.ll_item, content, false);
    
    for (int i = 0; i < 6; i++) {
        delta_id[i] = generateViewId();
    }
    id.add(delta_id.clone());
    
    Button date_1 = (Button) item.findViewById(R.id.date_1);
    date_1.setText(date_1_string);
    date_1.setOnClickListener(this);
    date_1.setId(delta_id[0]);
    
    EditText key = (EditText) item.findViewById(R.id.key);
    key.setText(key_string);
    key.setId(delta_id[1]);
    
    Spinner spin = (Spinner) item.findViewById(R.id.spin);
    adapter_supp =  new ArrayAdapter<String>(this, R.layout.spinner, suppliers);
    spin.setAdapter(adapter_supp);
    spin.setPrompt("Поставщик:");
    Log.d("my_log", "supp_string = " + supp_string);
    spin.setSelection(Arrays.asList(suppliers).indexOf(supp_string));
    Log.d("my_log", "Index of the supp_string = " + Arrays.asList(suppliers).indexOf(supp_string));
    adapter_supp.notifyDataSetChanged();
    spin.setId(delta_id[2]);
    
    EditText sum = (EditText) item.findViewById(R.id.sum);
    sum.setText(sum_int.toString());
    sum.setId(delta_id[3]);
    
    CheckBox check = (CheckBox) item.findViewById(R.id.check);
    if (check_int == 1) {
        check.setChecked(true);
    } else if (check_int == 0){
        check.setChecked(false);
    }
    check.setId(delta_id[4]);
    
    Button date_2 = (Button) item.findViewById(R.id.date_2);
    date_2.setText(date_2_string);
    date_2.setOnClickListener(this);
    date_2.setId(delta_id[5]);
    
    content.addView(item);
}

The weird thing is that when I go to the second activity, then return to the first, I got my selections set correctly as it was. But when I close the program, then open it again, all the spinners are set to default item with index 0. Here is my onResume() code:

@Override
public void onResume() {
    super.onResume();
    
    load_array();
    
    // Верхний, главный, фильтр.
    
    adapter_supp = new ArrayAdapter<String>(this, R.layout.spinner, suppliers);
    adapter_supp.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    Spinner filter_supp = (Spinner) findViewById(R.id.filter_supp);
    filter_supp.setAdapter(adapter_supp);
    filter_supp.setPrompt("Фильтр по поставщику:");
    
    // Обновить спиннеры поставщиков. Update spinners.
    
    for (int i = 0; i < id.size(); i++) {
        Integer[] item = id.get(i);
        Spinner supp = (Spinner) findViewById(item[2]);
        supp.setAdapter(adapter_supp);
        if (pause_cash_string != null) {
        supp.setSelection(Arrays.asList(suppliers).indexOf(pause_cash_string[i]));
        adapter_supp.notifyDataSetChanged();
        }
    }
}

Yes, Arrays.asList(suppliers).indexOf() in both places (in onResume() and draw() functions) returns correct index, I have checked it few times.

Ramesh R
  • 7,009
  • 4
  • 25
  • 38
oleg.v
  • 1,065
  • 3
  • 11
  • 20

4 Answers4

8

I have same problem. the solution is posting setSelection() method:

mSpinner.post(new Runnable() {        
    public void run() {
      mSpinner.setSelection(1);
    }
  });

also in some cases calling setSelection(position, animation) instead of setSelection(position) solves the problem:

setSelection(1, false);

but I recommend the first code.

hope helpful.

Ramesh R
  • 7,009
  • 4
  • 25
  • 38
afruzan
  • 1,454
  • 19
  • 20
  • This worked for me (the post) when restoring the selected item in onRestoreInstanceState() – alzee Jan 18 '16 at 20:51
0

Call adapter_supp.notifyDataSetChanged(); before (not after) you try to set the selected item with supp.setSelection()

invertigo
  • 6,336
  • 5
  • 39
  • 64
  • didn't help. In the first case, when i go to the second activity, then back, it still works. But it did no effect on the closing and opening program. – oleg.v Jul 10 '13 at 16:02
  • i still think it's related to the fact that you are calling notifyDataSetChanged() in onResume() in a loop. you should only need to call notifyDataSetChanged() after the data (suppliers) changes. i dont see the data changing at all after you set up the adapter, so there is no need to call notifyDataSetChanged() in onResume(). – invertigo Jul 10 '13 at 16:09
  • also, adapter_supp does not need to be instatiated over and over again in draw(). create it once in onCreate() and just reuse that instance whenever you need to call setAdapter() for your spinners. – invertigo Jul 10 '13 at 16:12
  • in my second activity i can change my suppliers list, so i need to create adapter with changed array "suppliers". Forgot to write it in the question, sorry. Thank you for the advice about calling notifyDataSetChanged() in the loop, but it still dont solve my problem. – oleg.v Jul 10 '13 at 16:21
0

I've resorted to storing the value of the position in an int (spinnerSelection) and when it hits onItemSelected (which it will when you call .setSelection() ) I set it again. It's a hack but it works for me now.

public void onItemSelected(AdapterView<?> parent, View view,
                           int pos, long id) {
    if(spinnerFixer >=2){ //it hits this twice before any user input for some reason (init + setSelection both trigger).
      //stuff
    } else { spinnerFixer++;
        if(spinnerSelection != 0){
        spinner.setSelection(spinnerSelection,true); spinnerSelection=0; }
    }
Ramesh R
  • 7,009
  • 4
  • 25
  • 38
mevdev
  • 701
  • 8
  • 16
0

After setting values to adapter, call setSelection()

ArrayAdapter<String> adapter = new ArrayAdapter<String>
                (this, android.R.layout.simple_spinner_item,
                        spinnerArray);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
//setSelection
spinner.setSelection(1);
Ramesh R
  • 7,009
  • 4
  • 25
  • 38