微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Firebase setValue调用上java.util.HashMap $ HashIterator上的StackOverflowError

如何解决Firebase setValue调用上java.util.HashMap $ HashIterator上的StackOverflowError

我在ValueEventListener中收到StackOverflowError,但我不确定原因,因为我删除了侦听器。似乎与对setValue()的调用有关。这是代码

    public void joinGame(final String gameId)
    {
        System.out.println("join");
        mtGames.child(gameId).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                Game game = snapshot.getValue(Game.class);
                game.addplayer(mProfile);
                mProfile.setGame(game);
                mtGames.child(gameId).setValue(mProfile.getGame()); // The error occurs on this line
                mtGames.removeEventListener(this);
            }

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

            }
        });
    }

这可能是我正在使用的监听器吗?我曾经有一个想法是,由于它是一个addValueEventListener,自从我在onDataChange()中向数据库添加元素以来,它一直被调用。但是,我在数据库中看不到此行为,代码块似乎没有被多次调用,因此我删除了侦听器。我不太确定为什么会这样。

这是控制台输出

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: skateboard.skate,PID: 10127
    java.lang.StackOverflowError: stack size 8192KB
        at java.util.HashMap$HashIterator.<init>(HashMap.java:1423)
        at java.util.HashMap$ValueIterator.<init>(HashMap.java:1468)
        at java.util.HashMap$Values.iterator(HashMap.java:968)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:652)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:167)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.access$200(CustomClassMapper.java:47)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:675)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:167)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.access$200(CustomClassMapper.java:47)
...
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:675)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:167)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.access$200(CustomClassMapper.java:47)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.serialize(CustomClassMapper.java:675)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.serialize(CustomClassMapper.java:167)
        at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToPlainJavaTypes(CustomClassMapper.java:60)
        at com.google.firebase.database.DatabaseReference.setValueInternal(DatabaseReference.java:282)
        at com.google.firebase.database.DatabaseReference.setValue(DatabaseReference.java:159)
        at skateboard.skate.MainActivity$2.onDataChange(MainActivity.java:155)
        at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
        at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
        at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8125)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

解决方法

您将获得无限递归,这将侵蚀您的堆栈空间。

@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
    Game game = snapshot.getValue(Game.class);
    game.addPlayer(mProfile);
    mProfile.setGame(game);
    mtGames.child(gameId).setValue(mProfile.getGame()); // <-- changes data,triggering onDataChange to be invoked.
    mtGames.removeEventListener(this); // <-- happens too late.
}

修复可能类似于:

@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
    Game game = snapshot.getValue(Game.class);
    if (mProfile.getGame() != game)
    {
        game.addPlayer(mProfile);
        mProfile.setGame(game);
        mtGames.child(gameId).setValue(mProfile.getGame());
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。