通过引用多个 Spinner 的 setOnItemSelectedListener 传递 String 变量

发布于 2024-12-27 08:46:35 字数 2335 浏览 2 评论 0原文

好的,我已经阅读了,发现 Java 只按值传递,而不是按值传递参考,所以我不知道如何实现这一点。

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

    public void fillSpinner(String spinner_name, Final String field_name) {
    // 这会找到通过 spinner_name 传递到方法中的 Spinner ID
    // 来自资源文件。例如旋转器1
    int resID = getResources().getIdentifier(spinner_name, "id",
            获取包名());
    Spinner s = (Spinner) findViewById(resID);
    最终光标 cMonth;
    // 这获取数据来填充微调器,例如,如果 field_name 是
    // 强度 = SELECT _id, 雪茄强度 GROUP BY 强度
    cMonth = dbHelper.fetchSpinnerFilters(field_name);
    开始管理光标(cMonth);
    String[] from = new String[] { 字段名称 };
    int[] to = new int[] { android.R.id.text1 };
    SimpleCursorAdapter 月 = new SimpleCursorAdapter(this,
            android.R.layout.simple_spinner_item,cMonth,从,到);
    Months.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    s.setAdapter(月);
    // 这是设置 Spinner Item Selected Listener 回调,其中
    // 所有问题都会发生
    s.setOnItemSelectedListener(new OnItemSelectedListener() {
        public void onItemSelected(AdapterViewparent, View view,
                int 位置,长 id) {
            Cursor theCursor = (Cursor)parent.getSelectedItem();
            // 这是问题区域。
            object_reference_to_clas_member_of_field_name = theCursor
                    .getString(theCursor.getColumnIndex(field_name));
        }
    
        公共无效onNothingSelected(AdapterView <?>父){
            // showToast("Spinner1: 未选择");
        }
    });
    

    }

fillSpinner("spinner1","strength"); 那样调用此方法。

它找到 ID 为 spinner1 的微调器,并在数据库中查询 strength 字段。 field_name,在本例中是一个强项,必须声明为在 onItemSelectedListener 中使用的最终变量,否则我会收到错误Cannot reference a non-final variable field_name inside an inside class Defined in a different method< /代码>。

但是,当使用每个不同的 Spinner 时,如何让 onItemSelectedListener 更改不同实例成员的值?这是最重要的代码行: object_reference_to_clas_member_of_field_name = theCursor .getString(theCursor.getColumnIndex(field_name));

我无法使用最终字符串,因为当用户选择不同的值时,变量显然会发生变化。我已经阅读了很多内容并且很难找到解决方案。我可以复制并粘贴此代码 6 次,然后忘记重构,但我真的很想知道优雅的解决方案。如果您不明白我的问题,请发表评论,我不确定我是否解释得很好。

OK, I've read around and see that Java only passes by value, not by reference so I don't know how to accomplish this.

  • I've 6 Spinners in an Android Activity that are populated with different SQLite queries.
  • The code to populate each Spinner and set the OnItemSelectedListener is very similiar so I was hoping to refactor to one method and call it 6 times with each Spinner ID and Sqlite query.
  • How do I get the Spinner onItemSelectedListener to change the right instance member on each different Spinner?

    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");
        }
    });
    

    }

You call this method like this fillSpinner("spinner1","strength");.

It finds the spinner with id spinner1 and queries the database for the strength field. field_name, which is strength in this example had to be declared a final variable to be used in the onItemSelectedListener or I'd get the error Cannot refer to a non-final variable field_name inside an inner class defined in a different method.

But how do I get the onItemSelectedListener to change the value of a different instance member when each different Spinner is used? This is the all important line of code:
object_reference_to_clas_member_of_field_name = theCursor .getString(theCursor.getColumnIndex(field_name));

I can't use a final String as the variable will obviously change when the user selects a different value. I've read around a good bit and am stumped to a solution. I can just copy and paste this code 6 times and forget about refactoring but I'd really like to know the elegant solution. Post a comment if you don't understand my question, I'm not sure if I explaned myself well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

围归者 2025-01-03 08:46:35

您可以通过传递附加类作为 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);
    }
});

You can do it, by passing additional class as parameter of fillSpinner method:

A. Create interface

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

B. Change your method a bit:

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. provide listener:

fillSpinner("spinner1","strength", new OnSpinnerValueSelected() {
    public void onValueSelected(String selectedValue) {
        yourObject.setField(selectedValue);
    }
});
对你再特殊 2025-01-03 08:46:35

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

Refactor your listener to a new "class". Initialize with the right arguments/instances as required so that the repeated "code" is reusuable.

时光瘦了 2025-01-03 08:46:35

是的,这就是我的管理方式,但我仍然愿意接受新的建议以接受答案,并且我还创建了赏金。

我没有创建像 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;

一些 hack,但是如果 Java 不允许对象真正通过引用传递,这就是我所能做的。

Right, this is how I managed it but I'm still open to new suggestions for an accepted answer and I also created a bounty.

I didn't create a new class like panzerschreck suggested so I'm posting this as a new answer to my own question. Bit of a hack but I just created an if..then..else statement in the listener to check what spinner was selected and then set a different instance member.

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");
        }
    });

Here are the class members

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

Bit of hack but without Java allowing objects to be really passed by reference, it's all I could do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文