我正在开发比赛应用程序。该应用程序已连接到Firebase实时数据库,该数据库被组织成一些子级列表,每个子级都有自己的字符串值,如下所示:

category1:
    child1: "string"
    child2: "string"
category2:
    child3: "string"
    child4: "string"
(etc.)


我正在尝试获取这些类别的名称,并将它们添加到我的布局之一的Spinner下拉菜单中。但是,当我测试此布局时,会发生一些奇怪的事情。如果点击微调按钮以打开下拉菜单,它将不断刷新自身(我可以看到它不断关闭并重新打开)。甚至更奇怪的是,有时,它只会显示两个字符串的列表(默认情况下我会添加),而上面的类别名称都不显示,而其他时候它将在列表中同时显示两个字符串。

无论我是否尝试从Firebase添加子名称字符串,刷新问题似乎都会发生。我知道发生这种情况的原因是Android Studio中的调试器窗口经常被垃圾邮件

D/ViewRootImpl@a8fa8f6[PopupWindow:d00794f]: Relayout returned: old=[286,729][962,1113] new=[286,729][962,1113] result=0x1 surface={valid=true 531823960064} changed=false

只要打开“微调器”下拉菜单(在两种情况下)。我尝试搜索该错误(全部或部分),但找不到与我要完成的任务完全相关的东西。

这是将列表添加到微调框的代码(打开“活动”时将调用此方法):

    public void onOpen() {
        // This is not the complete method, but the relevant portion of it

        final List<String> categories = new ArrayList<>();
        categories.add(selectionEmpty);
        categories.add(selectionCreateNew);
        dbh.dbref.child("users").child("a_users_uid_goes_here").child("flashcards").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot child : dataSnapshot.getChildren()) {
                    categories.add(child.getKey());
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, categories);
        setSelector.setAdapter(dataAdapter);
    }


这是我分配给微调器的OnItemSelectedListener:

    AdapterView.OnItemSelectedListener selectSet = new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long id) {
            String selection = adapterView.getItemAtPosition(pos).toString();
            if (selection.equals(selectionEmpty)) onOpen();
            if (selection.equals(selectionCreateNew)) onCreateNewSet();
            else onSelectSet(selection);
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView) {

        }
    };


onCreateNewSet()onSelectSet(String set)当前是两个空方法。我认为这不会产生任何影响,但是以防万一,他们目前不会采取任何措施。 onOpen()是上面的代码段。

这是我第一次使用Spinner对象,而且一般来说我也是Android Studio的新手(使用了6个月),因此如果我只是缺少明显的代码行,我深表歉意。总结一下:最佳情况下,Spinner下拉列表应该显示两个预设字符串和数据库中的所有类别名称,并且只能打开一次。实际发生的情况是它不断重复关闭/打开,并且每隔打开一次仅显示数据库中的类别名称(但是预设字符串始终存在)。我非常感谢您的帮助!

如果有人需要,我可能会很快将遇到的问题链接到GIF。

更新:似乎只有在下拉菜单中选择了默认值(这是两个预设字符串之一)时,才会发生此刷新故障。如果我选择另一个,则不会发生此故障。仍然不确定为什么会这样。

第二次更新:我自己解决了这个问题,这是我很尴尬地犯的一个菜鸟错误。问题在于,在方法onOpen()中,我为Spinner设置了适配器,但是在Spinner的AdapterView.onItemSelectedListener中,我再次调用了onOpen(),这导致递归循环破坏了一切。解决方法是创建一个名为onOpen()onSelectNoSet()复制方法,该方法除了未设置微调器的适配器之外,还执行了相同的操作,并让侦听器调用该方法而不是onOpen()

TL; DR递归不好

最佳答案

第二次更新:我自己解决了这个问题,这是我很尴尬地犯的一个菜鸟错误。问题在于,在方法onOpen()中,我为Spinner设置了适配器,但是在Spinner的AdapterView.onItemSelectedListener中,我再次调用了onOpen(),从而导致递归循环中断了所有工作。解决方法是创建一个称为onOpen()onSelectNoSet()重复方法,该方法除了未设置微调器的适配器之外,还执行了相同的操作,并让侦听器调用该方法而不是onOpen()

TL; DR递归不好

07-28 04:17