Java 通过引用将字符串变量传递给多个微调器的setOnItemSelectedListener

Java 通过引用将字符串变量传递给多个微调器的setOnItemSelectedListener,java,android,pass-by-reference,android-spinner,Java,Android,Pass By Reference,Android Spinner,好的,我已经看到Java只通过值传递,而不是通过引用,所以我不知道如何实现这一点 我在Android活动中有6个微调器,它们填充了不同的SQLite查询 填充每个微调器并设置OnItemSelectedListener的代码非常相似,因此我希望重构为一个方法,并使用每个微调器ID和Sqlite查询调用它6次 如何让微调器onItemSelectedListener更改每个不同微调器上的正确实例成员 public void fillSpinner(String spinner_name, fin

好的,我已经看到Java只通过值传递,而不是通过引用,所以我不知道如何实现这一点

  • 我在Android活动中有6个微调器,它们填充了不同的SQLite查询
  • 填充每个微调器并设置OnItemSelectedListener的代码非常相似,因此我希望重构为一个方法,并使用每个微调器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");
        }
    });
    
    public void fillSpinner(字符串微调器\u名称,最终字符串字段\u名称){
    //这将查找传递到具有微调器\u名称的方法中的微调器ID
    //来自资源文件。例如,spinner1
    int resID=getResources().getIdentifier(微调器名称,“id”,
    getPackageName());
    微调器s=(微调器)findViewById(剩余);
    最后一个月;
    //这将获取填充微调器的数据,例如,如果字段名称为
    //强度=选择_id,按强度从雪茄组中选择强度
    cMonth=dbHelper.fetchSpinnerFilters(字段名称);
    开始管理光标(厘米月);
    String[]from=新字符串[]{field_name};
    int[]to=newint[]{android.R.id.text1};
    SimpleCrsorAdapter月数=新SimpleCrsorAdapter月数(此,
    android.R.layout.simple\u微调器\u项目,每月,从,到);
    months.setDropDownViewResource(android.R.layout.simple\u微调器\u下拉菜单\u项);
    s、 设置适配器(个月);
    //这是设置微调器项Selected Listener回调,其中
    //所有的问题都会发生
    s、 setOnItemSelectedListener(新的OnItemSelectedListener(){
    已选择公共视图(AdapterView父视图、视图、,
    内部位置,长id){
    Cursor theCursor=(Cursor)parent.getSelectedItem();
    //这就是问题所在。
    对象\u引用\u到\u类\u成员\u字段\u名称=构造函数
    .getString(cersor.getColumnIndex(字段名称));
    }
    未选择公共无效(AdapterView父级){
    //showToast(“喷丝头1:未选择”);
    }
    });
    
    }

您可以这样调用此方法
fillSpinner(“spinner1”、“strength”)


它查找id为
spinner1
的微调器,并查询数据库中的
强度
字段。field_name(在本例中为strength)必须声明为要在onItemSelectedListener中使用的最终变量,否则会出现错误
无法引用在不同方法中定义的内部类中的非最终变量field_name

但是,当使用每个不同的微调器时,如何让onItemSelectedListener更改不同实例成员的值?这是最重要的一行代码:
object\u reference\u to\u clas\u member\u of_field\u name=theCursor.getString(theCursor.getColumnIndex(field\u name))


我不能使用最后一个字符串,因为当用户选择不同的值时,变量将明显改变。我读了很多书,很难找到一个解决办法。我可以复制粘贴这段代码6次,然后忘记重构,但我真的很想知道优雅的解决方案。如果您不理解我的问题,请发表评论。我不确定我是否解释得很好。

将您的侦听器重构为一个新的“类”。根据需要使用正确的参数/实例进行初始化,以使重复的“代码”可重用。

对,我就是这样管理它的,但我仍然愿意接受新的建议以获得可接受的答案,并且我还创建了一个赏金

我没有像建议的那样创建一个新类,所以我将此作为我自己问题的新答案发布。有点麻烦,但我只是在侦听器中创建了一个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");
        }
    });

有点小技巧,但如果Java不允许通过引用真正传递对象,我只能这样做。

您可以通过将附加类作为
fillSpinner
方法的参数传递来实现:

A.创建
接口

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) {

        }
    });
}

事实上,不清楚你想要什么,你在选举中面临什么问题。请详细说明。
不能在用其他方法定义的内部类中引用非最终变量字段名。
,为什么不在主类中全局声明
字段名
。是的,听起来不错。我会试着这样做,然后向你汇报,谢谢。我必须说,用“如果”来陈述不是一个好的做法。尽可能避免硬编码值,这是维护的噩梦!如果你是这个意思,我不能在字符串上使用switch语句。我知道,我也不想使用硬编码的值,但还有什么选择呢。我很想知道这个问题的优雅解决方案。我试着像你建议的那样作为一个监听器创建一个新类,但问题是我如何通过引用而不是通过值将实例成员传递给这个新监听器类的构造函数。很好,这很有效,而且似乎比在重构函数本身中使用硬编码的变量名要好。因此,在Java中,不能通过引用传递String对象,但可以传递具有设置String对象值的方法的最终对象。
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) {

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