Coder Social home page Coder Social logo

kaushikgopal / movies-usf-android Goto Github PK

View Code? Open in Web Editor NEW
228.0 12.0 44.0 34.28 MB

Movie searching using a Unidirectional State Flow pattern for Android

License: Apache License 2.0

Kotlin 100.00%
kotlin android unidirectional-data-flow mvi mvvm redux

movies-usf-android's Introduction

Movie search using a unidirectional state flow pattern

This is an attempt at coming up with a unidirectional state flow pattern that uses the concepts of patterns like Redux, Cycle.js, MVI etc.

Many of my contemporaries have already done amazing work in this area and I've drawn a lot of lessons and learnings from their work already:

I wanted to achieve the benefits of this pattern without introducing any new libraries or a new framework. How would one familiar with an MVVM model today leverage the principles/benefits of a unidirectional state/data flow? I hope to demo those concepts with this app.

usf_animation.gif "picture showing the USF animation"

The app is a simple movie search app. Clicking the movie result populates a history list. While this is not an extremely complex app, it isn't a silly Hello World one either, so the hope is that it'll cover regular use cases for a basic application.

I've also started meaninful test cases in the repo.

Setting up your OMDB API KEY

We use the wonderful OMDB api to fetch movie information.

There are quotas on this api, so please don't use mine :)

  1. Get an api key for OMDB here
  2. Add it to you local.properties file (which shouldn't be checked in to a VCS) like so:
# local.properties
OMDB_API_KEY="<API_KEY_GOES_HERE>"

For great movie recommendations, ping me @kau.sh (seriously, I watch a lot of movies).

I gave a talk at MBLT}Dev 2018 on how I went about building this app. Slides can be found here.

Getting Started

This project now uses ksp to reduce the boilerplate in wiring up a new feature. This PR has the details for how this change was made.

All that's needed is writing the implementation of your ViewModel so MyFeatureViewModelImpl: UsfViewModelImpl<E, R, VS, VE> and adding the @UsfViewModel annotation. Your ViewModel boilerplate code will be auto-generated.

Take a look at MSMovieViewModelImpl for the View Model logic and MSMovieActivity to see how the viewModel is invoked.

iOS app

I gave another talk at Mobilization IX showing how we can use the same concepts on iOS too and wrote my first iOS app to demonstrate these concepts - You can check that out here.

movies-usf-android's People

Contributors

cubanazcuy avatar kaushikgopal avatar varunbarad 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

movies-usf-android's Issues

[Question] Navigation change and life cycle edge case

I'm running into an edge case and wanted to pick your brain on this, here is the use case

UI Event triggers a slow network op which starts with a loading state
UI is updated with a progress indicator
User backgrounds the app
Network op finishes while the app is in background (assume no process kill by android)
UI is subscribed to changes until onDestroy and gets notified of a navigation effect
Navigation Effect tries to perform fragment transaction while the app is paused
Things go haywire from here.

One approach to solve this was by having UI subscribe only until onPause and resubscribe from onResume. However, with this the effect notification is lost (no active subscriptions from paused state) when slow network op finishes while the app is backgrounded and re-subscription onResume fails as effect has no replay behavior from the view model.

This is kind of forcing navigation changes into view state. How do you go about this?

spaces in search not working

Problem:
spaces in search not working.

Example:
When I search Godfather , it works. (but it shows Malayalam movie)
When I search "The Godfather" , it works
When I search The Godfather , it shows Invalid API key!

Suggestion:
Surround the entire search string with " " before making request.

    return movieApi.searchMovie("\""+movieName+"\"")

instead of
return movieApi.searchMovie(movieName)
at
https://github.com/kaushikgopal/movies-usf-android/blob/master/app/src/main/java/co/kaush/msusf/movies/MSMovieRepository.kt#L13

Question: How would you partially update UI?

I see that whenever there is a change in state you are setting all Views, Adapter anew. In my MVVM code I have LiveData object for small state chunks and I update them separate from each other. How would you achieve the same in MVI?

feat: add a single ui instrumentation test

The view state tests are the more interesting ones imho, but for this to be fully "complete", we'd definitely need UI instrumentation tests to make sure:

  1. the output "view state" is being bound properly to our Android Views
  2. the android views are generating the correct input "events"

A single espresso tests should suffice for that.

Build error

When I try to build this on Android Studio 3.3.2, I get an error:

> Task :app:kaptReleaseKotlin FAILED
e: /Users/barry.sia/src/open/movies-usf/app/build/tmp/kapt3/stubs/release/co/kaush/msusf/MSApp.java:6: error: incompatible types: NonExistentClass cannot be converted to Annotation
@error.NonExistentClass()
      ^
    e: /Users/barry.sia/src/open/movies-usf/app/build/tmp/kapt3/stubs/release/co/kaush/msusf/movies/MSMovieRepository.java:6: 
error: incompatible types: NonExistentClass cannot be converted to Annotation
@error.NonExistentClass()
      ^

how to

why not using the scan operator instead of
private val _viewState = MutableStateFlow(initialState)
override val viewState = _viewState.asStateFlow()

Question: USF & navigation

@kaushikgopal - Thanks for the demo app. Quick question - according to you, what would be the best practice if we need to manage screen navigations with USF? For eg. in this demo app (movies-usf) if there is a button (say, "Details") that launches a new activity which shows the movie details, how will you integrate that button click event into this entire pattern? Thanks again!

[Enhancement] In-place member functions on Result to State and Effect

Just a thought for folks using this pattern.

Instead of having this nested when statements for Result to State and Result to Effect conversion, base Result could have functions to convert it to State (given current state) and to Effect.

With this in place, VM can just invoke a generic result.toState(currentState) and result.toEffect(). Any new Event and Result can be coded in place without having the lengthy conversion function. VM will just need additional logic to convert event to results.

feat: add an example for necessary side effects

In the event flow process, it's sometimes required to execute side effects as a result of some action.

In my real world usage at Instacart, I had the following requirement:

  • I have a polling endpoint that checks to see if our "systems" are online
  • if system is not online, show "systems offline"
  • if systems are online, show "systems online"
  • but also pull the latest order information (this is basically a new event that needs to be launched, but without an explicit user input!

so we'd need a way to send back new "events" into the events-> results function. Basically we need a side-effect introduced without necessarily making the function "impure"

I'll have to come up with an example that works in this movie search case. Probably have a polling endpoint that shows a random recommendation for a movie, every 1 minute. If recommendations are available, allow those to be clicked and added to the history list as well.

Partial UI update with a wrapper

Hello kaushik, I have a question regarding the unidirectional state flow architecture. The implementation that you have done with rxjava in movies-usf is really good
, really appreciated that. One of my confusion is the way we pass the view state from viewmodel. Since, you are passing the entire state from the ViewModel, if the state is complex, then even a small change like changing the title can render the entire view. I also followed #14 where you mentioned of using diffing tool. I was wandering if we could use some wrapper around each attributes in the viewstate like NullBox (for nullables in rxjava) to identify if the state has changed or not, may be a wrapper with a boolean? This way we can check in the view weather the attributes in the state has changed or not and render only the changed ones.

MS prefix

Why do you use MS prefix everywhere?
Is this repo sponsored by Microsoft? ;-)

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.