Giter VIP home page Giter VIP logo

sunflower's Introduction

Android Sunflower with Compose

A gardening app illustrating Android development best practices with migrating a View-based app to Jetpack Compose. To learn about how Sunflower was migrated to Compose, see the migration journey document.

Note: To see the original View implementation of Sunflower, checkout the views branch.

Screenshots

Features

This sample showcases how to migrate an existing View-based app (Material 2) to Compose (Material 3). See the linked migration journey doc above to learn more.

Note: As Compose cannot render HTML code in Text yet. The AndroidViewBinding API is used to embed a TextView in Compose. See the PlantDescription composable in the PlantDetailView file.

Requirements

Unsplash API key

Sunflower uses the Unsplash API to load pictures on the gallery screen. To use the API, you will need to obtain a free developer API key. See the Unsplash API Documentation for instructions.

Once you have the key, add this line to the gradle.properties file, either in your user home directory (usually ~/.gradle/gradle.properties on Linux and Mac) or in the project's root folder:

unsplash_access_key=<your Unsplash access key>

The app is still usable without an API key, though you won't be able to navigate to the gallery screen.

Android Studio IDE setup

For development, the latest version of Android Studio is required. The latest version can be downloaded from here.

Sunflower uses ktlint to enforce Kotlin coding styles. Here's how to configure it for use with Android Studio (instructions adapted from the ktlint README):

Additional resources

Check out these Wiki pages to learn more about Android Sunflower:

Non-Goals

Previously, this sample app was focused on demonstrating best practices for multiple Jetpack libraries. However, this is no longer the case and development will instead be focused on how to adopt Compose in an existing View-based app. So, there are no plans to implement features outside of this scope. Keep this in mind when making contributions to this library.

Support

If you've found an error in this sample, please file an issue: https://github.com/android/sunflower/issues

Patches are encouraged, and may be submitted by forking this project and submitting a pull request through GitHub.

Third Party Content

Select text used for describing the plants (in plants.json) are used from Wikipedia via CC BY-SA 3.0 US (license in ASSETS_LICENSE).

"seed" by Aisyah is licensed under CC BY 3.0

sunflower's People

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  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

sunflower's Issues

Navigation Drawer remains open

The navigation drawer should close first (if open) onBackPressed. Right now, the drawer is left open while fragment transactions going in the back.

Proposal to remove clicklistener logic from adapter

  1. define an interface OnPlantClickedListener(View view, Plant plant). the view can be used for transition animation later.
  2. implement in Fragment with the Navigation logic
  3. In the XML of the list item, at the root will be android:onClick="@{v -> listener.onPlantClicked(v, plant)}"
  4. When creating the Adapter, pass in the OnPlantClickedListener or create setOnPlantClickedListener method in adapter

Bug : Multiple subscription to livedata

Every time you switch fragment from GardenPlantListing to PlantListing and vice versa both fragments are detached and re-attached causing onCreateView call. Since in onCreateView we call subscribeUi method causing multiple live data observer. This will lead to multiple callbacks for livedata observer and because of this multiple notifyDataSetChanged in adapter.

This blog post explain the issue with livedata and fragment

https://medium.com/@BladeCoder/architecture-components-pitfalls-part-1-9300dd969808

To avoid multiple observer we need to use new view life cycle while observing livedata instead of fragment lifecycle.

Following session from google I/O 18 will help to understand the issue better

https://youtu.be/pErTyQpA390?t=5m41s

New view life cycle is added in support lib 28.0.0 and androidx 1.0.0.

Why not data-binding in GardenPlantingAdapter?

I see still there are some findViewById calls and use non-data-binding style.
Is that the contract of this project that data-binding would not be used in list-view like objects?
I want a confirm, otherwise I will try a PR to optimize it with data-binding.

Why not open test-logging?

When I run "gradlew clean test" I would really have the interest to see logging.

one change-request is to have something like these, not all of them, some are enough:

    testOptions { // <-- You need this
        animationsDisabled = true
        unitTests {
            returnDefaultValues = true
            includeAndroidResources = true
        }

        unitTests.all {
            // All the usual Gradle options.
            testLogging {
                events "passed", "skipped", "failed", "standardOut", "standardError"
                outputs.upToDateWhen { false }
                showStandardStreams = true
            }
            reports.html.enabled = true
            reports.junitXml.enabled = true
            maxParallelForks = 5
            forkEvery = 200
        }

    }

Bug: Too many chances to open "drawer"

There're too many approaches to open "drawer".

  1. Garden-list, with "burg" button
  2. Plant-list, with "arrow" button
  3. In detail screen

How about using a solution of bottom-bar which is also an approach of MD, right @andhie , @tiembo ?

RecyclerView in PlantListFragment does not maintain scroll position on screen rotation

I think this is is because the adapter is initialized and set in the onCreateView, which is called on each rotation.

The scroll position is restored if you set the adapter in subscribeUi instead of in the onCreateView, but then you get a console error:

05-30 16:58:03.796 4570-4570/com.google.samples.apps.sunflower E/RecyclerView: No adapter attached; skipping layout

Use of Kotlin Android Extensions

In GardenFragment.kt can't we directly use
garden_list.run{ }
instead of
findViewById<RecyclerView>(R.id.garden_list).run { } using the Kotlin Android Extensions ?

Compiler Error

Hi, I am pretty new to Kotlin as a development language for Android and I decided to give it a try with this sample app especially since it also introduces me to the Android Jetpack set of libraries and components. I, unfortunately, cannot seem to get it to build once I clone it into my Android Studio. I keep getting the following error and I can't seem to fix it.

 Task :app:kaptGenerateStubsDebugKotlin UP-TO-DATE
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ActivityGardenBinding.java:29: error: cannot find symbol
  protected ActivityGardenBinding(DataBindingComponent _bindingComponent, View _root,
                                  ^
  symbol:   class DataBindingComponent
  location: class ActivityGardenBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ActivityGardenBinding.java:47: error: cannot find symbol
      @Nullable ViewGroup root, boolean attachToRoot, @Nullable DataBindingComponent component) {
                                                                ^
  symbol:   class DataBindingComponent
  location: class ActivityGardenBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ActivityGardenBinding.java:58: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class ActivityGardenBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ActivityGardenBinding.java:67: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class ActivityGardenBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\FragmentPlantDetailBinding.java:49: error: cannot find symbol
  protected FragmentPlantDetailBinding(DataBindingComponent _bindingComponent, View _root,
                                       ^
  symbol:   class DataBindingComponent
  location: class FragmentPlantDetailBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\FragmentPlantDetailBinding.java:79: error: cannot find symbol
      @Nullable ViewGroup root, boolean attachToRoot, @Nullable DataBindingComponent component) {
                                                                ^
  symbol:   class DataBindingComponent
  location: class FragmentPlantDetailBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\FragmentPlantDetailBinding.java:90: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class FragmentPlantDetailBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\FragmentPlantDetailBinding.java:99: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class FragmentPlantDetailBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\FragmentPlantListBinding.java:17: error: cannot find symbol
  protected FragmentPlantListBinding(DataBindingComponent _bindingComponent, View _root,
                                     ^
  symbol:   class DataBindingComponent
  location: class FragmentPlantListBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\FragmentPlantListBinding.java:31: error: cannot find symbol
      @Nullable ViewGroup root, boolean attachToRoot, @Nullable DataBindingComponent component) {
                                                                ^
  symbol:   class DataBindingComponent
  location: class FragmentPlantListBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\FragmentPlantListBinding.java:42: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class FragmentPlantListBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\FragmentPlantListBinding.java:51: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class FragmentPlantListBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ListItemGardenPlantingBinding.java:29: error: cannot find symbol
  protected ListItemGardenPlantingBinding(DataBindingComponent _bindingComponent, View _root,
                                          ^
  symbol:   class DataBindingComponent
  location: class ListItemGardenPlantingBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ListItemGardenPlantingBinding.java:52: error: cannot find symbol
      @Nullable ViewGroup root, boolean attachToRoot, @Nullable DataBindingComponent component) {
                                                                ^
  symbol:   class DataBindingComponent
  location: class ListItemGardenPlantingBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ListItemGardenPlantingBinding.java:63: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class ListItemGardenPlantingBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ListItemGardenPlantingBinding.java:72: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class ListItemGardenPlantingBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ListItemPlantBinding.java:29: error: cannot find symbol
  protected ListItemPlantBinding(DataBindingComponent _bindingComponent, View _root,
                                 ^
  symbol:   class DataBindingComponent
  location: class ListItemPlantBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ListItemPlantBinding.java:58: error: cannot find symbol
      @Nullable ViewGroup root, boolean attachToRoot, @Nullable DataBindingComponent component) {
                                                                ^
  symbol:   class DataBindingComponent
  location: class ListItemPlantBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ListItemPlantBinding.java:69: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class ListItemPlantBinding
e: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\generated\data_binding_base_class_source_out\debug\dataBindingGenBaseClassesDebug\out\com\google\samples\apps\sunflower\databinding\ListItemPlantBinding.java:78: error: cannot find symbol
      @Nullable DataBindingComponent component) {
                ^
  symbol:   class DataBindingComponent
  location: class ListItemPlantBinding
w: C:\Users\hiseh\Documents\Android Studio Projects\android-sunflower\app\build\tmp\kapt3\stubs\debug\com\google\samples\apps\sunflower\data\GardenPlanting.java:15: warning: plant_id column references a foreign key but it is not part of an index. This may trigger full table scans whenever parent table is modified so you are highly advised to create an index that covers this column.
public final class GardenPlanting {
             ^
e: [kapt] An exception occurred: java.lang.UnsatisfiedLinkError: org.sqlite.core.NativeDB._open_utf8([BI)V
	at org.sqlite.core.NativeDB._open_utf8(Native Method)
	at org.sqlite.core.NativeDB._open(NativeDB.java:71)
	at org.sqlite.core.DB.open(DB.java:174)
	at org.sqlite.core.CoreConnection.open(CoreConnection.java:220)
	at org.sqlite.core.CoreConnection.<init>(CoreConnection.java:76)
	at org.sqlite.jdbc3.JDBC3Connection.<init>(JDBC3Connection.java:25)
	at org.sqlite.jdbc4.JDBC4Connection.<init>(JDBC4Connection.java:24)
	at org.sqlite.SQLiteConnection.<init>(SQLiteConnection.java:45)
	at org.sqlite.JDBC.createConnection(JDBC.java:114)
	at android.arch.persistence.room.verifier.DatabaseVerifier$Companion.create(DatabaseVerifier.kt:71)
	at android.arch.persistence.room.processor.DatabaseProcessor.doProcess(DatabaseProcessor.kt:76)
	at android.arch.persistence.room.processor.DatabaseProcessor.process(DatabaseProcessor.kt:53)
	at android.arch.persistence.room.RoomProcessor$DatabaseProcessingStep.process(RoomProcessor.kt:57)
	at com.google.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:318)
	at com.google.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:171)
	at org.jetbrains.kotlin.kapt3.base.ProcessorWrapper.process(annotationProcessing.kt:99)
	at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794)
	at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705)
	at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91)
	at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035)
	at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176)
	at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
	at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1068)
	at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:55)
	at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:27)
	at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:216)
	at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:164)
	at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:93)
	at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:98)
	at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:108)
	at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:85)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:370)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:61)
	at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:101)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:361)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:126)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:154)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:51)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:95)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:50)
	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:88)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$1$2.invoke(CompileServiceImpl.kt:405)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$1$2.invoke(CompileServiceImpl.kt:98)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:927)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:98)
	at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:957)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:926)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:404)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346)
	at sun.rmi.transport.Transport$1.run(Transport.java:200)
	at sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

> Task :app:kaptDebugKotlin FAILED

FAILURE: Build failed with an exception.

I have tried looking up resources online but can't seem to find anything to point me in the right direction. Any and all help will be appreciated. Thanks!

Dagger 2 for dependency injection

Are there any plans on using Dagger 2 for dependency injection in this project? Would be great with a working Android sample using this together with view models and repositories.

AndroidX?

Hello, I was wondering if you guys/gals are going to do a namespace migration to androidx in this project.

I'm asking this because on my current project I'm getting errors:

Failed to resolve: com.google.android.material:material:1.1.0
Failed to resolve: androidx.fragment:fragment:1.1.0
Failed to resolve: androidx.recyclerview:recyclerview:1.1.0

(...)

It would be good to see a working sample with recommended practices. I've been following the guide but with no success, also I included the experimental:

# AndroidX
android.enableJetifier=true
android.useAndroidX=true

Running on:

Android Studio 3.2 Canary 15
Build #AI-181.4668.68.32.4773949, built on May 10, 2018
JRE: 1.8.0_152-release-1136-b02 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
macOS 10.12.6

Project: https://github.com/JoaquimLey/transport-eta/tree/migration/jetpack

Why having multiple activities?

According to this article, Google suggested using only one Activity:

Today we are introducing the Navigation component as a framework for structuring your in-app UI, with a focus on making a single-Activity app the preferred architecture. With out of the box support for Fragments, you get all of the Architecture Components benefits such as Lifecycle and ViewModel while allowing Navigation to handle the complexity of FragmentTransactions for you.

So my question is, why didn't you follow the advice yourself gave?

InstantApp support

Does android-sunflower support InstantApp projects (feature modules)?

Filter button state does not persist on rotation

To reproduce: view the plant list, press the filter button, and then rotate the phone. The list of plants remained filtered but the button state is unfiltered. This means that after the rotation, the first filter button press will not change the [filtered] list of plants (going from unfiltered -> filtered) but the second button press will set both the button state and the list of plants to unfiltered.

Potential-bug: Kotlin (1.2.50) workarounds for Data-binding

  1. dataBindingExportFeaturePackageIdsDebug and dataBindingExportFeaturePackageIdsRelease doesn't work when the app has multi-flavors. However, when the app doesn't have flavors, for defensive programming we need check before using them.
       buildTypes {
            debug { ....
            tasks.whenTaskAdded { task ->
                if (task.name == 'kaptDebugKotlin' && project.tasks.findByName("dataBindingExportFeaturePackageIdsDebug")) { 
                    task.dependsOn dataBindingExportFeaturePackageIdsDebug
                }
            }
        }

        release { ....
            tasks.whenTaskAdded { task ->
                if (task.name == 'kaptReleaseKotlin' && project.tasks.findByName("dataBindingExportFeaturePackageIdsRelease")) {
                    task.dependsOn dataBindingExportFeaturePackageIdsRelease
                }
            }
        }
    }
  1. For multi-flavors case, for example, anyone has interest to define like below, the app cannot be built:
    flavorDimensions "app"

    productFlavors {
        prod {
            dimension "app"
        }
        mock {
            dimension "app"
        }
    }

Solution:

    buildTypes {
        debug {
            ......
            tasks.whenTaskAdded { task ->
                if (task.name == 'kaptDebugKotlin' && project.tasks.findByName('dataBindingExportFeaturePackageIdsDebug')) task.dependsOn dataBindingExportFeaturePackageIdsDebug
                if (task.name == 'kaptProdDebugKotlin' && project.tasks.findByName('dataBindingExportFeaturePackageIdsProdDebug')) task.dependsOn dataBindingExportFeaturePackageIdsProdDebug
                if (task.name == 'kaptMockDebugKotlin' && project.tasks.findByName('dataBindingExportFeaturePackageIdsMockDebug')) task.dependsOn dataBindingExportFeaturePackageIdsMockDebug
            }
        }

        release {
            .......
            tasks.whenTaskAdded { task ->
                if (task.name == 'kaptReleaseKotlin' && project.tasks.findByName('dataBindingExportFeaturePackageIdsRelease')) task.dependsOn dataBindingExportFeaturePackageIdsRelease
                if (task.name == 'kaptProdReleaseKotlin' && project.tasks.findByName('dataBindingExportFeaturePackageIdsProdRelease')) task.dependsOn dataBindingExportFeaturePackageIdsProdRelease
                if (task.name == 'kaptMockReleaseKotlin' && project.tasks.findByName('dataBindingExportFeaturePackageIdsMockRelease')) task.dependsOn dataBindingExportFeaturePackageIdsMockRelease
            }
        }
    }

This is only a potential-bug which might be ignored unneccessarily fixing at moment or in the future when Kotlin doesn't need the workarounds anymore. For learning and experience accumulating I think it could be a thought and noticed.

Paging library & Network

I would like to see work with Paging library and downloading data from the network and updating it to the database

Data Binding Question

Is it is a necessary to have kapt for databinding compiler if you are using data binding in this project?

I noticed this project doesn't have one.

Question

Why do you use your own singleton implementation when you can use embedded language construction: object?

Bug: GardenActivityTest need fix, it doesn't work well

Hi try to test from command line

./gradlew connectedAndroidTest

com.google.samples.apps.sunflower.GardenActivityTest > clickOnPlantListDrawerMenuItem_StartsPlantListActivity[SM-G950F - 7.0] FAILED 
        android.support.test.espresso.NoActivityResumedException: No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)?
        at dalvik.system.VMStack.getThreadStackTrace(Native Method)
11:24:24 V/InstrumentationResultParser: INSTRUMENTATION_STATUS_CODE: -2
11:24:24 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: numtests=14
11:24:24 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: stream=
11:24:24 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
11:24:24 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: test=clickOnAndroidHomeIcon_OpensAndClosesNavigation
11:24:24 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: class=com.google.samples.apps.sunflower.GardenActivityTest
11:24:24 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: current=2
11:24:24 V/InstrumentationResultParser: INSTRUMENTATION_STATUS_CODE: 1


com.google.samples.apps.sunflower.GardenActivityTest > pressDeviceBack_CloseDrawer_Then_PressBack_Close_App[SM-G950F - 7.0] FAILED 
        android.support.test.espresso.NoActivityResumedException: No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)?
        at dalvik.system.VMStack.getThreadStackTrace(Native Method)
11:25:30 V/InstrumentationResultParser: INSTRUMENTATION_STATUS_CODE: -2
11:25:30 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: numtests=14
11:25:30 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: stream=
11:25:30 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: id=AndroidJUnitRunner
11:25:30 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: test=onRotate_NavigationStaysOpen
11:25:30 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: class=com.google.samples.apps.sunflower.GardenActivityTest
11:25:30 V/InstrumentationResultParser: INSTRUMENTATION_STATUS: current=4
11:25:30 V/InstrumentationResultParser: INSTRUMENTATION_STATUS_CODE: 1


ViewModels request new data each time view is recreated

If PlantListFragment or GardenPlantingListFragment are recreated, their ViewModels make a new database request instead of returning the last value held by the livedata.

For example:

fun getGardenPlantings() = gardenPlantingRepository.getGardenPlantings()

fun getPlantAndGardenPlantings() = gardenPlantingRepository.getPlantAndGardenPlantings()

The Arch docs say this is a not to do this (link):

    private LiveData<String> getPostalCode(String address) {
       // DON'T DO THIS
       return repository.getPostCode(address);
    }

The UI component then needs to unregister from the previous LiveData object and register to the new instance each time it calls getPostalCode(). In addition, if the UI component is recreated, it triggers another call to the repository.getPostCode() method instead of using the previous call’s result.

The Arch components BasicSample shows a better way to implement this using MediatorLiveData (link)

When I implemented this myself, using the MediatorLiveData also fixed #10
https://github.com/chris-feldman/android-sunflower/blob/master/app/src/main/java/com/google/samples/apps/sunflower/viewmodels/PlantListViewModel.kt

3rd-party Gradle plug-ins may be the cause

Failed to resolve: junit
Open File

Folder /media/halove/work/demo/android-sunflower/app/build/generated/source/kaptKotlin/debug

Folder /media/halove/work/demo/android-sunflower/app/build/generated/source/kaptKotlin/release

3rd-party Gradle plug-ins may be the cause

my android studio:3.1.2

Logo design contribution

Hallo
I am Masud Rana.
Want to male a logo for this projects.if you have any requirements then let me know.its totally free for open source projects.

Doesn't CI run TESTS?

Should CI run tests?

like:

./gradlew uninstallAll clean connectedAndroidTest test

I think it could give more PR checks.

[MD] Image Item spacing

The spacing of the text between image and text in list item. they seems a little far, may be confusing due to the text might related to the top or the bottom image without reading the text.

suggestion 1:
put the text on the image to inline it. text may need to be shorter to fit nicer

suggestion 2:
have more space between the text and the next item (32dp), doing this will probably have to write a SpaceItemDecorator that applies top margin on 2nd item onwards
https://material.io/design/components/image-lists.html#anatomy

Foreseeable problems:
Suggestion 2 would be more suitable but needs code to do it. reason primarily is because of Plant list is clickable and should have a touch feedback (it doesnt now). need to consider what areas to have ripple or maybe change design

Issue spawned from #47

PlantDetailFragmentTest failed: "java.lang.IllegalArgumentException"

When I run androidTest, it would be failed in testShareTextIntent of PlantDetailFragmentTest.
Log:

java.lang.IllegalArgumentException: Required argument "plantId" is missing and does not have an android:defaultValue
at com.google.samples.apps.sunflower.PlantDetailFragmentArgs.fromBundle(PlantDetailFragmentArgs.java:23)
at com.google.samples.apps.sunflower.PlantDetailFragment.onCreateView(PlantDetailFragment.kt:51)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2425)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2644)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2415)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2371)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2272)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
at android.os.Handler.handleCallback(Handler.java:754)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6348)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:880)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)

Test running failed: Instrumentation run failed due to 'Process crashed.'

Hero image transition animation

Doing transition animation to detail activity via the hero image

Work to do:
Use ActivityOptionsCompat#makeSceneTransitionAnimation(). for the animation by passing in activity and the imageview.
Each list item in Plant adapter should use ViewCompat#setTransitionName() and prefix/suffixed with item position. Both list and detail imageview need to have same transition name. this allows anim to transition backwards when user press back on Detail activity
We need to delay anim in detail via supportPostponeEnterTransition() until Glide loads the image and then use supportStartPostponedEnterTransition()

https://developer.android.com/reference/android/support/v4/app/ActivityOptionsCompat.html#makescenetransitionanimation_4
https://developer.android.com/reference/android/support/v4/view/ViewCompat.html#setTransitionName(android.view.View,%20java.lang.String)

Detail page has two toolbars

After converting to single-activity, there're two toolbars on detail screen.
The app needs a ux/ui decision what should be shown in detail page. @tiembo

Change request for Travis CI

I am a user of Travis CI , I think there are also a lot people here will use it,
any plan to install it for this project or I create a PR for it ?

Previous Activity gets recreated by UP navigation

If the previous activity exists, is it supposed to "pop up"?

I thought according to Principles of Navigation, "if the previous destination exists on the stack, then UP should behave as BACK navigation".

Up and Back are equivalent within your app's task
When the system Back button would not exit your app, such as when you are on your own task and not on the start destination, the Up button should function identically to the system Back button.

getZoneForLatitude seems to have wrong checks

https://github.com/googlesamples/android-sunflower/blob/ee23fbc7608ea99a6fdd008885f0ae09d842dd47/app/src/main/java/com/google/samples/apps/sunflower/utilities/GrowZoneUtil.kt#L38
Looking at the alternatives:
in 21.0..28.0 -> 10
in 28.0..21.0 -> 9
in 35.0..21.0 -> 8
in 42.0..21.0 -> 7
in 49.0..21.0 -> 6
in 56.0..21.0 -> 5
in 63.0..21.0 -> 4
in 70.0..77.0 -> 3

35 to 21 is a subset of 42 to 21, and I'm quite sure you just made a mistake due to copy-paste, so should be:

in 21.0..28.0 -> 10
in 28.0..35.0 -> 9
in 35.0..42.0 -> 8
in 42.0..49.0 -> 7
in 49.0..56.0 -> 6
in 56.0..63.0 -> 5
in 63.0..70.0 -> 4
in 70.0..77.0 -> 3

Material Design specs

The sample app UI is quite crude, and parts of it does not follow the MD specs.
e.g. the Add icon used in the FAB is using the wrong size
e.g. paddings of text

Are there any plans to touch up the UI? or a mock that i can follow for a PR

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.