Giter Club home page Giter Club logo

scoop's Introduction

Deprecation Note

The open-source version of Scoop is no longer actively maintained and does not represent the version of Scoop currently being used internally at Lyft.

Scoop Build Status

Scoop is a micro framework for building view based modular Android applications.

What do I get?

  1. Router. Object that allows you to navigate between screens and maintain backstack.
  2. View controllers. A new building block that you will use instead of Activity and Fragments.
  3. Layouts. A new building block that you will use instead of Activity and Fragments.
  4. Scoops ("Scopes"). Hierarchical scopes that allows you organize your application dependencies and their lifespan.
  5. Transitions. Animations played between moving from one view to another. We provide a set of basic transitions such as sliding right, left, etc. Additionally, you are able to create your own custom transitions.

Navigation

Our navigation is based on lightweight objects called Screen.

Screen is a meta data object that specifies which view controller or layout you want to show and optional data you want to pass to your view controller or layout. You can think of them as Android Intents with a much simpler API.

Screen screen = new MyScreen(new MyData("foo"));

router.goTo(screen);

The Screen class is extendable, and will provide you with the foundation for your navigation.

@ViewController(MyController.class)
public class MyScreen extends Screen {
}

We provide 5 primary navigation methods:

  1. goTo - Go to specified Screen and add it to the backstack.
  2. replaceWith - Go to specified Screen and replace the top of the backstack with it.
  3. replaceAllWith - Replace the backstack with a List of specified Screens, and navigate to the last Screen in the list.
  4. resetTo - Go to specified Screen and remove all Screens after it from the backstack. If the specified screen is not in the backstack, remove all and make this Screen the top of the backstack.
  5. goBack - Navigate to previous Screen.

Router does not render views. Router just emits an event that you can listen to in order to render the specified Screen. Within Scoop we provide the extensible view UIContainer that you can use to render view controllers and transitions.

ViewController

This class manages a portion of the user interface as well as the interactions between that interface and the underlying data. Similar to an activity or a fragment, ViewController requires you to specify the layout id and has lifecycle methods. However, a ViewController lifecycle only has two states: "attached" and "detached".

You can also use view binders like Butterknife. So you don't need to explicitly call ButterKnife.bind/unbind.

@ViewController(MyController.class)
public class MyScreen extends Screen {
}
public class MyController extends ViewController {

    @Override
    protected int layoutId() {
        return R.layout.my;
    }

    @Override
    public void onAttach() {
        super.onAttach();
    }

    @Override
    public void onDetach() {
        super.onDetach();

    }

    @OnClick(R.id.do_smth)
    public void doSomething() {

    }
}

The big difference from Android fragments and activities is that in Scoop we don't keep the ViewController in memory after it was detached. Whenever you move to a new Screen the ViewController detaches and is disposed together with the view.

Layout

A Layout annotation can be used similarly to ViewController annotation, and can accomplish the same goals. However, there is a higher degree of coupling between the controller and the view in this approach, so this implementation is generally not recommended.

@Layout(R.layout.my)
public class MyScreen extends Screen {
}
public class MyView extends FrameLayout {

    public LayoutView(Context context, AttributeSet attrs) {
      super(context, attrs);
    }

    @Override
    protected void onAttachedToWindow() {
      super.onAttachedToWindow();

      if (isInEditMode()) {
        return;
      }
    }

    @OnClick(R.id.do_smth)
    public void doSomething() {

    }
}

Scoops

Scoop's namesake is the word "scope". You can think of app scopes as ice cream scoops: going deeper in the navigation stack is an extra scoop on the top with another flavor.

Primary purpose of scoops is providing access to named services. When you create a scoop you have to specify its parent (except root) and services.

Scoop rootScoop = new Scoop.Builder("root")
        .service(MyService.SERVICE_NAME, myService)
        .build();

Scoop childScoop = new Scoop.Builder("child", rootScoop)
        .service(MyService.SERVICE_NAME, myService2)
        .service(OtherService.SERVICE_NAME, otherService)
        .build();

Internally, when trying to find a service within scoop, scoop will first try to find the service within itself. If the service is not within itself, scoop will iteratively go up in its scoop heirarchy to try to find the service.

MyService service = childScoop.findService(MyService.SERVICE_NAME);

When a scoop is no longer needed you can destroy it, which will remove references to all its services and invoke destroy for all children.

childScoop.destroy();

You are only required to create the root scoop manually. All child scoops will be created by Router whenever you advance in navigation. Created child scoops will be destroyed whenever you navigate to a previous item in the backstack.

To control child scoop creation you should extend ScreenScooper class. By default ScreenScooper only adds Screen to each child scoop.

Instead of adding individual services to your scoops, we recommend implementing dagger integration. In this case the only added service will be the dagger injector.

public class DaggerScreenScooper extends ScreenScooper {

    @Override
    protected Scoop addServices(Scoop.Builder scoopBuilder, Screen screen, Scoop parentScoop) {
        DaggerInjector parentDagger = DaggerInjector.fromScoop(parentScoop);

        DaggerModule daggerModule = screen.getClass().getAnnotation(DaggerModule.class);

        if(daggerModule == null) {
            return scoopBuilder.service(DaggerInjector.SERVICE_NAME, parentDagger).build();
        }

        DaggerInjector screenInjector;

        try {
            Object module = daggerModule.value().newInstance();
            screenInjector = parentDagger.extend(module);
        } catch (Throwable e) {
            throw new RuntimeException("Failed to instantiate module for screen: " + screen.getClass().getSimpleName(), e);
        }

        return scoopBuilder
                .service(DaggerInjector.SERVICE_NAME, screenInjector).build();
    }
}

Transitions

Transitions are animations played between moving from one ViewController to another. Within Scoop we provide the following built in transitions:

  1. Backward slide
  2. Forward slide
  3. Downward slide
  4. Upward slide
  5. Fade

To apply a transition you have to specify it for your ViewController by overriding enterTransition()/exitTransition() methods.

public class MyController extends ViewController {

    @Override
    protected ScreenTransition enterTransition() {
        return new ForwardSlideTransition();
    }

    @Override
    protected ScreenTransition exitTransition() {
        return new BackwardSlideTransition();
    }

    ...
}

If a transition is not specified, views will be swapped instantly.

You can also implement custom transitions by implementing the ScreenTransition interface.

public class AutoTransition implements ScreenTransition {

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void translate(final ViewGroup root, final View from, final View to, final TransitionListener transitionListener) {

        Scene toScene = new Scene(root, to);

        android.transition.AutoTransition transition = new android.transition.AutoTransition();

        transition.addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionEnd(Transition transition) {
                transitionListener.onTransitionCompleted();
            }

            @Override
            public void onTransitionCancel(Transition transition) {
                transitionListener.onTransitionCompleted();
            }
            ...
        });

        TransitionManager.go(toScene, transition);
    }
}

Samples

  • Basics - App that showcases the basics of Scoop (navigation, parameter passing, dependency injection)
  • Micro Lyft - advanced sample based on Lyft's public api to showcase real world usage [COMING SOON].

Questions

For questions please use GitHub issues. Mark the issue with the "question" label.

Download

compile 'com.lyft:scoop:0.4.2'

Snapshots of development version are available in Sonatype's snapshots repository.

License

Copyright (C) 2015 Lyft, Inc.

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.

Special Thanks

scoop's People

Contributors

bencodes avatar eveliotc avatar itspbj avatar jrodbx avatar kathyma avatar kxfang avatar lexer avatar ryan-lane avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scoop's Issues

How would you make a sub view/screen router?

First off thank you guys for building out this framework. From my short experience with it, it's already way more simple than using Fragments/Activities. One thing I've not been able to quite figure out yet is if you can somehow nest screens and give them a different UiContainer, then lose that container when you go to another main screen i.e. scope the sub containers? So instead of switching to a whole new view each time you call router.goTo() you can keep some common elements?

So I have a login form in my app with multiple sub views, each share a common background that should stay fixed, but I'd love to be able to call goTo( new NextScreenName()). Originally I was solving this by having a common Activity and each form view would be it's own fragment. Is this possible with the current framework? Any advice on how to solve this would be greatly appreciated.

UiContainer should avoid queuing route changes

Since now we are blocking UI during UIContainer transitions. Probably there is no reason to support queuing of the RouteChanges. So last RouteChange should always win and other routechanges should not be executed.

Alternatively, we can avoid destroying scoops when we pop them from the backstack.

Is Scoop still maintained ?

I just discovered this awesome project and would like to know the project's status. is it abandoned or still under maintenance?

Cordially ;)

Pros/Cons against Mortar/Flow

  1. Many are probably wondering what are the pros/cons compared to Mortar/Flow?
  2. Does Lyft actually use this library internally?

./gradlew installDebug not working with Java 1.8

In a fresh clone with HEAD = e0003efd2cf4da65a4e953393d0484d58c386a6e

› java -version
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
› ./gradlew installDebug
:scoop:compileJava UP-TO-DATE
:scoop:processResources UP-TO-DATE
:scoop:classes UP-TO-DATE
:scoop:jar UP-TO-DATE
:scoop-basics:preBuild UP-TO-DATE
:scoop-basics:preDebugBuild UP-TO-DATE
:scoop-basics:checkDebugManifest
:scoop-basics:preReleaseBuild UP-TO-DATE
:scoop-basics:prepareComAndroidSupportAppcompatV72221Library UP-TO-DATE
:scoop-basics:prepareComAndroidSupportDesign2221Library UP-TO-DATE
:scoop-basics:prepareComAndroidSupportMultidex100Library UP-TO-DATE
:scoop-basics:prepareComAndroidSupportSupportV42221Library UP-TO-DATE
:scoop-basics:prepareComGoogleAndroidGmsPlayServicesBase810Library UP-TO-DATE
:scoop-basics:prepareComGoogleAndroidGmsPlayServicesBasement810Library UP-TO-DATE
:scoop-basics:prepareComGoogleAndroidGmsPlayServicesLocation810Library UP-TO-DATE
:scoop-basics:prepareComGoogleAndroidGmsPlayServicesMaps810Library UP-TO-DATE
:scoop-basics:prepareIoReactivexRxandroid101Library UP-TO-DATE
:scoop-basics:prepareDebugDependencies
:scoop-basics:compileDebugAidl UP-TO-DATE
:scoop-basics:compileDebugRenderscript UP-TO-DATE
:scoop-basics:generateDebugBuildConfig UP-TO-DATE
:scoop-basics:generateDebugAssets UP-TO-DATE
:scoop-basics:mergeDebugAssets UP-TO-DATE
:scoop-basics:generateDebugResValues UP-TO-DATE
:scoop-basics:generateDebugResources UP-TO-DATE
:scoop-basics:mergeDebugResources UP-TO-DATE
:scoop-basics:processDebugManifest UP-TO-DATE
:scoop-basics:processDebugResources UP-TO-DATE
:scoop-basics:generateDebugSources UP-TO-DATE
:scoop-basics:processDebugJavaRes UP-TO-DATE
:scoop-basics:compileDebugJavaWithJavac UP-TO-DATE
:scoop-basics:compileDebugNdk UP-TO-DATE
:scoop-basics:compileDebugSources UP-TO-DATE
:scoop-basics:preDexDebug
Unknown source file : UNEXPECTED TOP-LEVEL EXCEPTION:
Unknown source file : java.lang.RuntimeException: Exception parsing classes
Unknown source file :   at com.android.dx.command.dexer.Main.processClass(Main.java:752)
Unknown source file :   at com.android.dx.command.dexer.Main.processFileBytes(Main.java:718)
Unknown source file :   at com.android.dx.command.dexer.Main.access$1200(Main.java:85)
Unknown source file :   at com.android.dx.command.dexer.Main$FileBytesConsumer.processFileBytes(Main.java:1645)
Unknown source file :   at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)
Unknown source file :   at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
Unknown source file :   at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
Unknown source file :   at com.android.dx.command.dexer.Main.processOne(Main.java:672)
Unknown source file :   at com.android.dx.command.dexer.Main.processAllFiles(Main.java:574)
Unknown source file :   at com.android.dx.command.dexer.Main.runMultiDex(Main.java:366)
Unknown source file :   at com.android.dx.command.dexer.Main.run(Main.java:275)
Unknown source file :   at com.android.dx.command.dexer.Main.main(Main.java:245)
Unknown source file :   at com.android.dx.command.Main.main(Main.java:106)
Unknown source file : Caused by: com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000)
Unknown source file :   at com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java:472)
Unknown source file :   at com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:406)
Unknown source file :   at com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary(DirectClassFile.java:388)
Unknown source file :   at com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.java:251)
Unknown source file :   at com.android.dx.command.dexer.Main.parseClass(Main.java:764)
Unknown source file :   at com.android.dx.command.dexer.Main.access$1500(Main.java:85)
Unknown source file :   at com.android.dx.command.dexer.Main$ClassParserTask.call(Main.java:1684)
Unknown source file :   at com.android.dx.command.dexer.Main.processClass(Main.java:749)
Unknown source file :   ... 12 more
Unknown source file : 1 error; aborting

:scoop-basics:preDexDebug FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':scoop-basics:preDexDebug'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 15.768 secs

Multi-Window Support

Does Scoop offer an elegant solution for applications that support multi-window? Maybe an extension for onMultiWindowModeChanged and onConfigurationChanged ?

Status of scoop?

Is scoop still being maintained?

I really enjoy using this library as it makes prototyping out an app very easy.
What was the reason for removing the exit & enter transition annotations from the library? I had thought that this was a major selling point of this library as you gain an animation simply by adding an annotation.
Can the layout annotation be used instead of having a layout method in the controller? I would be willing to help with issues in order to help keep this library updated for the community.

Proper way to expose a service to any view in a Scoop app

Hello,

I'm really liking your framework here.

I've successfully implemented a service at "root" scope level, and I'd like your comments or "best practice" advice for implementing such such a service.

Below are my notes on implementing a service accessible from any ViewController via the root scoop. I have saved my questions for the end.

Following these notes I was a able to start a single instance of Duktape at application load, and provide it as a service to all of my views, I'm just not confident that I did it properly.

Create the Service

/scoop/MyService.java

package com.xxx.scoop;

import android.view.View;
import com.lyft.scoop.Scoop;

public class MyService {

    public static final String SERVICE_NAME = "isthisevenusedbytheprogrammer";

    private String myString;

    public MyService() {
        myString = "This is the default text.";
    }

    public void setMyString(String text) {
        myString = text;
    }

    public String getMyString() {
        return myString;
    }


    public static MyService fromScoop(Scoop scoop) {
        return scoop.findService(SERVICE_NAME);
    }

    public static MyService fromView(View view) {
        return Scoop.fromView(view).findService(SERVICE_NAME);
    }
}

Add the service to root scoop:

/MainActivity.java

package com.xxx;
//...
import com.xxx.scoop.MyService;

//...

            private Scoop getRootScoop() {
//...

            DaggerInjector activityInjector = new DaggerInjector(activityGraph);

            MyService mysrv = new MyService();

            rootScoop = new Scoop.Builder("root")
            .service(DaggerInjector.SERVICE_NAME, activityInjector)
            .service(MyService.SERVICE_NAME, mysrv)
            .build();

        Timber.d("rootscoop built. name: " + rootScoop.getName());

        MyService testMyService = rootScoop.findService(MyService.SERVICE_NAME);
        Timber.d("testMyService.getMyString():" + testMyService.getMyString());
        Timber.d("testMyService.setMyString('test'):" + testMyService.setMyString("test"));
        Timber.d("testMyService.getMyString():" + testMyService.getMyString());
            }
        return rootScoop;
    }

Add the service to a ViewController and use it:

/ui/MyUi/MyTestController.java

package com.xxx.ui.myui;
//...
import com.xxx.scoop.MyService;

//...

@ControllerModule(MyTestController.Module.class)
@EnterTransition(DownwardSlideTransition.class)
@ExitTransition(UpwardSlideTransition.class)
public class MyTestController extends ViewController {
    private MyService myService;

//...

    @Override
    public void attach(View view) {
        super.attach(view);
        this.view = view;
        String args = Screen.fromController(this).args();

        //this doesn't feel right... but it works.
        Timber.d("getScoop name: " + this.getScoop().getName()); //MyTestController
        Scoop parentScoop = this.getScoop().getParent();
        Timber.d("parentScoop: " + parentScoop.getName()); //DemosController
        this.myService = parentScoop.findService(MyService.SERVICE_NAME);

//...
@OnClick(R.id.whateverButton)
    public void onClickWhateverButton() {
        whateverTextView.setText(myService.getMyString());
}

My questions are:

  1. Is this the proper workflow to achieve this goal?
  2. I understand bundled persistence isn't available yet so if android kills my app in background, next time I open the app the services will be re-initialized. Is there a way to prevent this for root scoped services? Are there any other cases where the root scoop might forget my service?
  3. In the README.md you state:

Instead of adding individual services to your scoops, we recommend implementing dagger integration. In this case the only added service will be the dagger injector.

Is that what I've achieved here, or is there another way to go about it?

Thank you for all your work on this. Scoop is really excellent as I start to understand it better.

Back button handler needs debounce logic

Steps to recreate with scoop-basics:

  1. Open scoop-basics app on device
  2. Click "CUSTOM TRANSITION" button
  3. Click "Next" and "Back" buttons ("@+id/next_button" and "@+id/back_button" respectively) a bunch of times, until the MainActivity shows again.
  4. Click "WIZARD SAMPLE"

Result: App crashes. Below is logcat.

MainUiContainer  D  Scoop changed:AutoTransitionEndController
  5489        MainUiContainer  D  Scoop changed:AutoTransitionEndController
  5489        MainUiContainer  D  Scoop changed:AutoTransitionEndController
  5489        MainUiContainer  D  Scoop changed:AutoTransitionStartController
  5489        MainUiContainer  D  Scoop changed:DemosController
  5489        MainUiContainer  D  Scoop changed:AutoTransitionEndController
  5489        MainUiContainer  D  Scoop changed:DemosController
  5489         AndroidRuntime  D  Shutting down VM
  5489               dalvikvm  W  threadid=1: thread exiting with uncaught exception (group=0x41708c80)
  5489         AndroidRuntime  E  FATAL EXCEPTION: main
  5489         AndroidRuntime  E  Process: com.scooptest PID: 5489
  5489         AndroidRuntime  E  java.lang.NullPointerException
  5489         AndroidRuntime  E  at com.scooptest.scoop.DaggerInjector.fromScoop(DaggerInjector.java:30)
  5489         AndroidRuntime  E  at com.scooptest.scoop.DaggerScreenScooper.addServices(DaggerScreenScooper.java:11)
  5489         AndroidRuntime  E  at com.lyft.scoop.ScreenScooper.createScreenScoop(ScreenScooper.java:10)
  5489         AndroidRuntime  E  at com.lyft.scoop.Router.goTo(Router.java:56)
  5489         AndroidRuntime  E  at com.scooptest.ui.DemosController.goToWizardSample(DemosController.java:82)
  5489         AndroidRuntime  E  at com.scooptest.ui.DemosController$$ViewBinder$5.doClick(DemosController$$ViewBinder.java:53)
  5489         AndroidRuntime  E  at butterknife.internal.DebouncingOnClickListener.onClick(DebouncingOnClickListener.java:22)
  5489         AndroidRuntime  E  at android.view.View.performClick(View.java:4768)
  5489         AndroidRuntime  E  at android.view.View$PerformClick.run(View.java:19073)
  5489         AndroidRuntime  E  at android.os.Handler.handleCallback(Handler.java:755)
  5489         AndroidRuntime  E  at android.os.Handler.dispatchMessage(Handler.java:95)
  5489         AndroidRuntime  E  at android.os.Looper.loop(Looper.java:145)
  5489         AndroidRuntime  E  at android.app.ActivityThread.main(ActivityThread.java:5266)
  5489         AndroidRuntime  E  at java.lang.reflect.Method.invokeNative(Native Method)
  5489         AndroidRuntime  E  at java.lang.reflect.Method.invoke(Method.java:515)
  5489         AndroidRuntime  E  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:826)
  5489         AndroidRuntime  E  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:642)
  5489         AndroidRuntime  E  at dalvik.system.NativeStart.main(Native Method)
  5489         AndroidRuntime  I  To Report FATAL to activityManagerService
 16024        ActivityManager  I  handleApplicationCrash
 16024        ActivityManager  W  Force finishing activity com.scooptest/.MainActivity
  5489         AndroidRuntime  I  Finished reporting FATAL to activityManagerService
  5489                Process  I  Sending signal. PID: 5489 SIG: 9

Block UI during transitions

Common problem is that user can click twice on buttons while view are transitioning. We should prevent them

Remove parent based navigation

Parent based navigation proved to be very fragile when one screen is used as a child by two different screens.

We should always relay on going back, except deep link scenario when back stack could be constructed.

Transitions should not be responsible for adding or removing views

Sounds like a job for UIContainer.

SlideDownTransition:

        Animator animator = createAnimator(from);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                ((ViewGroup) from.getParent()).removeView(from);
                transitionListener.onTransitionCompleted();
            }
        });
        animator.start();

ObjectAnimatorTransition:

   @Override
    public void transition(final ViewGroup root, final View from, final View to, final TransitionListener transitionListener) {
        root.addView(to);

Cannot push object of the same Screen subclass on stack with neither goTo nor replaceWith

Hi,

in our project we are making settings to the view inside onAttach() method. We would like to be able to open SomeViewScreen() from the screen of the same class, i.e. SomeViewScreen(). Currently goTo() method of Router is preventing this from happening with this check:

    if (Screen.equals(backStack.peek(), nextScreen)) {
        return;
    }

equals method is overloaded in Screen in such a way that it checks whether objects are of the same class.

Would it be possible to add some "force: Boolean" parameter to goTo() and replaceWith() functions so that they would allow pushing object of same Screen class to the backstack?

Background and foreground behaviour

Our application has some triggers when it goes background and foreground that need to be reflected on the ViewController. How would you recommend passing that information to it, via an observable/bus that's passed on the component and the VC listens for until detached?

I can't label this as a question, only owners can.

MVP Examples?

I recon this lib has huge potential, but i'm a bit unsure how to use this with mvp on a lower level. Any chance a template could be provided?

Persisting/restoring state

Is there a recommended way for persisting and restoring a screen's state in the event that the app is backgrounded, killed by the OS, then restored? For example, something that is the equivalent of onCreate(Bundle args) / onSaveInstanceState for Activities.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.