2012-01-18 93 views
4

好吧,我read around并且看到Java只通过值传递,而不是通过引用,所以我不知道如何实现这一点。通过引用多个Spinner的setOnItemSelectedListener传递字符串变量

  • 我有6个Spinners在Android Activity中被填充了不同的SQLite查询。
  • 填充每个Spinner并设置OnItemSelectedListener的代码非常相似,所以我希望重构为一个方法,并使用每个Spinner ID和Sqlite查询调用它6次。
  • 如何获得微调onItemSelectedListener更改每个不同微调器上的正确实例成员?

    public void fillSpinner(String spinner_name, final String field_name) { 
    // This finds the Spinner ID passed into the method with spinner_name 
    // from the Resources file. e.g. spinner1 
    int resID = getResources().getIdentifier(spinner_name, "id", 
         getPackageName()); 
    Spinner s = (Spinner) findViewById(resID); 
    final Cursor cMonth; 
    // This gets the data to populate the spinner, e.g. if field_name was 
    // strength = SELECT _id, strength FROM cigars GROUP BY strength 
    cMonth = dbHelper.fetchSpinnerFilters(field_name); 
    startManagingCursor(cMonth); 
    String[] from = new String[] { field_name }; 
    int[] to = new int[] { android.R.id.text1 }; 
    SimpleCursorAdapter months = new SimpleCursorAdapter(this, 
         android.R.layout.simple_spinner_item, cMonth, from, to); 
    months.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    s.setAdapter(months); 
    // This is setting the Spinner Item Selected Listener Callback, where 
    // all the problems happen 
    s.setOnItemSelectedListener(new OnItemSelectedListener() { 
        public void onItemSelected(AdapterView<?> parent, View view, 
          int position, long id) { 
         Cursor theCursor = (Cursor) parent.getSelectedItem(); 
         // This is the problem area. 
         object_reference_to_clas_member_of_field_name = theCursor 
           .getString(theCursor.getColumnIndex(field_name)); 
        } 
    
        public void onNothingSelected(AdapterView<?> parent) { 
         // showToast("Spinner1: unselected"); 
        } 
    }); 
    

    }

调用此方法像这样fillSpinner("spinner1","strength");

它找到编号为spinner1的微调框并在数据库中查询strength字段。 field_name,这个例子中的强度必须被声明为在onItemSelectedListener中使用的最终变量,否则我会得到错误Cannot refer to a non-final variable field_name inside an inner class defined in a different method

但是,如何在使用每个不同的Spinner时,如何让onItemSelectedListener更改不同实例成员的值?这是所有重要的代码行:

我不能使用最终的字符串,因为当用户选择不同的值时,变量显然会改变。我已经读了很多,很难找到解决方案。我可以复制并粘贴这段代码6次,忘掉重构,但我真的很想知道这个优雅的解决方案。如果你不明白我的问题,请发表评论,我不确定我是否能够很好地解释自己。

+0

实际上,目前尚不清楚你想要什么,什么问题你都面临着onItemSelected。请详细说明。 – jeet 2012-01-18 04:59:30

+0

'不能在不同的方法中定义的内部类中引用非最终变量field_name',为什么不在主类中全局声明'field_name'。 – 2012-01-21 04:35:24

回答

1

你可以做到这一点,通过传递额外类为fillSpinner方法的参数:

A.创建interface

public interface OnSpinnerValueSelected { 
    void onValueSelected(String selectedValue); 
} 

B.更改方法的位:

public void fillSpinner(String spinner_name, final String field_name, 
        final OnSpinnerValueSelected valueChangeListener) { 

    // Prepare spinner 

    s.setOnItemSelectedListener(new OnItemSelectedListener() { 

     public void onItemSelected(AdapterView<?> parent, View view, 
        int position, long id) { 
      Cursor theCursor = (Cursor) parent.getSelectedItem(); 

      valueChangeListener.onValueSelected(theCursor 
          .getString(theCursor.getColumnIndex(field_name))); 
     } 

     public void onNothingSelected(AdapterView<?> parent) { 

     } 
    }); 
} 

C.提供监听器:

fillSpinner("spinner1","strength", new OnSpinnerValueSelected() { 
    public void onValueSelected(String selectedValue) { 
     yourObject.setField(selectedValue); 
    } 
}); 
+0

太棒了,这个工作,似乎比在重构函数本身有硬编码变量名称更好。所以在Java中你不能通过引用传递一个String对象,但是你可以传递一个最终对象,它有一个方法来设置String对象的值。 – georgiecasey 2012-01-21 14:38:25

1

将您的听众重构为新的“课程”。根据需要使用正确的参数/实例进行初始化,以便重复的“代码”可重复使用。

+0

是的,这听起来很正确。我会尝试并报告,欢呼 – georgiecasey 2012-01-18 14:27:37

0

对,这就是我如何管理它,但我仍然接受新的建议,以接受答案,我也创造了一个赏金。

我没有建立像panzerschreck这样的新课程,所以我将这个作为新答案发布给我自己的问题。一个黑客的位,但我只是在侦听器中创建了一个if..then..else语句,以检查选择哪个微调器,然后设置不同的实例成员。

s.setOnItemSelectedListener(new OnItemSelectedListener() { 
     public void onItemSelected(AdapterView<?> parent, View view, 
       int position, long id) { 
      Cursor theCursor = (Cursor) parent.getSelectedItem(); 
      if (field_name.equalsIgnoreCase("strength")) { 
       strength=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("ring")) { 
       ring_gauge=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("country")) { 
       country=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("wrapper")) { 
       wrapper=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("length")) { 
       length=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("price")) { 
       price=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } 
      // showToast(category); 
     } 

     public void onNothingSelected(AdapterView<?> parent) { 
      // showToast("Spinner2: unselected"); 
     } 
    }); 

下面是类成员

private String strength,ring_gauge,country,wrapper,length,price; 

黑客的Java位,但没有允许对象通过引用传递真的,这是我所能做的。

+1

我必须说它不是一个很好的做法,如果'陈述。尽可能避免硬编码值,这是一个维护噩梦! – panzerschreck 2012-01-19 03:30:46

+0

如果这就是你的意思,我无法在字符串上使用switch语句。我知道,我不想使用硬编码值,但还有其他选择。我很想知道这个优雅的解决方案。我尝试创建一个新的类作为你建议的监听器,但问题是我如何通过引用传递实例成员,而不是通过值来传递这个新监听器类的构造函数。 – georgiecasey 2012-01-19 03:50:37