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

Related tags

Demo u2020
Overview

U+2020

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

Watch the corresponding talk or view the slides.

The ObjectGraph is created in the U2020App's onCreate method. The Modules class provides a single method, list, which returns the list of module instances to use.

In order to add functionality in the 'debug' version of the app, this class is only present in the release/ and debug/ build type folders. The 'release' version only includes the U2020Module while the 'debug' version includes both U2020Module and DebugU2020Module, the latter of which is only present in the debug/ build type folder and is an override module.

Through the use of Dagger overrides, the 'debug' version of the app adds a slew of debugging features to the app which are presented in the Debug Drawer™. The drawer is opened by a bezel swipe from the right of the screen. From here you can change and view all of the developer options of the application.

The drawer is provided by the simple interface ViewContainer. This is an indirection that the single activity uses to fetch its container into which it can place its content. The default implementation returns the Android-provided content view. The 'debug' version overrides this with DebugViewContainer which is responsible for creating the drawer, adding it to the activity, and returning its content view group. It also injects all of the developer objects and binds them to controls in the drawer.

The most notable feature the 'debug' version exposes is the concept of endpoints. Using the spinner at the top of the drawer, you can change the endpoint to which the app communicates. We also expose a false endpoint named "Mock Mode" which simulates an in-memory server inside the app. This "Mock Mode" eases manual testing and also provides a static set of data to write instrumentation tests against.

"Mock Mode" can be queried when modules are configuring their dependencies which is what allows simulating the remote server in-memory.

@Singleton class MockFoo() {
  @Inject MockFoo() {}
  // ...
}
@Provides @Singleton Foo provideFoo(@IsMockMode boolean isMockMode, MockFoo mockFoo) {
  return isMockMode ? return mockFoo : new RealFoo();
}

See DebugDataModule and DebugApiModule to see this in action in the real app.

The mock implementations of these types are some of those injected into the DebugViewContainer for binding in the drawer. This allows us to do things like control their fake network behavior and alter their behavior.

In order to keep the shared state which represents the server-side data we use a ServerDatabase singleton. At present this is only done with a combination of in-memory collections and images in the debug/assets/. In a more complex app you could even use a full database. This class is injected into each mock service which uses its methods to query and mutate state (e.g., MockGalleryService).

Debug drawer

Libraries

To Do

  • Something with animations to showcase animation control.
  • Network errors probably crash the app.
  • Add another part of the app other than 'trending' so we can demo child graphs.

License

Copyright 2014 Jake Wharton

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.
Comments
  • Open drawer by clicking toolbar navigation icon

    Open drawer by clicking toolbar navigation icon

    From TrendingView.java:

      toolbarView.setNavigationOnClickListener(new OnClickListener() {
          @Override public void onClick(View v) {
            // TODO bind to drawer with... injection?
          }
        });
    

    How are you guys planning to implement this binding with MainActivity.drawerLayout?

    Typically I'm doing this the following way: ActivityConnector binds to Activity livecycle with attach/detach (e.g. called from onStart/onStop), holds reference to some object in Activity. Simply it looks like this:

    public class ActivityConnector<T> {
      private WeakReference<T> ref;
    
      public void attach(T obj) {
        ref = new WeakReference<T>(obj);
      }
    
      public void detach() {
        ref = null;
      }
    
      public T get() {
        return ref == null ? null : ref.get();
      }
    }
    

    More robust implementation can be found here.

    This approach can be used to bind drawerLayout:

    public final class MainActivity extends Activity {
      @Inject ActivityConnector<DrawerLayout> drawerConnector;
    
      @InjectView(R.id.main_drawer_layout) DrawerLayout drawerLayout;
    
      @Override protected void onStart() {
        super.onStart();
        drawerConnector.attach(drawerLayout);
      }
    
      @Override protected void onStop() {
        super.onStop();
        drawerConnector.detach();
      }
    }
    

    in TrendingView.java:

    @Inject ActivityConnector<DrawerLayout> drawerConnector;
    @InjectView(R.id.trending_toolbar) Toolbar toolbarView;
    
    @Override protected void onFinishInflate() {
       super.onFinishInflate();
       ButterKnife.inject(this);
    
       toolbarView.setNavigationIcon(R.drawable.menu_icon);
       toolbarView.setNavigationOnClickListener(new OnClickListener() {
         @Override public void onClick(View v) {
           DrawerLayout drawer = drawerConnector.get();
           if (drawer != null) {
             drawerLayout.openDrawer(Gravity.START);
           }
         }
       });
    }
    

    What do you think about that?

    opened by kboyarshinov 10
  • Debug Drawer as gradle dependency

    Debug Drawer as gradle dependency

    Hi, I was wondering if it is possible to abstract out the Debug Drawer into a separate library that can be pulled into any app as a gradle dependency. In your sample, your are specifically using Dagger1, and there is a lot of code to look at just to understand how the debug drawer is implemented. I think it would be great if folks can use your implementation with any project (and Dagger2) without understanding all the separate classes that comprise the drawer.

    Thanks, Igor

    opened by IgorGanapolsky 8
  • Can't run project ?

    Can't run project ?

    I got a error when run project .

    Could you please help me solve this problem ? Tks

    Error:(112, 0) Could not find method implementation() for arguments [com.android.support:support-v4:26.0.0-beta2] on object of type org.gradle.api.internal.artifacts.dsl.depend screen shot 2017-07-23 at 2 54 46 pm encies.DefaultDependencyHandler.

    Please install the Android Support Repository from the Android SDK Manager. Open Android SDK Manager

    opened by chihung93 7
  • Switching back and forth between 2 Custom Views

    Switching back and forth between 2 Custom Views

    Is there any possibility of adding to this app an example of how you switch back and forth between 2 custom views?

    I've heard someone mention that Square doesn't use Fragments in their apps -- it would be nice to see an example in this app of how to handle multiple screens without Fragments.

    opened by raskasa 7
  • Showcase Mortar 0.7

    Showcase Mortar 0.7

    I forked your library to showcase Mortar. I created this PR just in case you are interested in showcasing Mortar as well. Note that adding Flow would be easy too and can be done later when more than one screen would be used.

    opened by niqo01 7
  • Fix possibly outdated adapter position

    Fix possibly outdated adapter position

    https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#onBindViewHolder(VH,%20int)

    The setHasStableIds(true); is unrelated but nice to have.

    opened by NightlyNexus 6
  • Provide examples for unit tests

    Provide examples for unit tests

    I struggle to find a good reference for how Dagger is used to inject dependencies in unit tests, especially when fragments and activities are involved.

    I believe we're at our 3rd round of rewriting this in our app (we finally moved away completely from the clunky and verbose approach where you inject into the test class using a test module), and would be interested to see what Square suggests here.

    FWIW: We went back to cutting out Dagger from unit tests and having @VisibleForTesting constructors on fragments, and then pass in mocks manually in unit tests. In the default ctor, the one Android would invoke, we then inject the object graph and have package visible fields with @Inject annotations. That introduces a weird split though between how dependencies are resolved (manually in tests, via Dagger in prod.)

    opened by mttkay 6
  • `no-skin` is removed.

    `no-skin` is removed.

    It removes device configuration when emulator initializes. It causes the device to be 320x480 with 240 or 320 display density. Which makes effective screen width about 160dp. Emulator becomes almost useless. More info here. https://github.com/travis-ci/docs-travis-ci-com/pull/466

    opened by tasomaniac 5
  • Unable to build productionRelease

    Unable to build productionRelease

    It looks like lint isn't happy with passing a raw number to res.getColor/getDimension

    › ./gradlew assembleProductionRelease
    :preBuild UP-TO-DATE
    :preProductionReleaseBuild UP-TO-DATE
    :checkProductionReleaseManifest
    :preInternalDebugBuild UP-TO-DATE
    :preInternalReleaseBuild UP-TO-DATE
    :preProductionDebugBuild UP-TO-DATE
    :prepareComAndroidSupportAppcompatV72301Library UP-TO-DATE
    :prepareComAndroidSupportDesign2301Library UP-TO-DATE
    :prepareComAndroidSupportRecyclerviewV72301Library UP-TO-DATE
    :prepareComAndroidSupportSupportV42301Library UP-TO-DATE
    :prepareComF2prateekRxPreferencesRxPreferences100Library UP-TO-DATE
    :prepareComJakewhartonRxbindingRxbinding020Library UP-TO-DATE
    :prepareComJakewhartonThreetenabpThreetenabp102Library UP-TO-DATE
    :prepareComJakewhartonTimberTimber401Library UP-TO-DATE
    :prepareComSquareupLeakcanaryLeakcanaryAndroidNoOp131Library UP-TO-DATE
    :prepareIoReactivexRxandroid101Library UP-TO-DATE
    :prepareProductionReleaseDependencies
    :compileProductionReleaseAidl UP-TO-DATE
    :compileProductionReleaseRenderscript UP-TO-DATE
    :generateProductionReleaseBuildConfig
    :generateProductionReleaseAssets UP-TO-DATE
    :mergeProductionReleaseAssets UP-TO-DATE
    :generateProductionReleaseResValues UP-TO-DATE
    :generateProductionReleaseResources UP-TO-DATE
    :mergeProductionReleaseResources UP-TO-DATE
    :processProductionReleaseManifest UP-TO-DATE
    :processProductionReleaseResources UP-TO-DATE
    :generateProductionReleaseSources
    :processProductionReleaseJavaRes UP-TO-DATE
    :compileProductionReleaseJavaWithJavac
    Note: Some input files use or override a deprecated API.
    Note: Recompile with -Xlint:deprecation for details.
    :compileRetrolambdaProductionRelease
    :compileProductionReleaseNdk UP-TO-DATE
    :compileProductionReleaseSources
    :lintVitalProductionRelease
    /Users/mattm/Code/u2020/build/generated/source/apt/production/release/com/jakewharton/u2020/ui/MainActivity$$ViewBinder.java:19: Error: Expected resource of type color [ResourceType]
        target.statusBarColor = res.getColor(2131361859);
                                             ~~~~~~~~~~
    /Users/mattm/Code/u2020/build/generated/source/apt/production/release/com/jakewharton/u2020/ui/trending/TrendingView$$ViewBinder.java:41: Error: Expected resource of type dimen [ResourceType]
        target.dividerPaddingStart = res.getDimension(2131099747);
                                                      ~~~~~~~~~~
    
       Explanation for issues of type "ResourceType":
       Ensures that resource id's passed to APIs are of the right type; for
       example, calling Resources.getColor(R.string.name) is wrong.
    
    2 errors, 0 warnings
    :lintVitalProductionRelease FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':lintVitalProductionRelease'.
    > Lint found fatal errors while assembling a release target.
    
      To proceed, either fix the issues identified by lint, or modify your build script as follows:
      ...
      android {
          lintOptions {
              checkReleaseBuilds false
              // Or, if you prefer, you can continue to check for errors in release builds,
              // but continue the build even when errors are found:
              abortOnError false
          }
      }
      ...
    
    * 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.452 secs
    
    opened by matthewmichihara 5
  • Use ShareCompat to have the perfect sharing experience.

    Use ShareCompat to have the perfect sharing experience.

    ShareCompat is used to always have good sharing Intent with necessary flags attached to it.

    Here is the screenshots from old and new versions. In the old version you can see that Google Inbox app seems to be inside the screen of U+202 Internal.

    | Old | New | | --- | --- | | screenshot_2015-08-14-09-51-39 | screenshot_2015-08-14-09-50-30 |

    opened by tasomaniac 5
  • Debug drawer widgets should be updated onResume to keep in sync with SharedPreferences

    Debug drawer widgets should be updated onResume to keep in sync with SharedPreferences

    If you go to a second activity (ensuring that the previous activity is not destroyed), and change a setting in the debug drawer (such as latency), then go back to the first activity, the UI widgets in the debug drawer get out of sync with the preferences that back them since the widgets are only initialized in onCreate().

    I've worked around this in my application by removing the @Singleton annotations from the DebugAppContainer class and the module that provides it, and adding a second method bind() so the interface for AppContainer looks like this:

    ViewGroup get(Activity activity);
    void bind(Activity activity);
    

    Then I call bind() in onResume of my activity.

    This adds a fair amount of complexity but is kind of necessary.

    Please let me know if you're interested in a PR.

    opened by jacobtabak 5
  • Changing network endpoint doesn't work.

    Changing network endpoint doesn't work.

    In DebugView, ProcessPhoenix.triggerRebirth seems to kill the process too fast. On my device, the SharedPreference won't get set, so I can't change the endpoint from the DebugView.

    opened by NightlyNexus 3
  • Build error

    Build error

    I got an error when run app! It showed could not find symbol. symbol: variable nullL, in u2020-master/app/src/internalDebug/java/com/jakewharton/u2020/ui/debug/DebugView.java 9333a4c1-588d-42c1-a9f8-0bf4cd17666a

    opened by duckmoon 6
  • Show real screen size / size in DP where possible

    Show real screen size / size in DP where possible

    The debug drawer currently shows the available screen size, rather than the full screen size — it's useful to be able to see both. Also, show these sizes in dp as well as px, as these are the units we work in more often.

    u2020_screenshot

    opened by jonathan-caryl 1
  • Setting invalid custom endpoint breaks the app

    Setting invalid custom endpoint breaks the app

    Setting endpoint to custom with value that is not parseable (e.g "saffga") will make the app crash. It will crash on every consequent startup until the app data is cleared. The reason is that the user inputed string is saved to @ApiEndpoint String preference, which is later read by provideHttpUrl method in DebugApiModule. The method tries to parse the String into HttpUrl but invalid Strings are parsed to null value. When null HttpUrl is provided as a base url when building retrofit instance, the app will crash.

    Fix: Make sure user provided custom URL is parseable. Additional validation is required when custom endpoint is set by the user(within DebugView, check if it is parseable by HttpUrl.parse() method). I've made pull request for this but I guess I'm not allowed to push anything to this repo.

    opened by bradroid 1
A simple app demonstrates using Jetpack compose with other Jetpack libraries.

Android Pokemon Compose This repository is a simple app that make request to https://pokeapi.co and display them in the paginated lists. It demonstrat

BenBoonya 56 May 21, 2022
[] Port of Jake Wharton's U2020 sample app with use of MVP and Dagger 2

U+2020-mvp [DEPRECATED] We recomend to try Moxy framework instead of our solution. Port of Jake Wharton's U2020 sample app with use of MVP pattern and

Live Typing 315 Nov 14, 2022
🔥 Android MVP with Volley usage simple registration App 🔥

?? Android MVP with Volley usage simple registration App ?? This is a MVP architecture app that uses volley .Project is made using Android Studio. Vol

ABHISHEK KUMAR PATHAK 3 Aug 7, 2022
! Usage examples for Android Maven Plugin

Android Maven Plugin - Sample Projects WARNING This project is deprecated. All sample projects for the Android Maven Plugin as of version 4.0.0-rc.1 a

Jayway 190 Nov 28, 2022
Movie discovery app showcasing MVP, RxJava, Dagger 2 and Clean Architecture

MovieGuide ?? Refactoring in progress ??‍♀️ ⛏ ?? ??️ ?? ?? ?? Comments and new issues are welcome. ?? Currently not accepting external PRs that touch

Arun Sasidharan 2.6k Dec 25, 2022
Beetlebug is an open source insecure Android application with CTF challenges built for Android Penetration Testers and Bug Bounty hunters.

Beetlebug Beetlebug is a beginner-friendly Capture the Flag Android application that aims to inspire interest in Mobile Application Security. It is ge

Hafiz Abdulaziz 60 Oct 11, 2022
Proguard configurations for common Android libraries

android-proguard-snippets Example Proguard configurations for common Android libraries. This project assumes that your ProGuard configuration is based

Kevin Schultz 4.6k Dec 18, 2022
A demo of the power menu with Reveal and other animations

MaterialPowerMenu A demo of the power menu with Reveal and other animations Some days ago, I saw a gif on Google+ demonstating a concept of Android Po

Naman Dwivedi 888 Oct 11, 2022
Deletes other specs before the compileGroovy gradle task

run-groovy-spec-faster Template ToDo list Create a new IntelliJ Platform Plugin Template project. Get familiar with the template documentation. Verify

null 0 Nov 27, 2021
A sample app showing how to build an app using the MVI architecture pattern.

MVI Example This application was streamed live on Twitch to demonstrate how to build an application using MVI. You can find the VOD here for now: http

Adam McNeilly 46 Jan 2, 2023
Quality-Tools-for-Android 7.5 0.0 L5 Java This is an Android sample app + tests that will be used to work on various project to increase the quality of the Android platform.

Quality Tools for Android This is an Android sample app + tests that will be used to work on various project to increase the quality of the Android pl

Stéphane Nicolas 1.3k Dec 27, 2022
How to apply meaningful and delightful motion in a sample Android app

Applying meaningful motion on Android How to apply meaningful and delightful motion in a sample Android app Read the complete post at https://medium.c

André Mion 167 Dec 19, 2022
Android sample app following best practices: Kotlin, Compose, Coroutines and Flow, Hilt, JetPack Navigation, ViewModel, MVVM and MVI, Retrofit, Coil

Foodies - Modern Android Architecture Foodies is a sample project that presents a modern 2021 approach to Android app development. The project tries t

null 362 Jan 2, 2023
A sample Android app that demonstrates how to use Firebase Authentication, Crashlytics, Cloud Firestore and Hilt with Jetpack Compose UI

showcase.mp4 Make it So This is a sample Android app that demonstrates how to use Firebase Authentication, Crashlytics, Cloud Firestore and Hilt with

null 107 Dec 31, 2022
A sample Grocery Store app built using the Room, MVVM, Live Data, Rx Java, Dependency Injection (Kotlin Injection) and support Dark Mode

Apps Intro A sample Grocery Store app built using the Room, MVVM, Live Data, Rx Java, Dependency Injection (Kotlin Injection) and support Dark Mode In

Irsyad Abdillah 25 Dec 9, 2022
👨‍💻 A demonstration modern Android development project with Jetpack(Compose, Room, ViewModel, Navigation), Hilt and based on MVVM by using Open Sky API. ✈️ 🌍

A demonstration modern Android development project with Jetpack(Compose, Room, ViewModel, Navigation), Hilt and based on MVVM by using Open Sky API.

Ismail Oguzhan Ay 13 Dec 4, 2022
📚 Sample Android Components Architecture on a modular word focused on the scalability, testability and maintainability written in Kotlin, following best practices using Jetpack.

Android Components Architecture in a Modular Word Android Components Architecture in a Modular Word is a sample project that presents modern, 2020 app

Madalin Valceleanu 2.3k Dec 30, 2022
Sample material transition animations for Android

See ListOfThings for a newer implementation. Android Material Transitions This Android project samples some Material Design-ish transitions for list i

Todd Way 1.2k Dec 7, 2022