RIBs is the cross-platform architecture framework behind many mobile apps at Uber. The name RIBs is short of Router, Interactor and Builder. This framework is designed for mobile apps with a large number of engineers and nested states.
Home Controller Confirmation Controller Location Controller Home Controller Home Controller Home Controller … … New Controller Simplified Version of Old Rider App
Home Controller Confirmation Controller Location Controller Home Controller Home Controller Home Controller … … New Controller Simplified Version of Old Rider App
Home Controller Confirmation Controller Location Controller Home Controller Home Controller Home Controller … … New Controller Simplified Version of Old Rider App
attach child router. loggedInRouter = loggedInBuilder.build(authToken) attachChild(loggedInRouter); // Extra step! Need to specify view attachment point getView().attachChild(loggedInRouter.getView()); } // … } // Extra step! Need to specify view attachment point getView().attachChild(loggedInRouter.getView()); Attaching child routers
fun detachLoggedOut() } Root router interface Routers sit between each Interactor and its children. They are only used for attaching/detaching children RIBs.
emissions. LoggedOut RIB Receives LocationStream from DI graph. Subscribes to LocationStream. LoggedIn RIB Receives LocationStream from DI graph. Subscribes to LocationStream. Communicate data downwards Using Rx
dependencies here, // or just list `Subcomponent.Builder` to get // everything you need. LoggedOutListener loggedOutListener(); } @LoggedInScope @Component(dependencies = ParentComponent.class, …) interface LoggedInComponent { … } }
dependencies here, // or just list `Subcomponent.Builder` to get // everything you need. LoggedOutListener loggedOutListener(); } @LoggedInScope @Component(dependencies = ParentComponent.class, …) interface LoggedInComponent { … } }
dependencies here, // or just list `Subcomponent.Builder` to get // everything you need. LoggedOutListener loggedOutListener(); } @LoggedInScope @Component(dependencies = ParentComponent.class, …) interface LoggedInComponent { … } }
redeemBuilder.build(parentView, pointsToRedeem) ); } // … } Backstack Handling Each RIB chooses how to handle backstack for its children. Lots choose the same way. So we’ve build utilities.
an observable. Our tooling won’t let you forget to bind your subscriptions to this lifecycle or cleanup routers after you’re done with them. class SomeInteractor { fun attachChild(pointsToRedeem:Int) { myObservable .doStuff() // don’t leak memory! .to(new Autodispose.with(this)) .subscribe(s -> …); } }
an observable. Our tooling won’t let you forget to bind your subscriptions to this lifecycle or cleanup routers after you’re done with them. class SomeInteractor { fun attachChild(pointsToRedeem:Int) { myObservable .doStuff() // don’t leak memory! .to(new Autodispose.with(this)) .subscribe(s -> …); } }
reserved. No part of this document may be reproduced or utilized in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval systems, without permission in writing from Uber. This document is intended only for the use of the individual or entity to whom it is addressed and contains information that is privileged, confidential or otherwise exempt from disclosure under applicable law. All recipients of this document are notified that the information contained herein includes proprietary and confidential information of Uber, and recipient may not make use of, disseminate, or in any way disclose this document or any of the enclosed information to any person other than employees of addressee to the extent necessary for consultations with authorized personnel of Uber.