如何在RxJava2中使用重试运算符记住状态

时间:2017-10-30 15:55:13

标签: android kotlin rx-java rx-java2

我有一个能够从中断中恢复的网络客户端,但在重试时需要最后一条消息。

Kotlin的例子:

fun requestOrResume(last: Message? = null): Flowable<Message> =
    Flowable.create({ emitter ->
        val connection = if (last != null)
                             client.start()
                         else
                             client.resumeFrom(last.id)

        while (!emitter.isDisposed) {
            val msg = connection.nextMessage()
            emitter.onNext(msg)
        }
    }, BackpressureStrategy.MISSING)

requestOrResume()
    .retryWhen { it.flatMap { Flowable.timer(5, SECONDS) } }
    // how to pass the resume data when there is a retry?

问题:正如您所看到的,我需要最后收到的消息才能准备简历呼叫。如何跟踪它,以便在重试时可以进行恢复请求?

一种可能的解决方案可能是创建一个持有者类,它只保存对最后一条消息的引用,并在收到新消息时更新。这样,当重试时,可以从持有者获得最后的消息。例如:

class MsgHolder(var last: Message? = null)

fun request(): Flowable<Message> {
    val holder = MsgHolder()
    return Flowable.create({ emitter ->
        val connection = if (holder.last != null)
                             client.start()
                         else
                             client.resumeFrom(holder.last.id)

        while (!emitter.isDisposed) {
            val msg = connection.nextMessage()
            holder.last = msg // <-- update holder reference
            emitter.onNext(msg)
        }
    }, BackpressureStrategy.MISSING)
}

我认为这可能会有效,但感觉就像是黑客攻击(线程同步问题?)。

是否有更好的方法来跟踪状态,以便可以重试?

2 个答案:

答案 0 :(得分:1)

请注意,除非你在最后一个元素周围重新抛出一个包装器(在功能上与你现有的&#34; hack&#34; -ish解决方案没有太大的区别,但uglier imo),没有错误处理操作符可以恢复最后一个元素一些外部帮助,因为他们只能访问private final ArrayList<RadioStation> namesOfStationsOfTopHitsStations = new ArrayList<>(); private final ArrayList<RadioStation> namesOfStationsOfHipHopStations = new ArrayList<>(); private final ArrayList<RadioStation> namesOfStationsOfRockStations = new ArrayList<>(); private final ArrayList<RadioStation> namesOfStationsOfElectronicStations = new ArrayList<>(); private final ArrayList<RadioStation> namesOfStationsOf80sStations = new ArrayList<>(); private final ArrayList<RadioStation> namesOfStationsOf90sStations = new ArrayList<>(); private final ArrayList<RadioStation> collegeRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> rockRadioStations = new ArrayList<>(); //radiostations by countries private final ArrayList<RadioStation> namesOfStationsOfAustrianStations = new ArrayList<>(); private final ArrayList<RadioStation> namesOfStationsOfBelarusianStations = new ArrayList<>(); private final ArrayList<RadioStation> namesOfStationsOfAlbanianStations = new ArrayList<>(); private final ArrayList<RadioStation> belgiumRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> bulgarianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> croatianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> cyprusRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> czechRepublicRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> denmarkRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> estonianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> finlandRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> franceRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> germanianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> greeceRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> hungarianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> irishRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> italianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> latvianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> lithuanianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> netherlandsRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> norwayRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> polishRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> portugalRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> romanianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> russianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> serbianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> slovakianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> slovenianRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> spanishRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> swedishRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> switzerlandRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> unitedKingdomRadioStations = new ArrayList<>(); private final ArrayList<RadioStation> ukrainianRadioStations = new ArrayList<>(); private final ArrayList<ArrayList<RadioStation>> totalStations = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Handler handler = new Handler(); new Thread(new Runnable() { @Override public void run() { totalStations.add(namesOfStationsOfTopHitsStations); totalStations.add(namesOfStationsOfHipHopStations); totalStations.add(namesOfStationsOfRockStations); totalStations.add(namesOfStationsOfElectronicStations ); totalStations.add(namesOfStationsOf80sStations ); totalStations.add(namesOfStationsOf90sStations ); totalStations.add(collegeRadioStations ); totalStations.add(rockRadioStations ); totalStations.add(namesOfStationsOfAlbanianStations ); totalStations.add(namesOfStationsOfAustrianStations ); totalStations.add(namesOfStationsOfBelarusianStations ); totalStations.add(belgiumRadioStations ); totalStations.add(bulgarianRadioStations ); totalStations.add(croatianRadioStations ); totalStations.add(cyprusRadioStations ); totalStations.add(czechRepublicRadioStations ); totalStations.add(denmarkRadioStations ); totalStations.add(estonianRadioStations ); totalStations.add(finlandRadioStations ); totalStations.add(franceRadioStations ); totalStations.add(germanianRadioStations ); totalStations.add(greeceRadioStations ); totalStations.add(hungarianRadioStations ); totalStations.add(irishRadioStations ); totalStations.add(italianRadioStations ); totalStations.add(latvianRadioStations ); totalStations.add(lithuanianRadioStations ); totalStations.add(netherlandsRadioStations ); totalStations.add(norwayRadioStations ); totalStations.add(polishRadioStations ); totalStations.add(portugalRadioStations ); totalStations.add(romanianRadioStations ); totalStations.add(russianRadioStations ); totalStations.add(serbianRadioStations ); totalStations.add(slovakianRadioStations ); totalStations.add(slovenianRadioStations ); totalStations.add(spanishRadioStations ); totalStations.add(swedishRadioStations ); totalStations.add(switzerlandRadioStations ); totalStations.add(unitedKingdomRadioStations ); totalStations.add(ukrainianRadioStations ); final ArrayList<String> genresList = new ArrayList<>(); genresList.add("Top Hits"); genresList.add("Hip hop"); genresList.add("Rock"); genresList.add("Electronic"); genresList.add("80s"); genresList.add("90s"); genresList.add("College radio"); genresList.add("Classic Rock radio"); genresList.add("Albanian radio"); genresList.add("Austrian radio"); genresList.add("Belarusian radio"); genresList.add("Belgium radio"); genresList.add("Bulgarian radio"); genresList.add("Croatian radio"); genresList.add("Cyprus radio"); genresList.add("Czech radio"); genresList.add("Denmark radio"); genresList.add("Estonian radio"); genresList.add("Finland radio"); genresList.add("France radio"); genresList.add("Germany radio"); genresList.add("Greece radio"); genresList.add("Hungarian radio"); genresList.add("Irish radio"); genresList.add("Italian radio"); genresList.add("Latvian radio"); genresList.add("Lithuanian radio"); genresList.add("Netherlands radio"); genresList.add("Norway radio"); genresList.add("Polish radio"); genresList.add("Portugal radio"); genresList.add("Romanian radio"); genresList.add("Russian radio"); genresList.add("Serbian radio"); genresList.add("Slovakian radio"); genresList.add("Slovenian radio"); genresList.add("Spanish radio"); genresList.add("Swedish radio"); genresList.add("Switzerland radio"); genresList.add("United Kingdom radio"); genresList.add("Ukrainian radio"); createRadioStations1(); createRadioStations2(); createRadioStations3(); createRadioStations4(); createRadioStations5(); createRadioStations7(); handler.post(new Runnable() { @Override public void run() { for(int i = 0; i<totalStations.size(); i++){ System.out.println(genresList.get(i) + " is curently iterated"); for(int j = 0; j<totalStations.get(i).size(); j++){ int index = genresList.get(i).indexOf(" "); if(index != -1){ System.out.println("RadioStation " + "radio" + (genresList.get(i).substring(0, index) + j + " = new RadioStation();")); } else { System.out.println("RadioStation " + "radio" + (genresList.get(i) + j + " = new RadioStation();")); } System.out.println("radio" + genresList.get(i) + j + ".mCustom = false;"); System.out.println("radio" + genresList.get(i) + j + ".mName = \"" + totalStations.get(i).get(j).mName + "\";"); System.out.println("radio" + genresList.get(i) + j + ".mUrl = \"" + totalStations.get(i).get(j).mUrl + "\";"); } } } }); } }).start(); } 的流。相反,看看以下递归方法是否适合您的需求:

Throwable

最大的区别是使用fun retryWithLast(seed: Flowable<Message>): Flowable<Message> { val last$ = seed.last().cache(); return seed.onErrorResumeNext { it.flatMap { retryWithLast(last$.flatMap { requestOrResume(it) }) } }; } retryWithLast(requestOrResume()); 缓存Observable中最后一次尝试的尾随值,而不是在值中手动执行此操作。另请注意,如果后续尝试继续失败,错误处理程序中的递归意味着cache将继续扩展流。

答案 1 :(得分:0)

Take a close look to buffer() operator: link中 您可以像这样使用它:

requestOrResume()
    .buffer(2)

从现在起,您的Flowable将返回List<Message>两个最新对象