Android: Polling a server with Retrofit

后端 未结 2 1999
萌比男神i
萌比男神i 2021-02-04 17:09

I\'m building a 2 Player game on Android. The game works turnwise, so player 1 waits until player 2 made his input and vice versa. I have a webserver where I run an API with the

2条回答
  •  感动是毒
    2021-02-04 17:46

    Thank you, I finally made it in a similar way based the post I referred to in my question. Here's my code for now:

    Subscriber sub =  new Subscriber() {
            @Override
            public void onNext(Long _EmittedNumber)
            {
                GameTurn Turn =  Api.ReceiveGameTurn(mGameInfo.GetGameID(), mGameInfo.GetPlayerOneID());
                Log.d("Polling", "onNext: GameID - " + Turn.GetGameID());
            }
    
            @Override
            public void onCompleted() {
                Log.d("Polling", "Completed!");
            }
    
            @Override
            public void onError(Throwable e) {
                Log.d("Polling", "Error: " + e);
            }
        };
    
        Observable.interval(3, TimeUnit.SECONDS, Schedulers.io())
                // .map(tick -> Api.ReceiveGameTurn())
                // .doOnError(err -> Log.e("Polling", "Error retrieving messages" + err))
                .retry()
                .subscribe(sub);
    

    The problem now is that I need to terminate emitting when I get a positive answer (a GameTurn). I read about the takeUntil method where I would need to pass another Observable which would emit something once which would trigger the termination of my polling. But I'm not sure how to implement this. According to your solution, your API method returns an Observable like it is shown on the Retrofit website. Maybe this is the solution? So how would it work?

    UPDATE: I considered @david.miholas advices and tried his suggestion with retry and filter. Below you can find the code for the game initialization. The polling should work identically: Player1 starts a new game -> polls for opponent, Player2 joins the game -> server sends to Player1 opponent's ID -> polling terminated.

        Subscriber sub =  new Subscriber() {
            @Override
            public void onNext(String _SearchOpponentResult) {}
    
            @Override
            public void onCompleted() {
                Log.d("Polling", "Completed!");
            }
    
            @Override
            public void onError(Throwable e) {
                Log.d("Polling", "Error: " + e);
            }
        };
    
        Observable.interval(3, TimeUnit.SECONDS, Schedulers.io())
                .map(tick -> mApiService.SearchForOpponent(mGameInfo.GetGameID()))
                .doOnError(err -> Log.e("Polling", "Error retrieving messages: " + err))
                .retry()
                .filter(new Func1()
                {
                    @Override
                    public Boolean call(String _SearchOpponentResult)
                    {
                        Boolean OpponentExists;
                        if (_SearchOpponentResult != "0")
                        {
                            Log.e("Polling", "Filter " + _SearchOpponentResult);
                            OpponentExists = true;
                        }
                        else
                        {
                            OpponentExists = false;
                        }
                        return OpponentExists;
    
                    }
                })
                .take(1)
                .subscribe(sub);
    

    The emission is correct, however I get this log message on every emit:

    E/Polling﹕ Error retrieving messages: java.lang.NullPointerException
    

    Apperently doOnError is triggered on every emit. Normally I would get some Retrofit debug logs on every emit which means that mApiService.SearchForOpponent won't get called. What do I do wrong?

提交回复
热议问题