จะทราบได้อย่างไรว่าการปล่อยที่สังเกตได้นั้นเป็นค่า BehaviourSubject ที่แคชไว้หรือไม่

ฉันใช้ BehaviourRelay เป็นแหล่งที่มาที่สังเกตได้ ฉันชอบที่มันจะปล่อยค่าแคชล่าสุดเมื่อสมัครสมาชิก ดังนั้นฉันจึงไม่จำเป็นต้องเรียก showPlayingState(mPlayStateManager.getCurrentState()) ด้วยตนเอง

อย่างไรก็ตาม สิ่งนี้ทำให้เกิดปัญหาเมื่อฉันต้องการตอบสนองต่อแอนิเมชันในการสมัครสมาชิก เนื่องจากฉันไม่ต้องการเรียกใช้แอนิเมชั่นตามการปล่อยแคชนี้ ซึ่งจะถูกปล่อยออกมาเมื่อฉันสมัครสมาชิกใน onCreate UI ควรข้ามไปที่สถานะ ไม่ใช่เคลื่อนไหว แอนิเมชันควรทำงานเฉพาะในกรณีที่มีการปล่อย "ใหม่" เท่านั้น

นี่เป็นกรณีการใช้งานที่ค่อนข้างธรรมดาสำหรับฉัน แต่ฉันมีปัญหาในการหามันในรูปแบบ rx

class Activity {

   PlayStateManager mPlayStateManager;
   Button mButton;

   void onCreate(SavedinstanceState state) {
      mPlayStateManager.playState()
        .subscribe(state -> {
           switch(state) {
            case PlayState.PLAYING:
                showPlayingState(true, ???);
                break;
            case PlayState.PAUSED:
                showPlayingState(false, ???);
                break;
           }
        }
   }

   void showPlayingState(boolean isPlay, boolean animate) {
     if(!animate) {
         mButton.setText(isPlay ? "Playing" : "Paused");
     } else {
         mButton.animate()
           .rotate(360)
           .onAnimationEnd(() -> {
              mButton.setText(isPlay ? "Playing" : "Paused");
           })
      }
   }
}


class PlayStateManager {

    BehaviourRelay<PlayState> mSubject = new BehaviourRelay();

    public void set(PlayState state) {
       mSubject.accept(state);
    }

    public Observable<PlayState> playState() {
        return mSubject.hide();
    }
}

person urSus    schedule 20.10.2017    source แหล่งที่มา


คำตอบ (1)


หากฉันเข้าใจคำถามของคุณถูกต้อง คุณคงไม่ต้องการที่จะแสดงแอนิเมชั่นหาก playState() เป็นข้อมูลที่เก่ากว่า แต่จะทำเฉพาะเมื่อเปลี่ยนสถานะเท่านั้น กล่าวอีกนัยหนึ่ง ในการเรียกครั้งแรกที่ onCreate() คุณไม่ต้องการทำแอนิเมชั่น แต่ต้องการทำแอนิเมชั่นหากค่าเปลี่ยนแปลง

enum PlayStateExpanded {
  UNKNOWN,
  PLAYING,
  PAUSED
}

class PlayStateManager {

    BehaviourRelay<PlayStateExpanded> mSubject = 
       new BehaviourRelay(PlayStateExpanded.UNKNOWN);

    public void set(PlayState state) {
       mSubject.accept(
           state == PlayState.PLAYING ? PlayStateExpanded.PLAYING
                                      : PlayStateExpanded.PAUSED);
    }

    public Observable<PlayStateExpanded> playState() {
        return mSubject.hide();
    }
}

void onCreate(SavedinstanceState state) {
  AtomicBoolean firstTime = new AtomicBoolean(true); // note first time
  mPlayStateManager.playState()
    .subscribe(state -> {
       switch(state) {
        case PlayStateExpanded.PLAYING:
            showPlayingState(true, firstTime.get());
            break;
        case PlayStateExpanded.PAUSED:
            showPlayingState(true, firstTime.get());
            break;
       }
       firstTime.set(false); // no longer first time
    }
}

ด้วยการกำหนดสถานะการเล่นใหม่ด้วยค่า UNKNOWN เงื่อนไขการเริ่มต้นจะง่ายขึ้น เพียงเพิ่มแฟล็กสำหรับการเปลี่ยนครั้งแรกที่จะรีเซ็ตหลังจากใช้งานครั้งแรกก็จะบรรลุเป้าหมายที่คุณระบุไว้

person Bob Dalgleish    schedule 20.10.2017
comment
ใช่ แต่หัวเรื่องสามารถเริ่มว่างเปล่าได้ โดยไม่มีค่าที่แคชไว้ - person urSus; 21.10.2017
comment
และ? คำถามของคุณไม่ได้อธิบายพฤติกรรมในกรณีเช่นนี้ รหัสแสดงว่าคุณรอการกำหนดค่าที่จะกำหนด - person Bob Dalgleish; 21.10.2017
comment
คุณหมายความว่าอย่างไร behaviorrelay ไม่มีค่าเริ่มต้น ค่าแรงนั้นสามารถเว้นว่างไว้ได้ ดังนั้นแรงจะไม่ถูกแคชไว้เมื่อสมัครสมาชิก และการปล่อยใหม่ครั้งแรกจะได้รับการปฏิบัติอย่างผิดๆ เช่นนี้ BTW นั้นขึ้นอยู่กับความจริงที่ว่ามันเป็นพฤติกรรมรีเลย์ซึ่งคุณไม่ควรรู้ดังนั้นการซ่อน () มีวิธีที่ฉันจะสามารถเข้ารหัสมันในข้อมูลที่ปล่อยออกมาได้หรือไม่? - person urSus; 21.10.2017
comment
ย้อนกลับไปในการออกแบบสักหน่อย เหตุใด playState() จึงไม่สามารถสังเกตได้จนกว่าจะมีการตั้งค่า ควรกำหนดไว้เสมอ โดยอาจมี UNKNOWN เป็นสถานะเริ่มต้น - person Bob Dalgleish; 22.10.2017
comment
โอเค นั่นคงจะได้ผล แต่ฉันก็ยังไม่ชอบความจริงที่ว่าคุณต้องรู้พฤติกรรมของมัน - person urSus; 22.10.2017
comment
คุณไม่จำเป็นต้องรู้พฤติกรรมของมัน คุณต้องจัดเตรียมสิ่งที่สังเกตได้ซึ่งมีการกำหนดสถานะไว้เสมอ มีความแตกต่าง - person Bob Dalgleish; 23.10.2017
comment
ใช่ ดีเลย ฉันหมายถึงว่าให้ปล่อยการจัดการพิเศษในสมาชิกก่อน และอาจจะมาจากสตรีมด้วย ซึ่งการปล่อยนี้ต้องการการจัดการแบบนั้น - person urSus; 23.10.2017
comment
ฉันเห็นด้วย. บางครั้งเราก็ไม่ได้ข้อมูลที่ดีเท่าที่ควรเสมอไปและต้องปรับเปลี่ยน :) - person Bob Dalgleish; 23.10.2017
comment
ฉันจะทำเช่นนั้นได้อย่างไร? การแบ่งคลาสย่อย BehaviorStream เพื่อปล่อย Pair‹Boolean, T› ? - person urSus; 23.10.2017
comment
ขอผมเขียนคำตอบใหม่นะ - person Bob Dalgleish; 23.10.2017