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

Related tags

App 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
An android application which shows usage of various jetpack libraries built by the android team

JetPacker JetPacker is an android application which implements various jetpack libraries created by the android team. FEATURES - (Will be updated as m

Ibrahim 14 Dec 9, 2022
Android app with advanced usage of Epoxy library

Epoxy Advanced Best practices and advanced usages (EditText & Forms) of Epoxy library written in accordance with the Modular and Clean Architectures.

Yusuf Gökmen Arısoy 6 Aug 30, 2022
A sample app illustrating Android development using Kotlin with MVVM architecture, Android Jetpack, and other commonly used libraries.

Anime Facts A sample app illustrating Android development using Kotlin with MVVM architecture, Android Jetpack, and other commonly used libraries. Ani

Eugene Javiñas 0 Dec 5, 2021
Comparison among Java, Groovy, Scala, Kotlin in Android Development.

中文版 日本語 AndroidDemoIn4Languages A simple Android application written in Java, Groovy, Scala and Kotlin in order to find out what is the better languag

Sidney Xu 196 Nov 11, 2022
Advanced Android Weather App using MVVM Architecture Sample (ViewModel + LiveData + Kotlin + volley) = Weather App

Advanced Android Weather App using MVVM Architecture Sample (ViewModel + LiveData + Kotlin + volley) = Weather App Video Weather.-.HD.720p.mov Introdu

wykee2 4 Jul 12, 2022
An Open Source App which enables users to drop all their professional handles and projects at one place.

An Open Source App which enables users to drop all their professional handles and projects at one place. This is a Beginner Friendly Repository made for Open Source Enthusiasts who can contribute to the App during HacktoberFest 2021.

GDSC JSS Noida 32 May 26, 2022
Shreyas Patil 2.1k Dec 30, 2022
ToDo list is a sample project for save task and complete they. developed with Kotlin , Coroutins and Dagger-Hilt Dependency injection.

ToDo list is a sample project for save task and complete they. developed with Kotlin , Coroutins and Dagger-Hilt Dependency injection.

Seyyed Ali Tabatabaei 8 Dec 28, 2022
Freegemas libGDX is an Android and Java desktop port of Freegemas, which in turn is an open source version of the well known Bejeweled.

freegemas-gdx Freegemas libGDX is an Android, HTML 5 and Java desktop port of Freegemas, which in turn is an open source version of the well known Bej

David Saltares 144 Jun 21, 2022
Freegemas libGDX is an Android and Java desktop port of Freegemas, which in turn is an open source version of the well known Bejeweled.

freegemas-gdx Freegemas libGDX is an Android, HTML 5 and Java desktop port of Freegemas, which in turn is an open source version of the well known Bej

David Saltares 144 Jun 21, 2022
Conscrypt Provider app, which can be included from other applications (WIP)

Conscrypt Provider is an APK which can provide the Conscrypt Library to apps that support older Android devices. The Conscrypt Library provides modern

mendhak 8 Oct 1, 2022
Asteroid radar app -Second Project from Udacity Advanced Android Development Kotlin Nanodegree

Asteroid radar app Using open-source Nasa Api Asteroid Radar is an app to view the asteroids detected by NASA that pass near Earth, you can view all t

Mostafa Mohamed 2 Aug 29, 2022
Ride-Sharing Uber Lyft Android App - Learn to build a ride-sharing Android Taxi Clone App like Uber, Lyft - Open-Source Project By MindOrks

Ride-Sharing Uber Lyft Android App - Learn to build a ride-sharing Android Taxi Clone App like Uber, Lyft - Open-Source Project By MindOrks

MindOrks 1.2k Dec 29, 2022
This is an Android project allowing you to use the advanced biometric authorization features.

PLEASE NOTE: If your project has minSDK 23 and should support only basic Fingerprint Authorization on most devices - take a look first at the AndroidX

Sergej Komlach 82 Dec 30, 2022
An advanced DEX editor for Android.

An advanced DEX editor for Android.

Mike Anderson 75 Jan 3, 2023
An advanced Kotlin (Android Native) application that uses SOLID architectural principles, consumes a RESTFUL Service, downloads & images using best practices

Dog-Playground Kotlin An advanced Kotlin (Android Native) application that uses SOLID architectural principles, consumes a RESTFUL Service, downloads

Amose Suwali 1 Jan 10, 2022
NetGuard provides simple and advanced ways to block access to the internet

NetGuard NetGuard provides simple and advanced ways to block access to the internet - no root required. Applications and addresses can individually be

Marcel Bokhorst 598 Dec 31, 2022
LirandAPI - Advanced Kotlin API for Spigot

Lirand API Lirand API allows you to develop Spigot plugins faster, easier and mo

dyamo 9 Dec 4, 2022
A quiz app built with trivia api. This app was built with mvvm architecture, dagger-hilt, retrofit, room database, and navigation components.

A quiz app built with trivia api. This app was built with mvvm architecture, dagger-hilt, retrofit, room database, and navigation components.

Stephen Odumirin 3 Dec 19, 2022