Rosie is an Android framework to create applications following the principles of Clean Architecture.

Related tags

Rosie
Overview

Karumi logoRosie Maven Central

The only way to make the deadline—the only way to go fast—is to keep the code as clean as possible at all times.

— Robert C. Martin in Clean Code: A Handbook of Agile Software Craftsmanship

Introduction

Rosie is an Android framework to create applications following the principles of Clean Architecture.

Rosie divides your application in three layers, view, domain and repository. For each layer, Rosie provides plenty of classes that will make defining and separating these concerns much easier.

  • View: It contains all your presentation logic, implemented through the Model-View-Presenter pattern. Rosie provides classes to represent the main components of this layer like RosieActivity, RosieFragment or RosiePresenter.
  • Domain: Holding all your business logic, its main component is RosieUseCase that gives you an easy way to define your application use cases and execute them in a background thread using the command pattern.
  • Repository: This layer gives you an abstraction of how to retrieve and store data in your application following the Repository pattern. RosieRepository and the multiple DataSource classes gives you the base to start building your own repositories.

Finally, Rosie comes with Dagger to solve Dependency inversion through Dependency Injection.

Screenshots

Screencast

Application UI/UX designs by Luis Herrero.

Data provided by Marvel. © 2016 MARVEL

Usage

First thing you will need to do is to make your own Application instance extend RosieApplication in order to provide your global dependencies module to Dagger:

public class SampleApplication extends RosieApplication {
	@Override protected List<Object> getApplicationModules() {
		return Arrays.asList((Object) new SampleGlobalModule());
	}
}

Extending from RosieApplication is needed to be able to easily use the configuration Rosie provides you related to Dependency Injection. If you do not want to use Dependency Injection in your project, you do not need to extend from RosieApplication.

Rosie provides several base classes to start implementing your architecture separated in three layers, view, domain and repository. Let's explore them in detail.

View

The view package contains all the classes needed to implement your presentation logic following the MVP pattern. To use the view package, make your Activity extend from RosieActivity or your Fragment from RosieFragment and specify the layout that Rosie will automatically inflate for you:

public class SampleActivity extends RosieActivity {
	@Override protected int getLayoutId() {return R.layout.sample_activity;}
	/*...*/
}

Extending from RosieActivity or RosieFragment is not mandatory. If your project is already extending from any other base Activity please review the class PresenterLifeCycleLinker and use it inside your base Activity or your Activities as follow:

public abstract class MyBaseActivity extends FragmentActivity
    implements RosiePresenter.View {

  private PresenterLifeCycleLinker presenterLifeCycleLinker = new PresenterLifeCycleLinker();

  @Override protected void onCreate(Bundle savedInstanceState) {
    ...
    presenterLifeCycleLinker.initializeLifeCycle(this, this);
    ...
  }
  @Override protected void onResume() {
    ...
    presenterLifeCycleLinker.updatePresenters(this);
    ...
  }

  @Override protected void onPause() {
    ...
    presenterLifeCycleLinker.pausePresenters();
    ...
  }

  @Override protected void onDestroy() {
    ...
    super.onDestroy();
    ...
  }

}

Rosie provides you some base classes to be extended and give you a quick access to the Dependency Injection and Model View Presenter features, but the usage of inheritance to use these features is not mandatory.

Dagger

Besides, you can define the Dagger dagger module that will contain the dependencies for your activity by overriding the getActivityScopeModules method:

public class SampleActivity extends RosieActivity {
	@Override protected List<Object> getActivityScopeModules() {
		return Arrays.asList((Object) new SampleModule());
	}
	/*...*/
}

There is also two useful annotations to provide Context dependencies into your classes, one for your Application context and one for your current Activity:

public class InjectedClass {
	@Inject public InjectedClass(@ForApplication Context applicationContext, @ForActivity Context activityContext) {
		/*...*/
	}
}

Presenter

To follow the MVP pattern, Rosie provides a RosiePresenter class that will be responsible for all your presentation logic. Rosie will take care of linking your view (a RosieActivity or RosieFragment implementation) with your presenter and subscribing it to its lifecycle. In order to do that, create a RosiePresenter and inject it into your activity/fragment with the @Presenter annotation:

public class SamplePresenter extends RosiePresenter<SamplePresenter.View> {
	public interface View extends RosiePresenter.View {
		/*...*/
	}
}
public class SampleActivity extends RosieActivity implements SamplePresenter.View {
	@Inject @Presenter SamplePresenter presenter;
	@Override protected void onPreparePresenter() {/*...*/}
}

Once both, view and presenter, are linked you can react to your view lifecycle directly from the presenter. The onPreparePresenter method gives you the opportunity to configure your presenter before any of these methods are called (e.g. with your intent parameters). You will be also able to call your view easily from the presenter:

public class SamplePresenter extends RosiePresenter<SamplePresenter.View> {
	protected void initialize() {/*...*/}
	protected void update() {/*...*/}
	protected void pause() {/*...*/}
	protected void destroy() {/*...*/}
	
	private void sampleMethod() {
		View view = getView(); // Get the view linked to the presenter
		view.foo();
	}
	
	public interface View extends RosiePresenter.View {
		void foo();
	}
}

To understand when the lifecycle methods are called take a look at the following table:

RosiePresenter Activity Fragment
initialize onCreate onViewCreated
update onResume onResume
pause onPause onPause
destroy onDestroy onDestroy

Domain

The domain package is meant to contain all your business logic that will change from app to app. For that reason, Rosie only provides a single RosieUseCase class that will help you execute your use cases in background following the command pattern.

To start using the Rosie domain package, create your use cases extending RosieUseCase and define the method containing your use case logic. Remember to call notifySuccess or notifyError to get results back to your presenter:

public class DoSomething extends RosieUseCase {
	@UseCase public void doSomething(Object arg) {
		Object response = getData();
		if (response.isOk()) {
			notifySuccess(response.getContent());
		} else {
			notifyError(response.getError());
		}
	}
}

To call your use case, create a UseCaseCall, configure it and execute it. Rosie gives you a fluent API to easily do this from your presenters:

public class SamplePresenter extends RosiePresenter<SamplePresenter.View> {
	public void callUseCase() {
		createUseCaseCall(doSomething)
			.args(arg /*, arg2, arg3, ...*/)
			.onSuccess(new OnSuccessCallback() {
				/*...*/
			})
			.onError(new OnErrorCallback() {
				/*...*/
			})
			.execute();
	}
	/*...*/
}

All the configuration calls are optional and can be omitted when not needed but keep in mind that provided arguments must match the ones declared in your UseCase method or an error will be raised. It is important to keep in mind that, by default, your callback methods will be executed in the main thread so you can easily update your UI from them.

Named use cases

Sometimes you need to specify use cases that are very similar to each other. To avoid creating multiple classes representing every use case configuration, you can create a single RosieUseCase class with multiple methods. Rosie will be able to identify the use case being called by matching its input parameters. If you create two methods with the @UseCase annotation that have the same input parameters, you can provide a name to each of them in order to identify them:

public class DoSomething extends RosieUseCase {
	public static final String USE_CASE_NAME = "UseCaseName";
	public static final String OTHER_USE_CASE_NAME = "OtherUseCaseName";
	@UseCase(name = USE_CASE_NAME) public void doSomething(Object arg) {/*...*/}
	@UseCase(name = OTHER_USE_CASE_NAME) public void doSomethingElse(Object arg) {/*...*/}
}

Even though using names is not mandatory when the method input parameters are different, it's highly recommended to use them just to make its usage more readable.

To call a named use case just configure its name:

public class SamplePresenter extends RosiePresenter<SamplePresenter.View> {
	public void callUseCase() {
		createUseCaseCall(doSomething)
			.args(arg)
			.useCaseName(DoSomething.USE_CASE_NAME)
			.execute();
	}
	/*...*/
}

Error handling

Errors can be either manually reported or implicitly notified when an exception is thrown from your use case context. To handle errors, there is a capturing event system that iterates over all your registered OnErrorCallback implementations and notifies them of the issue. Every callback needs to return a boolean value to inform whether the error has been handled and needs no further management. Callbacks are always called in this specific order:

  1. Use case specific callback; the ones you register while calling a use case.
  2. Global callbacks; the ones you can register from your presenter constructor.

With this approach you can create an error callback in your presenter that shows a generic error message to your user and create multiple other listeners for specific use cases and/or errors.

To register global callbacks from your presenter, call registerOnErrorCallback in the constructor:

public class SamplePresenter extends RosiePresenter<SamplePresenter.View> implements OnErrorCallback {
	public SamplePresenter(UseCaseHandler useCaseHandler) {
		super(useCaseHandler);
		registerOnErrorCallback(this);
	}

	@Override public boolean onError(Error error) {
		getView().showGenericError();
		return true;
	}
}

As explained in the UseCase section, you can also register error callbacks for a use case call. Rosie will assign those a higher priority:

public class SamplePresenter extends RosiePresenter<SamplePresenter.View> {
	public void callUseCase() {
		createUseCaseCall(doSomething)
			.args(arg)
			.onError(new OnErrorCallback() {
				getView().showSpecificError();
				// The error has been handled
				// Avoid calling any other error callback by returning true
				return true;
			})
			.execute();
	}
	/*...*/
}

You can create your own ErrorFactory implementation to map Exceptions to Errors. In your implementation you can unify your error handling.

public class CustomErrorFactory extends ErrorFactory {

	@Inject public CustomErrorFactory() {
	}

	@Override public Error create(Exception exception) {
		if (targetException instanceof MyConnectionException) {
			return new ConnectionError();
		}
		return new UnknownError();
  }
}

Remember to provide your ErrorFactory implementation inside a Dagger module.

	@Provides public ErrorHandler providesErrorHandler(CustomErrorFactory errorFactory) {
		return new ErrorHandler(errorFactory);
	}

Repository

The third layer is meant to encapsulate your data sources. To start using it just extend RosieRepository and configure its data sources in its constructor:

public class SampleRepository extends RosieRepository<Key, Value> {
	@Inject public SampleRepository(SampleApiDataSource sampleApiDataSource,
			SampleCacheDataSource sampleCacheDataSource) {
		addReadableDataSources(sampleApiDataSource);
		addCacheDataSources(sampleCacheDataSource);
	}
}

There are three different types of data sources and each one has its own interface that you can implement to use it in your repository:

  • ReadableDataSource<K, V>: Defines data sources where you can read values by a given key or retrieving them all.
  • WriteableDataSource<K, V>: Defines data sources where you can persist data with operations to add, update or delete values.
  • CacheDataSource<K, V>: Defines a mix of readable and writeable data sources to speed up access to your values.

There are empty implementations of each data source to simplify your own subclasses by overriding only the methods that make sense in your context. Besides, there is a generic InMemoryCacheDataSource to store recent values up to a configurable time.

public class SampleRepository extends RosieRepository<Key, Value> {
	@Inject public SampleRepository() {
	PaginatedCacheDataSource<Key, Value> inMemoryCacheDataSource =
		new InMemoryCacheDataSource<>(new TimeProvider(), MINUTES.toMillis(5));
	addCacheDataSources(inMemoryCacheDataSource);
  }
}

Users of the repositories can retrieve or modify data by using one of the multiple methods available for that matter. There are multiple ways to retrieve and store data using repositories, the following snippet shows some of the most useful:

// Initialization
Key key = /*...*/; Value value; Collection<Value> values;
RosieRepository<Key, Value> repository = /*...*/;

// Get a value by its key
value = repository.getByKey(key);
// Get a value by its key using only the defined cache
value = repository.getByKey(key, ReadPolicy.CACHE_ONLY);
// Get all the available values
values = repository.getAll();
// Get all the available values using only readable sources
values = repository.getAll(ReadPolicy.READABLE_ONLY);
// Add a new value
repository.addOrUpdate(value);
// Add a new value only to the first writeable data source that works
repository.addOrUpdate(value, WritePolicy.WRITE_ONCE);
// Delete a value by its key
repository.deleteByKey(key);
// Delete all values stored in the repository
repository.deleteAll();

Paginated repositories

Finally, Rosie gives you support for pagination in repositories. If your data is paginated, just extend PaginatedRosieRepository instead of RosieRepository. You will also need to implement your paginated data sources, PaginatedReadableDataSource<V> and PaginatedCacheDataSource<K, V>. Once your paginated repository is completely defined and configured you will be able to use it just as a regular repository with additional pagination-related methods:

// Initialization
Key key = /*...*/; PaginatedCollection<Value> page;
PaginatedRosieRepository<Key, Value> repository = /*...*/;

// Get a value by its key just as with a regular repository
Value value = repository.getByKey(key);
// Get a page
page = repository.getPage(Page.withOffsetAndLimit(offset, limit));
// Get a page using only the cache data source
page = repository.getPage(Page.withOffsetAndLimit(offset, limit), ReadPolicy.CACHE_ONLY);

To run the application using real data obtained from the Marvel API create a marvel.properties file inside the sample directory and add your public and private key there as follows:

MARVEL_PUBLIC_KEY="YOUR_MARVEL_PUBLIC_KEY"
MARVEL_PRIVATE_KEY="YOUR_MARVEL_PRIVATE_KEY"

Add it to your project

Include the library in your build.gradle

dependencies{
    compile 'com.karumi.rosie:rosie:3.0.2'
}

or to your pom.xml if you are using Maven

<dependency>
    <groupId>com.karumi.rosie</groupId>
    <artifactId>rosie</artifactId>
    <version>3.0.2</version>
    <type>aar</type>
</dependency>

More information?

We are writing some blog posts to explain the main motivations behind Rosie and some desing considerations:

Related projects

Do you want to contribute?

Feel free to report us or add any useful feature to the library, we will be glad to improve it with your help.

Keep in mind that your PRs must be validated by Travis-CI. Please, run a local build with ./gradlew checkstyle build connectedCheck before submitting your code.

Libraries used in this project

License

Copyright 2015 Karumi

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.
Issues
  • Error when running a signed APK

    Error when running a signed APK

    Hi, I do not understand what is happening.

    • When I install the app from Android Studio with the debugkeystore by default, there is no problem.
    • When I sign the app with the Android Studio tool and my keystore, then I pass it to the phone, install the app, execute and ERROR: This object does not contain any use case to execute. Did you forget to add the @UseCase annotation?

    Why these two different behaviors with the same code?

    Has something similar happened to you?

    Thanks in advance

    opened by pinicius 17
  • Moving Butter Knife and Renderers libraries from Rosie to the sample project, updated sample butterknife version 7.0.1 -> 8.0.1

    Moving Butter Knife and Renderers libraries from Rosie to the sample project, updated sample butterknife version 7.0.1 -> 8.0.1

    There was a warning for using a @Nullable over a @OnClick method in MarvelActivity.java, I have updated Butterknife, replace that @Nullable for @Optional and updated all the @Bind annotation for @BindView. Fix #70

    opened by luis-ibanez 11
  • Add a new interface extending from RosiePresenter.View

    Add a new interface extending from RosiePresenter.View

    Some of the views we have to implement have a loading state. We are going to create a RosiePresenter.ViewWithLoading interface with two methods: showLoading and hideLoading to avoid code duplicity in all the library client code related to this classes.

    enhancement 
    opened by Serchinastico 10
  • Do you think about using rxjava?

    Do you think about using rxjava?

    question 
    opened by Rainer-Lang 8
  • New repositories approach

    New repositories approach

    This is my repositories approach, it doesn't bring anything new to the table, it's just a clean up and a better segregation of interfaces, to wrap up:

    Repository

    As in the old implementation, if you want to create your repositories just extend from this class. To configure your data sources, call addReadables, addWriteables, addCaches in your constructor:

      public SampleRepository(SampleReadable sampleReadable, SampleWriteable sampleWriteable,
          SampleInMemoryCache sampleInMemoryCache) {
        addReadables(sampleReadable);
        addWriteables(sampleWriteable);
        addCaches(sampleInMemoryCache);
      }
    

    To do special stuff, like reading only from cache, reading only fresh data, etc, there is a method with a ReadPolicy that let's you define those special cases.

    Readable, Writeable, Cache

    This is the separation of the previous DataSource interface. Readable has get and getAll methods, Writeable has addOrUpdate, addOrUpdateAll, delete and deleteAll methods. Finally, Cache just merges these two interfaces. There is still the problem of having to implement methods you might not need (I might only need to implement get and don't need to implement getAll). You can use one of the EmptyReadable, EmptyWriteable and EmptyCache classes which provides an empty implementation for every method.

    I did an MVP with an implementation based on annotations where data sources only need to annotate it's get method with a @Get annotation. If the annotation is not present then the repository goes to the following data source. I've done some profiling and the annotation-based implementation is 20 times slower, we are talking about repository calls of 7ms which I think it's not acceptable. We might use apt but it will take us longer.

    Pagination is solved in the same fashion as in the previous implementation.

    Let me know the parts you like, the parts you don't, and let's close the repositories.

    opened by Serchinastico 8
  • Sample tests

    Sample tests

    • adding test to sample
    • adding error handler sample.
    opened by flipper83 6
  • Feedback from DroidsOnRoids

    Feedback from DroidsOnRoids

    @flipper83 @Serchinastico we have some feedback about Rosie in this blog post: http://www.thedroidsonroids.com/blog/android/rosie-lets-dive-into-clean-architecture/ There are some things we could improve like: change some methods visibility in the RosiePresenter to improve the class testability from the unit test point of view. What do you think?

    question 
    opened by pedrovgs 6
  • Move butter knife and renderers to the sample

    Move butter knife and renderers to the sample

    Fixes #70

    opened by luis-ibanez 6
  • I have another question, How can I include third library in my arr like your rosie?

    I have another question, How can I include third library in my arr like your rosie?

    I have many third library in my android library like Rosie with dagger and Butter Knife.But my arr package not include this, so It can't reference this library.

    How can i build it let my arr include this third library?Thx

    question 
    opened by h3clikejava 5
  • Marvel example

    Marvel example

    This branch includes some minor changes anticipating what we talked with Luis for the new designs

    • Add a toolbar in detail activities
    • Replace comic by comic series and add a grid of comics inside the comic series details window
    • Use native tabview
    opened by Serchinastico 5
  • Update gradle

    Update gradle

    :tophat: What is the goal?

    Update Gradle (tools, wrapper..) to improve the compilation time and take advantage of the last improvements in Android Studio 3.0. Also, update dependencies to follow new implementation/api instead of compile standard, that helps to improve compilation times

    How is it being implemented?

    • Follow this tutorial https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration?utm_source=android-studio#new_configurations
    • Add google() repository
    • Set compile version and target version to 27
    • Create variables in gradle to update the versions of the library and the samples at the same time

    GIF

    happy

    opened by Aracem 4
  • Allowing to implement RosiePresenter.View interfaces in base Fragments or Activity classes

    Allowing to implement RosiePresenter.View interfaces in base Fragments or Activity classes

    Hello guys! First of all thank you very much for Rosie. It has been very helpful in the project We are working on.

    I tried to implement my View interface in a Base Fragment class and I realized that was not possible because in RosiePresenter.class getViewInterfaceClass method was not looking for interfaces in any available super classes. I added a method that is called inside getViewInterfaceClass for seeking any RosiePresenter.View interfaces in any super class available if there is no RosiePresenter.View interfaces in the current class.

    PS: I ran the tests but I got this error while testing the app sample: android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (with id: com.karumi.rosie.sample:id/snackbar_text and with text...

    Thank you!

    opened by felHR85 2
  • Stabilize Travis-CI builds

    Stabilize Travis-CI builds

    As we've seen for the last months Travis-CI is failing constantly due to problems initializing the Android emulator, even when our tests are not flacky at all. Travis-CI is one of the core components in this project, so we should try to stabilize our build in Travis-CI environments using this tool

    enhancement 
    opened by pedrovgs 2
  • OnErrorCallback null pointer exception with Marshmallow devices

    OnErrorCallback null pointer exception with Marshmallow devices

    Every time I call the method notifyError(new Error("Error")) in a UseCase class I'm getting a null pointer exception. It seems that when I create the " .onError(new OnErrorCallback() {...}" in the presenter something goes wrong."I have tried with two different devices using Marshmallow version and in both cases the result is:

    java.lang.NullPointerException: Attempt to invoke interface method 'boolean com.karumi.rosie.domain.usecase.error.OnErrorCallback.onError(java.lang.Error)' on a null object reference at com.karumi.rosie.domain.usecase.RosieUseCase.notifyError(RosieUseCase.java:77)

    Versions under Marshmallow works perfectly. Any tip about what is causing this error?

    Thanks in advance

    bug 
    opened by bcarrera 1
  • Extract caching logic from RosieRepository.java

    Extract caching logic from RosieRepository.java

    I think It's not cool to put the caching logic directly into the repository (RosieRepository.java) because it violates the Single Responsibility Principle. Now, the concerns of data access and caching policy is in the same class, and if either of these changes, you'll need to change the class.

    A better approach would be to use a Proxy pattern to apply the caching logic in a separate type like CachedRosieRepository.

    enhancement 
    opened by RPallas92 1
  • NoSuchMethodError. No ButterKnife.bind(Activity) method

    NoSuchMethodError. No ButterKnife.bind(Activity) method

    Hi,

    I got weird crash when extending RosieAppCompatActivity. http://crashes.to/s/129c15fd43c

    Fatal Exception: java.lang.NoSuchMethodError: No static method bind(Landroid/app/Activity;)V in class Lbutterknife/ButterKnife; or its super classes (declaration of 'butterknife.ButterKnife' appears in /data/app/com.anotherdev.photos500.debug-1/base.apk)
           at com.karumi.rosie.view.RosieAppCompatActivity.onCreate(RosieAppCompatActivity.java:50)
    

    Except from my dependencies:

    compile 'com.jakewharton:butterknife:8.0.1'
    apt 'com.jakewharton:butterknife-compiler:8.0.1'
    compile 'com.karumi.rosie:rosie:2.1.0'
    
    opened by anotherdev 1
  • Review Repository/PaginatedRepository use.

    Review Repository/PaginatedRepository use.

    To use a PaginatedRepository implementation we have to extend from PaginatedRepository and write code like this:

    
      @Inject public CharactersRepository(CharacterDataSourceFactory characterDataSourceFactory,
          @Named(ApplicationModule.CHARACTERS_PAGE_IN_MEMORY_CACHE)
          PaginatedCacheDataSource<String, Character> inMemoryPaginatedCache,
          @Named(ApplicationModule.CHARACTERS_IN_MEMORY_CACHE)
          CacheDataSource<String, Character> inMemoryCache) {
        addCacheDataSources(inMemoryCache);
        addPaginatedCacheDataSources(inMemoryPaginatedCache);
    
        CharacterDataSource characterDataSource = characterDataSourceFactory.createDataSource();
        addReadableDataSources(characterDataSource);
        addPaginatedReadableDataSources(characterDataSource);
      }
    

    We should review this implementation to do not need to add the data source to the cache data sources list and the paginated list. We should just configure the same data source once because a paginated data source should be used as a normal data source.

    The usage of the repository should be something like:

    
      @Inject public CharactersRepository(CharacterDataSourceFactory characterDataSourceFactory,
          @Named(ApplicationModule.CHARACTERS_PAGE_IN_MEMORY_CACHE)
          PaginatedCacheDataSource<String, Character> inMemoryPaginatedCache) {
        addPaginatedCacheDataSources(inMemoryPaginatedCache);
    
        CharacterDataSource characterDataSource = characterDataSourceFactory.createDataSource();
        addPaginatedReadableDataSources(characterDataSource);
      }
    
    enhancement 
    opened by pedrovgs 0
  • Add realm migration DB

    Add realm migration DB

    On current realm data source implementation the migration policy is remove the previous database values and create the table with empty values. That could be good for some project but someone it's posible that have other requirement, could be good can configure the migration Policy from outside without override the method getRealm.

    enhancement 
    opened by flipper83 0
  • Create a Realm Data Source

    Create a Realm Data Source

    Create a realm data source that implement Rosie Data source, for people can use directly Realm on his projects. this dataSource implementation must be out of rosie default implementation.

    enhancement 
    opened by flipper83 0
  • Add Activity extra injection library

    Add Activity extra injection library

    Provide a way to inject Activity extra parameters automatically

    enhancement 
    opened by Serchinastico 0
Releases(3.0.2)
  • 3.0.2(Aug 3, 2018)

  • 3.0.1(Mar 16, 2018)

  • 3.0.0(Mar 7, 2017)

    With this release, we are removing some dependencies from the library to make it easier for you to import it into your projects! To be precise, we have removed Butterknife and Renderers.

    If you want to update to this version of the library, just follow the steps described in #86

    Source code(tar.gz)
    Source code(zip)
  • 2.1.2(Mar 6, 2017)

    This release can be considered a hotfix, we have reverted the removal of butterknife and renderers from the library itself. We will move that commit to version 3.0.0

    Source code(tar.gz)
    Source code(zip)
  • 2.1.1(Feb 20, 2017)

  • 2.1.0(Apr 4, 2016)

  • 2.0.0(Mar 28, 2016)

    Model View Presenter implementation improvements. Given all the feedback received related to the MVP implementation we have decided to update some code related to this feature in order to be able to use it without RosieActivity or RosieFragment.

    • Change PresenterLifeCycleLinker visibility to be public.
    • Change RosiePresenter lifecycle methods and setView method to be public and improve testability from the unit testing point of view.
    • Update some dependencies like Renderers or Priority Job Queue.
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Mar 11, 2016)

  • rosie-1.0.0(Feb 25, 2016)

Owner
Karumi
Karumi, the Rock Solid Code studio
Karumi
A full-featured framework that allows building android applications following the principles of Clean Architecture.

EasyMVP A powerful, and very simple MVP library with annotation processing and bytecode weaving. EasyMVP eliminates the boilerplate code for dealing w

null 1.3k Aug 6, 2021
UltimateAndroid is a rapid development framework for developing your apps

UltimateAndroid Version:0.10.2 UltimateAndroid is a rapid development framework for developing apps Master branch: Dev branch: V0.7.0 Ui Demo screensh

MarshalChen 2.1k Sep 12, 2021
Android Plugin Framework

Android Plugin Framework This project is pre-mature and may be changed very frequently. Introduction Android Plugin Framework (APF) aims to providing

Umeng Limited 326 Jul 27, 2021
A Mosby based VIPER library for Android

Moviper A Mosby based VIPER library for Android Why Moviper? You got tired because of fact that your Activities and Fragments were becoming god classe

Mateusz Koślacz 78 Dec 11, 2020
A Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving UX and application stability.

This Project is Deprecated! Thanks to everybody who've used Android Priority JobQueue. It was designed in a world where there was no JobScheduler, RxJ

Yigit Boyar 3.4k Sep 16, 2021
A small, yet full-featured framework that allows building View-based Android applications

Conductor A small, yet full-featured framework that allows building View-based Android applications. Conductor provides a light-weight wrapper around

BlueLine Labs 3.8k Sep 14, 2021
MVVM framework for Android

RoboMVVM - MVVM Framework For Android RoboMVVM is an open source library that facilitates the use of the MVVM pattern in Android apps. The MVVM patter

Debdatta Basu 55 Nov 24, 2020
Kick-starts Android application development.

Synopsis If you've made it here, chances are you are not quite as satisfied with the Android application framework as you could be. Same for us, that'

Matthias Käppler 1.3k Aug 26, 2021
Cross-platform framework for building truly native mobile apps with Java or Kotlin. Write Once Run Anywhere support for iOS, Android, Desktop & Web.

Codename One - Cross Platform Native Apps with Java or Kotlin Codename One is a mobile first cross platform environment for Java and Kotlin developers

Codename One 1.1k Sep 15, 2021
dexposed enable 'god' mode for single android application.

What is it? Dexposed is a powerful yet non-invasive runtime AOP (Aspect-oriented Programming) framework for Android app development, based on the work

Alibaba 4.4k Sep 10, 2021
Nucleus is an Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application.

Nucleus Deprecation notice Nucleus is not under develpment anymore. It turns out that Redux architecture scales way better than MVP/MVI/MVVM/MVxxx and

Konstantin Mikheev 2k Aug 25, 2021
A data-binding Presentation Model(MVVM) framework for the Android platform.

PLEASE NOTE, THIS PROJECT IS NO LONGER BEING MAINTAINED. As personal time contraints, I am currently unable to keep up. Please use official android da

RoboBinding open source 1.3k Aug 13, 2021
Android app built with MVP architectural approach and uses Marvel Comics API that allows developers everywhere to access information about Marvel's vast library of comics. :zap:

Villains & Heroes Android app built with MVP architectural approach and uses Marvel Comics API that allows developers everywhere to access information

André Mion 53 Jun 28, 2021
Moxy is MVP library for Android

Moxy This Moxy repository is deprecated and no longer supported. Please migrate to the actual version of the Moxy framework at Moxy communuty repo. De

Arello Mobile 1.6k Sep 9, 2021
A collection of hand-crafted extensions for your Kotlin projects.

Splitties Splitties is a collection of small Kotlin multiplatform libraries (with Android as first target). These libraries are intended to reduce the

Louis CAD 1.9k Sep 16, 2021
Android Development Utils

QuickUtils This repository offers a set of random useful classes to deal with repetitive tasks in the Android Framework. Intended to help you getting

César Ferreira 254 Sep 1, 2021
A framework for hook java methods.

Legend Projects are out of date, plese move to: Whale Hook What is Legend? Legend is a Hook framework for Android Development, it allows you to Hook J

Lody 1.5k Sep 12, 2021
a MVP library for Android favoring a stateful Presenter

DEPRECATED - no longer actively maintained ThirtyInch - a MVP library for Android This library adds Presenters to Activities and Fragments. It favors

HCI @ gcx 1.1k Aug 19, 2021
🔥 Android component-based routing framework

README-CN Latest version module krouter-core krouter-compiler krouter-annotation krouter-plugin version Features 支持通过路由获取intent 支持方法注解,通过路由调用方法 支持给fra

Jiaming Gu 3 Sep 16, 2021