Convert Figma logo to code with AI

uber logoRIBs

Uber's cross-platform mobile architecture framework.

7,751
905
7,751
124

Top Related Projects

8,512

Epoxy is an Android library for building complex screens in a RecyclerView

A small, yet full-featured framework that allows building View-based Android applications

5,683

A sample Android app which showcases advanced usage of Dagger among other open source libraries.

5,490

A Model-View-Presenter / Model-View-Intent library for modern Android apps

2,786

Name UI states, navigate between them, remember where you've been.

Quick Overview

RIBs is Uber's cross-platform mobile architecture framework. It's designed to build large-scale, modular apps with a focus on scalability and developer productivity. RIBs stands for Router, Interactor, and Builder, which are the main components of the architecture.

Pros

  • Promotes scalability and modularity in large mobile applications
  • Supports cross-platform development (iOS and Android)
  • Encourages testability and separation of concerns
  • Provides a consistent architecture across teams and projects

Cons

  • Steep learning curve for developers new to the architecture
  • Can be overkill for smaller, simpler applications
  • Requires significant initial setup and boilerplate code
  • Limited adoption outside of Uber, potentially affecting community support

Code Examples

  1. Creating a RIB:
final class ExampleBuilder: Builder<ExampleDependency>, ExampleBuildable {
    func build(withListener listener: ExampleListener) -> ExampleRouting {
        let viewController = ExampleViewController()
        let interactor = ExampleInteractor(presenter: viewController)
        interactor.listener = listener
        return ExampleRouter(interactor: interactor, viewController: viewController)
    }
}
  1. Implementing an Interactor:
final class ExampleInteractor: PresentableInteractor<ExamplePresentable>, ExampleInteractable {
    weak var router: ExampleRouting?
    weak var listener: ExampleListener?

    override func didBecomeActive() {
        super.didBecomeActive()
        // Perform setup when the RIB becomes active
    }

    override func willResignActive() {
        super.willResignActive()
        // Perform cleanup when the RIB becomes inactive
    }
}
  1. Implementing a Router:
final class ExampleRouter: ViewableRouter<ExampleInteractable, ExampleViewControllable>, ExampleRouting {
    override init(interactor: ExampleInteractable, viewController: ExampleViewControllable) {
        super.init(interactor: interactor, viewController: viewController)
        interactor.router = self
    }

    func routeToChildRIB() {
        // Implement routing logic to attach child RIBs
    }
}

Getting Started

To get started with RIBs, follow these steps:

  1. Install the RIBs template generator:

    brew tap uber/formulae
    brew install ribs-generator
    
  2. Create a new RIB:

    ribs-generator new --name Example
    
  3. Implement the generated RIB components (Builder, Router, Interactor, and ViewController).

  4. Attach the RIB to your app's root RIB or another parent RIB:

    let example = ExampleBuilder(dependency: appComponent).build(withListener: self)
    attachChild(example)
    

For more detailed instructions and best practices, refer to the official RIBs documentation on GitHub.

Competitor Comparisons

8,512

Epoxy is an Android library for building complex screens in a RecyclerView

Pros of Epoxy

  • Simplifies complex RecyclerView layouts with a declarative API
  • Supports automatic diffing for efficient updates
  • Provides powerful data binding and view holder generation

Cons of Epoxy

  • Steeper learning curve for developers new to the library
  • May introduce additional complexity for simple list views
  • Requires more setup and configuration compared to standard RecyclerView adapters

Code Comparison

Epoxy:

class PhotoController : EpoxyController() {
    override fun buildModels() {
        header {
            id("header")
            title("Photo Gallery")
        }
        photoList.forEach { photo ->
            photoView {
                id(photo.id)
                url(photo.url)
                title(photo.title)
            }
        }
    }
}

RIBs:

class PhotoListBuilder(dependency: Component) : Builder<PhotoListRouter, PhotoListInteractor>() {
    override fun build(parentViewGroup: ViewGroup): PhotoListRouter {
        val view = PhotoListView(parentViewGroup.context)
        val interactor = PhotoListInteractor()
        return PhotoListRouter(view, interactor)
    }
}

While RIBs focuses on app architecture and navigation, Epoxy specializes in efficient list rendering. RIBs provides a more comprehensive structure for large-scale apps, while Epoxy excels at simplifying complex RecyclerView implementations.

A small, yet full-featured framework that allows building View-based Android applications

Pros of Conductor

  • Simpler learning curve and easier to implement for basic navigation scenarios
  • More flexible and lightweight, allowing for custom implementations
  • Better suited for smaller to medium-sized projects

Cons of Conductor

  • Less opinionated architecture, which may lead to inconsistencies in large teams
  • Lacks built-in state management and dependency injection features
  • May require additional libraries for complex app structures

Code Comparison

Conductor basic usage:

Router.setRoot(RouterTransaction.with(HomeController()))

RIBs basic usage:

class RootBuilder(dependency: RootDependency) : ViewBuilder<RootView, RootRouter, RootDependency>(dependency) {
    override fun build(parentViewGroup: ViewGroup): RootRouter {
        val view = RootView(parentViewGroup.context)
        val interactor = RootInteractor()
        return RootRouter(view, interactor, component)
    }
}

Conductor focuses on simplicity for navigation, while RIBs provides a more comprehensive architecture with built-in patterns for larger, more complex applications. Conductor offers more flexibility but requires additional effort for advanced features, whereas RIBs provides a structured approach out-of-the-box at the cost of a steeper learning curve.

5,683

A sample Android app which showcases advanced usage of Dagger among other open source libraries.

Pros of u2020

  • Simpler architecture, easier to understand for small to medium-sized projects
  • Focuses on showcasing best practices in Android development
  • Includes examples of popular libraries like Dagger, Retrofit, and Picasso

Cons of u2020

  • Less scalable for large, complex applications
  • Not actively maintained (last update in 2017)
  • Limited to Android platform

Code Comparison

u2020 (Dagger module example):

@Module(
    injects = {
      U2020App.class,
      MainActivity.class
    },
    includes = {
      AndroidModule.class,
      DataModule.class,
      UiModule.class
    }
)
public final class U2020Module {
  // Module implementation
}

RIBs (RIB router example):

class SomeRouter(
    interactor: Interactor<SomeInteractor.SomePresenter, SomeRouting>,
    component: SomeBuilder.Component
) : ViewRouter<SomeView, SomeInteractor, SomeBuilder.Component>(interactor, component) {
    // Router implementation
}

While u2020 demonstrates a more traditional Android architecture, RIBs introduces a unique approach to building scalable mobile applications. RIBs offers better separation of concerns and is designed for large-scale apps, but may have a steeper learning curve compared to u2020's more conventional structure.

5,490

A Model-View-Presenter / Model-View-Intent library for modern Android apps

Pros of Mosby

  • Simpler architecture, easier to learn and implement for smaller projects
  • Focuses on MVP pattern, which is widely understood in the Android community
  • Provides ready-to-use base classes for common scenarios

Cons of Mosby

  • Less scalable for large, complex applications compared to RIBs
  • Limited to MVP architecture, while RIBs offers more flexibility
  • Less active development and community support

Code Comparison

Mosby (MVP pattern):

class MyPresenter : MvpBasePresenter<MyView>() {
    fun loadData() {
        view?.showLoading()
        // Load data and update view
    }
}

RIBs (Router-Interactor-Builder pattern):

class MyRouter(
    interactor: Interactor<MyInteractor.MyPresenter, MyInteractor>,
    component: MyBuilder.Component
) : ViewRouter<MyView, MyInteractor>(view, interactor) {
    // Router implementation
}

Both libraries aim to improve Android app architecture, but they take different approaches. Mosby focuses on the MVP pattern, making it easier to implement for smaller projects. RIBs, developed by Uber, offers a more complex but scalable architecture suitable for large applications. The choice between the two depends on project size, complexity, and team preferences.

2,786

Name UI states, navigate between them, remember where you've been.

Pros of Flow

  • Simpler architecture, easier to learn and implement
  • Better suited for smaller to medium-sized apps
  • More flexible, allowing developers to choose their preferred architecture patterns

Cons of Flow

  • Less opinionated, which may lead to inconsistencies in large teams
  • Lacks built-in state management solutions
  • May require additional libraries for complex navigation scenarios

Code Comparison

Flow:

class HomeScreen : Screen {
    @Composable
    override fun Content() {
        Text("Welcome to Flow!")
    }
}

RIBs:

class HomeBuilder(dependency: HomeDependency) : ViewBuilder<HomeView, HomeRouter, HomeDependency>(dependency) {
    override fun build(parentViewGroup: ViewGroup): HomeRouter {
        val view = createView(parentViewGroup)
        val interactor = HomeInteractor()
        return HomeRouter(view, interactor, dependency)
    }
}

Flow focuses on simplicity and composability, making it easier to create and manage screens. RIBs, on the other hand, provides a more structured approach with separate components for routing, interacting, and building views.

While Flow offers more flexibility and is easier to adopt, RIBs provides a robust architecture that scales well for large, complex applications. The choice between the two depends on the project size, team preferences, and specific requirements of the application.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

RIBs

Android CI License Maven Central Cocoapods Compatible Carthage Compatible

RIBs is the cross-platform architecture framework behind many mobile apps at Uber. The name RIBs is short for Router, Interactor and Builder, which are core components of this architecture. This framework is designed for mobile apps with a large number of engineers and nested states.

The RIBs architecture provides:

  • Shared architecture across iOS and Android. Build cross-platform apps that have similar architecture, enabling iOS and Android teams to cross-review business logic code.
  • Testability and Isolation. Classes must be easy to unit test and reason about in isolation. Individual RIB classes have distinct responsibilities like: routing, business, view logic, creation. Plus, most RIB logic is decoupled from child RIB logic. This makes RIB classes easy to test and reason about independently.
  • Tooling for developer productivity. RIBs come with IDE tooling around code generation, memory leak detection, static analysis and runtime integrations - all which improve developer productivity for large teams or small.
  • An architecture that scales. This architecture has proven to scale to hundreds of engineers working on the same codebase and apps with hundreds of RIBs.

Documentation

To get started with RIBs, please refer to the RIBs documentation. This describes key concepts on RIBs, from what they are for, their structure and common use cases.

To get more hands on with RIBs, we have written a series of tutorials that run you through the main aspects of the architecture with hands-on examples.

To read about the backstory on why we created RIBs, see this blog post we wrote when releasing RIBs in production the first time and see this short video where we discussed how the RIBs architecture works.

What is the difference between RIBs and MV*/VIPER?

MVC, MVP, MVI, MVVM and VIPER are architecture patterns. RIBs is a framework. What differentiates RIBs from frameworks based on MV*/VIPER is:

  • Business logic drives the app, not the view tree. Unlike with MV*/VIPER, a RIB does not have to have a view. This means that the app hierarchy is driven by the business logic, not the view tree.
  • Independent business logic and view trees. RIBs decouple how the business logic scopes are structured from view hierarchies. This allows the application to have a deep business logic tree, isolating business logic nodes, while maintaining a shallow view hierarchy making layouts, animations and transitions easy.

There are some other novel things about RIBs. However, these could also be implemented with other MV*/VIPER frameworks. These are:

  • Cross-platform approach, allowing iOS and Android architecture to stay in sync.
  • Tooling for easier adoption on larger apps or teams. Tooling we are open sourcing includes IDE plugins for code generation and static code analysis.
  • Strong opinions about how state should be communicated, using DI and Rx. Each RIB defines its dependencies and what dependencies it needs from its parent. Parent components that fulfill a child’s parent dependencies are provided to child Builders as a constructor dependency to allow for hierarchical DI scoping. This means that information is communicated via these dependencies up and down the tree.

Usage

  1. Clone this repository
  2. Integrate using your preferred installation mechanism

For usage of the tooling built around RIBs, please see the Tooling section in our documentation.

Installation for Android

To integrate the recommended minimum setup for RIBs add the following to your build.gradle:

dependencies {
  annotationProcessor 'com.uber.rib:rib-compiler-test:0.16.3'
  implementation 'com.uber.rib:rib-android:0.16.3'
  testImplementation 'com.uber.rib:rib-test:0.16.3'
}

There are a number of extension packages available as well including Kotlin extensions, Jetpack Compose support, Coroutines support

Installation for iOS

CocoaPods

To integrate RIBs into your project add the following to your Podfile:

pod 'RIBs', '~> 0.9'

Carthage

To integrate RIBs into your project using Carthage add the following to your Cartfile:

github "uber/RIBs" ~> 0.9

Related projects

If you like RIBs, check out other related open source projects from our team:

  • Needle: a compile-time safe Swift dependency injection framework.
  • Motif: An abstract on top of Dagger offering simpler APIs for nested scopes.
  • Swift Concurrency: a set of concurrency utility classes used by Uber, inspired by the equivalent java.util.concurrent package classes.
  • Swift Abstract Class: a light-weight library along with an executable that enables compile-time safe abstract class development for Swift projects.
  • Swift Common: common libraries used by this set of Swift open source projects.

License

Copyright (C) 2017 Uber Technologies

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.