Giter VIP home page Giter VIP logo

dart's Introduction

Dart Maven Central Android ArsenalBuild Status

This is the README of the version 3 of Dart & Henson has been released. If you are looking for the README page of Dart & Henson 2, please visit this wiki page.

Summary

Extra "binding" & intent builders library for Android. Dart & Henson (DH) uses annotation processing to bind intent's extras to pojo fields, and to generate intent builders via a fluent API.

Description of DH 3

Dart and Henson is a an Android Library that structures the navigation layer of your apps. It helps to create intents and consume them in a structured way. We believe it's the best way to organize your navigation layer, and make it less error-prone and easier to maintain.

It is made of 2 components: Dart and Henson. Both of them use annotated classes (navigation models) that describe the parameters (extras of the intent) of a target activity. DH3 provides a gradle plugin to generate the henson navigator class, and we strongly encourage to use the plugin. See the samples for more details.

Navigation models

A navigation model class is a simple pojo with annotated non private fields. The fields describe an extra passed to the target of an intent:

@DartModel //use this annotation on all your models
public class MyActivityNavigationModel {
  //a simple requested field, it's name is used as the extra key
  @BindExtra String extra1;
  //a named field using an annotation
  @BindExtra(MY_CONSTANT_NAME) String extra2;
  //an optional field
  @BindExtra @Nullable MyParcelableOrSerializable extra3;
}

To setup a navigation model module:

dependencies {
  implementation 'com.f2prateek.dart:dart-annotations:X.Y.Z'
  implementation 'com.f2prateek.dart:dart:X.Y.Z'
  implementation 'com.f2prateek.dart:henson:X.Y.Z'
  annotationProcessor 'com.f2prateek.dart:dart-processor:X.Y.Z'
  annotationProcessor 'com.f2prateek.dart:henson-processor:X.Y.Z'
}

Note that in DH3, navigation models:

  • are mandatory, it's not possible to annotate activities directly.
  • must follow a naming convention: they should have the same fully qualified name as the activity or service they describe the navigation of, plus the suffix: NavigationModel. (e.g.: com.foo.wooper.app.MyActivityNavigationModel).
  • must be placed in their own module. If MyActivity lives in the module module-foo, then you should place your navigation models inside a module named module-foo-navigation. There is no constraint enforcement on the name of this module, but we strongly encourage you to stick to this convention for naming the navigation model.
  • the @DartModel annotation is actually optional if there is at least one field annotated with @BindExtra, but, as a good practice, we recommend to always add it.

Dart

The historical first component of the library is used to map intents to Pojos (navigation models). Typically, a target activity will define a navigation model class, a pojo with annotated fields and will map the intents it receives to an instance of its model:

public class MyActivity extends Activity {

  //the navigation model field must be annotated
  //it's up to developers to initialize it
  @DartModel MyNavigationModel navigationModel;
  
  public void onCreate(Bundle savedInstanceState) {
    Dart.bind(this);
  }
}

Note that in DH3:

  • an activity (or a service) can map the extras of the intent it receives, or a bundle like savedInstanceState. For fragments the bundle of getArguments() will be used;
  • you can also use Dart.bind(this, this) or Dart.bind(this, bundle);
  • the initialization of the navigation model is performed by Dart.
  • you can use the code above in a super class and forget not call bind in subclasses. But subclasses will need to annotate their own navigation model field.
  • in the case of inheritance, the navigation model of the subclasses must extend the navigation model of the super class.
  • in the case of inheritance, bind() will replace the instance of the navigation model of the super classes by an instance of the navigation model of the subclasses. That's a side effect of Dart, it allows for better performances (as it doesn't rebind the model in all classes).

Henson

The second component of the library is used to create intents. Based on the navigation model, henson will create an intent builder for the described class (remember the name of the activity / service can be dedudced from the FQN of the model). It creates also some useful wrapper around them, see below.

Generally speaking, Intent Builders generated by Henson are not used directly, but via the HensonNavigator class that is generated for each module. When you want a module M0 to use other module navigation APIs, M0 must use the gradle henson-plugin.

The HensonNavigator Class

Setup of a module using other modules navigation API via HensonNavigator:

apply plugin: 'dart.henson-plugin'

buildscript {
  repositories {
     jcenter()
  }
  dependencies {
    classpath "com.f2prateek.dart:henson-plugin:X.Y.Z"
  }
}

dependencies {
  implementation project(':module1-navigation')
}

henson {
  navigatorPackageName = "com.foo.module0"
}

The plugin scans your dependencies and wraps all the intent builders that are found in the classpath. The HensonNavigator is then generated:

Intent intent = HensonNavigator.gotoMyActivity(context)
 .extra1("foo")
 .extra2(42)
 .extra3(myObj) //optional
 .build();

The intent builders used by a module are detected automatically during the build, based on the dependencies a module uses, and the HensonNavigator is generated accordingly.

What's new in DH3 ?

Briefly:

  • DH2.1 is available to help you migrate to DH3. We will detail this in our migration guide.
  • DH3 classes have been repackaged to allow a smoother migration.
  • DH3 fully supports modularization. It was the main motivation for the version 3, and it requested quite a few changes.
  • DH3 supports navigation cycles between modules. As modules expose their navigation APIs in a different module, we avoid compile time cycles.
  • DH3 offers a gradle plugin. DH3 uses a lot of annotation processing internally, configurations, artifacts, custom tasks. Do not set it up manually unless you know gradle well. Use the plugin.
  • DH3.1+ supports incremental annotation processing when used with gradle 4.7+. All annotation processors are isolating.
  • DH3.1.2+ requires Android Gradle Plugin 3.3.0 as it uses Task Configuration Avoidance.

ProGuard

If ProGuard is enabled be sure to add these rules to your configuration:

-dontwarn dart.internal.**
-keep class **__ExtraBinder { *; }
-keep class **__NavigationModelBinder { *; }
-keepclasseswithmembernames class * {
    @dart.* <fields>;
}
-keep class **Henson { *; }
-keep class **__IntentBuilder { *; }
-keep class **HensonNavigator { *; }

#if you use it
#see Parceler's github page
#for specific proguard instructions

Download

Dart:

implementation 'com.f2prateek.dart:dart:(insert latest version)'
annotationProcessor 'com.f2prateek.dart:dart-processor:(insert latest version)'

Henson :

implementation 'com.f2prateek.dart:henson:(insert latest version)'
annotationProcessor 'com.f2prateek.dart:henson-processor:(insert latest version)'

Henson-plugin :

classpath 'com.f2prateek.dart:henson-plugin:(insert latest version)'
apply plugin: 'dart.henson-plugin'

Kotlin

For all Kotlin enthusiasts, you may wonder how to use this library to configure your intents. This is perfectly compatible, with a bit of understanding of how Kotlin works, especially when it comes to annotation processing.

Assuming that your project is already configured with Kotlin, update your build.gradle file :

apply plugin: 'kotlin-kapt'

dependencies {
  implementation 'com.f2prateek.dart:henson:(insert latest version)'
  kapt 'com.f2prateek.dart:henson-processor:(insert latest version)'
}

Please note that DH3 annotation processors will support incremental annotation processing via the new gradle API. They are also deterministic and kapt tasks can be safely cached.

Now you can use @BindExtra annotation to generate either non-null or nullables properties :

class MyExampleActivityNavigationModel {
  @BindExtra
  lateinit var title: String

  @BindExtra
  var titleDefaultValue: String = "Default Title"

  @Nullable
  @JvmField
  @BindExtra
  var titleNullable: String? = null
}

Note that you still need to use the Java @Nullable annotation otherwise Henson won't interpret your property as nullable and will generate a builder with a mandatory field (even though you declared your property as nullable with the "?" Kotlin marker). Finally, you have to add the @JvmField annotation or your compiler will complain about not having a backing field.

Finally, if you are using Parceler that comes built-in with this library, the syntax does not change from Java, except when dealing with data classes. Because Parceler requires a default constructor with no argument, here is how you need to declare your data class :

@Parcel(Parcel.Serialization.BEAN)
data class ParcelExample @ParcelConstructor constructor(
        val id: Int,
        val name: String,
        ...
}

Talks & Slides

Credits

The original author of the library is Prateek Srivastava who got inspired by the work of Jake Wharton on butter knife.

Later, Daniel Molinero Reguera and Stephane NICOLAS contributed Henson in Dart 2, and rewrote the library for Dart 3.

Logo was designed by Jibbie R. Eguna(jbeguna04)

All the effort on versions 2 and versions 3 have been actively supported by Groupon. Thanks for this awesome OSS commitment !

License

Copyright 2013 Jake Wharton
Copyright 2014 Prateek Srivastava (@f2prateek)

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.

dart's People

Contributors

aardouin avatar alexfacciorusso avatar bryant1410 avatar dlemures avatar f2prateek avatar gabrieloshiro avatar iainconnor avatar intrications avatar jbeguna04 avatar johncarl81 avatar kshirsagarps avatar macarse avatar malinskiy avatar smelfungus avatar stephanenicolas avatar stephenvinouze avatar stkent avatar yaming116 avatar yeuristic avatar

Stargazers

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

Watchers

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

dart's Issues

Being added as a contributor

Hi guys,

First of all congratulations for the library, it is amazing!

I'd like to be added as a contributor to help you continue with this. Currently I'm working with Stephane on it.

Thanks!

[DART 2] Annotation processors should not use Android deps

It creates a confusion : classes of annotation processing time are different from classes at runtime, it's generally a bad idea to refer to classes when creating an annotation processor.

And those dependencies will also slow down CI builds as the dep will always be downloaded when doing a clean build.

Test Class extends a Parcelable

Add a test case for when a class implements Parcelable and extends another class that implements a Parcelable.

class One implements Parcelable {
}
class Two extends One implements Parcelable {
}

Add @InjectArg annotation

It would be nice, in order to remain semantically consistent, to have a specific annotation for Fragment's Arguments.

Missing proguard configuration

Hi,

I was about to start a similar project but just found yours. Thanks for the work. I built my app using Gradle and Proguard throws quite a lot of warnings. I thought it would be nice to have a proguard config in your README.md.

[DART 2.0] sub sub class looses extras from parent

In case we have

class C {
  @InjectExtra String foo;
}
@Henson class B extends C {}
@Henson class A extends B {}

And naming is important (as A is processed before B), then A doesn't contain the extra injections of C.

I will submit a TDD bug fix in a few minutes.

Generalize adapters

A while ago we integrated Dart with Parceler. Recently FragmentArgs integrated as well and I wanted to point out their approach to the same problem. Specifically, FragmentArgs includes a "bundler" parameter to specify any sort of adapter code necessary around reading/writing of bundle extras:

https://github.com/sockeqwe/fragmentargs#argsbundler

I imagine we could do the same thing and would reduce (the already low) coupling mainly around hard coding the Parcels.wrap/unwrap functionality. Something like this:

    @InjectExtra(adapter = ParcelerAdapter.class) ParcelExample example;

Worth noting, Parceler allows you to identify beans to wrap outside of annotating them directly with @Parcel. In the case where we define Parceler beans using @ParcelClass (for instance), Dart would not wrap/unwrap the target instance.

[DART 2.0] Allow to extend the intent builder to a subclass

@Macarse @johncarl81 @f2prateek, please check :

Proposal of extension to Henson DSL.

The problem is the following. Let's say we have

class A {
 @InjectExtra String s;
}

@Henson class B {
}

It would be possible, only in the case of a subclass, to use the DSL of class A to build an intent for class B. Some conditions apply, they are discussed later on.

It would allow to do something like (pseudo code):

if (condition) {
  gotoA();
} else {
  gotoB();
}

For now, the only way to perform such constructs is to build fully independent intents to go to both A and B.

The proposed enhanced DSL syntax would be

Henson.with(context)
 .gotoA()
 .extendTo(B.class)
 .build();

The generated code would then build a normal intent to goto A but would ultimately invoke setClass(context, B.class) on the intent being built when the verb extendTo is invoked.

Conditions and verification

It is important to emphasize that such use case can actually follow a normal good-practice of OO inheritance. However, in order to promote good practices and avoid intent mess, we should not allow to extend the DSL to classes that don't have an inheritance link. That would be a very bad design to share same intent keys for unrelated classes and the would destroy constraint enforcement checking philosophy of Henson.

  • it is possible to check at compile-time that B extends A.
  • in the same way, we should also check that B contains no non-optional @InjectExtra annotated fields (as this would imply an intent to A would only build an incomplete intent to B). Optional fields are allowed though. This can also be checked at compile-time.

Nevertheless, the call to extendTo will be executed at runtime only. We won't be able to perform the checks before runtime and it will require reflection (which breaks the Dart philosophy).
--> See proposal enhancement for compile-time check.

Proposal enhancement to get compile time verification

We could slightly adapt the former proposal to perform a compile-time constraint verification :

Henson.with(context)
 .gotoA()
 .extendToB()
 .build();

In that case, the generated code would allow to switch to B if and only if all conditions described above have been met. Otherwise the DSL extension will not be generated.

Additional feature of the enhanced proposal

It is probably possible to return the internal state B.AllSet after extendToB(). There are maybe some additional constraints but it looks feasible. In that case, after the call to extendToB() it would even be possible use the B$$IntentBuilder DSL to set optional extras of B :

Henson.with(context)
 .gotoA()
 .extendToB()
 .optionalFooInB("foo");
 .build();

In that case the initial condition would be solved by the very elegant :

A.AllSet state = Henson.with(context)
 .gotoA();

if (condition) {
 state.extendToB()
 .optionalFooInB("foo");
 .build()
}

Conflict

This proposal conflicts with #54.

Or maybe the best would be to allow abstract classes to generate a DSL if and only if they are extended (which would change the final state of the DSL state machine). Indeed an abstract class DSL would not provide the build method, only subclasses would, in case we can implement the enhanced proposal.

Schedule

Dart 2.0 RC 3

Henson example

I can't find out how to use henson, the readme is quite shallow, i got a activity annotated with Henson annotation, but the generated navigator don't have any extras options, and if i use InjectExtra on any field of the activity i got the following exception:

Error:(30, 8) error: @henson class MainActivty must not contain any @InjectExtra annotation

How can i correctly use henson with extras?

Proguard issue

Hi, I am using proguard and faced with problem. Current dart proguard rules described here prevent from obfuscate class names.
I found similar issue for butterKnife and took solution from there.
JakeWharton/butterknife#117
Here is correct proguard rules:

-dontwarn com.f2prateek.dart.internal.**
-keep class **$$ExtraInjector { *; }
-keepclasseswithmembernames class * {
    @com.f2prateek.dart.* <fields>;
}

Failed to use Dart/Henson v2 with more than 1 activities

I have 3 activities A, B, C.
When use @InjectExtra in activity B, then call it from activity A with Henson, all works good, but when adding some fields with @InjectExtra to activity C, it fails to generate code.

javax.annotation.processing.FilerException: Illegal name .ui.Henson
    at com.sun.tools.javac.processing.JavacFiler.checkName(JavacFiler.java:495)
    at com.sun.tools.javac.processing.JavacFiler.checkNameAndExistence(JavacFiler.java:517)
    at com.sun.tools.javac.processing.JavacFiler.createSourceOrClassFile(JavacFiler.java:396)
    at com.sun.tools.javac.processing.JavacFiler.createSourceFile(JavacFiler.java:378)
    at com.f2prateek.dart.henson.processor.HensonExtraProcessor.process(HensonExtraProcessor.java:119)
    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:1173)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:859)
    at com.sun.tools.javac.main.Main.compile(Main.java:523)
    at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
    at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
    at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:45)
    at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:33)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:101)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:50)
    at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:36)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:34)
    at org.gradle.api.internal.tasks.compile.CleaningJavaCompilerSupport.execute(CleaningJavaCompilerSupport.java:25)
    at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:157)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:139)
    at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:93)
    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:483)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:243)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:219)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:230)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:208)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:62)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

Actvity factory with Extra inputs

Had an idea for Dart that may be useful. On the Transfuse project we have a feature to build Activities using generated factories which enforce the required/optional characteristics of Extras (http://androidtransfuse.org/documentation.html#intent_factory). A similar feature would compliment Dart as it stands today, giving users a more structured way to start Activities (and possibly services):

class ExampleActivity extends Activity {
  @InjectExtra("name") String name;
  @InjectExtra("age") @Optinal Integer age; 

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    Dart.inject(this);
  }
}

Generated factory generated by Dart every time @InjectExtra is found per class:

DartFactory.start(new ExampleActivityFactory("Andy").setAge(42));

This is similar to the static factory approach taken by many people to start Activities/etc.

Just thought this would be neat. Let me know what you think.

Make @HensonNavigable work even if @InjectExtra is present

What about the fact of making @HensonNavigable to work, even if the Activity contains @InjectExtra annotated fields? In a similar way to @FragmentWithArgs annotation from fragmentargs, this can allow to just annotate all activities, and then if extras are changed during the development cycle (even when all are removed) it still works.

Explain how default values work in README.md

Suppose we have an @Optional @InjectExtra boolean foo. Can we use foo = false/true to initialize a default value in case the field is not found ?

This is missing in the documentation.

[DART 2] Henson not able to detect extras from external target class

When an activity defines its extras in an external class and injects them through Dart.inject(Object target, Activity source), Henson cannot find them.

A possible solution may be a new annotation. It could be used to do two things:

  1. Set target class.
  2. Let Henson know where to look for more extras.

For instance: @InjectExtraTarget private Model model = new Model();...

Lint fails

Hi,

I receive the following error when performing a lint check on my app :

InvalidPackage: Package not included in Android
../../../../../../../.gradle/caches/modules-2/files-2.1/com.f2prateek.dart/dart/1.1.0/cb3f00582e458cea0437f2ec9e04d30543ce7fb6/dart-1.1.0.jar: Invalid package reference in library; not included in Android: javax.lang.model.type. Referenced from com.f2prateek.dart.internal.ExtraInjector.

How can I solve this ?

Proguard rules for Dart 2.0 & Hension?

I tried the rules as documented in README.md but still get some warnings:

Warning: library class com.f2prateek.dart.henson.processor.HensonExtraProcessor extends or implements program class com.f2prateek.dart.common.AbstractDartProcessor
Warning: library class com.f2prateek.dart.henson.processor.HensonNavigatorGenerator extends or implements program class com.f2prateek.dart.common.BaseGenerator
Warning: library class com.f2prateek.dart.henson.processor.IntentBuilderGenerator extends or implements program class com.f2prateek.dart.common.BaseGenerator
Warning: library class com.f2prateek.dart.processor.ExtraInjectionGenerator extends or implements program class com.f2prateek.dart.common.BaseGenerator
Warning: library class com.f2prateek.dart.processor.InjectExtraProcessor extends or implements program class com.f2prateek.dart.common.AbstractDartProcessor
Warning: com.f2prateek.dart.common.AbstractDartProcessor: can't find referenced field 'javax.annotation.processing.ProcessingEnvironment processingEnv' in program class com.f2prateek.dart.common.AbstractDartProcessor
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.LinkOption
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Files
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Files
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Path
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.attribute.FileAttribute
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Files
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.OpenOption
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Files
Warning: com.squareup.javapoet.JavaFile: can't find referenced method 'java.nio.file.Path toPath()' in library class java.io.File
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Path
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Files
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Path
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Path
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Path
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Path
Warning: com.squareup.javapoet.JavaFile: can't find referenced class java.nio.file.Path

IntentBuilder DSL

From @stephanenicolas #33 (comment)

//the real intent builder would actually 
//define a constructor with a context
//intent is a fake class below
public class IntentBuilder {
    private Intent intent = new Intent();

    //starting point
    public AfterSettingA withA(A a) {
        intent.putExtra(a);
        return new AfterSettingA() {};
    }

    //intermediary states for mandatory fields
    //one per field
    public class AfterSettingA {
        public AllSet withB(B b) {
            intent.putExtra(b);
            return new AllSet() {};
        }
    }

    //final state, also allows to use optional fields.
    public class AllSet {
        //one method per optional field, same return type
        public AllSet withC(C c) {
            intent.putExtra(c);
            return this;
        }

       //final method
        public Intent build() {
            return intent;
        }
    }
}

[DART 2] Ease error fixing, make Henson generation robust

Henson is gonna be generated only in case all works, otherwise you got hundreds of errors

Maybe we could enhance the code generator, to be robust to one activity's builder to fail to be generated in that case Henson would still get generated with only the missing methods for a single failed class that would make it easier to fix.

Thx to Danny Preussler (@dpreussler) for this !

[Dart 2.0] sanitize keys so that they can be java identifiers

For instance if one declares @InjectExtra("a.b"), the intent builder generates code :

public class LocalizedMobileAppService$$IntentBuilder {
  private Intent intent;

  private Bundler bundler = Bundler.create();

  public LocalizedMobileAppService$$IntentBuilder(Context context) {
    intent = new Intent(context, LocalizedMobileAppService.class);
  }

  //a.b is not valid Java identifier
  public LocalizedMobileAppService$$IntentBuilder.AllSet LocationInfo(LocationInfo a.b) {
    bundler.put("a.b", a.b);
    return new LocalizedMobileAppService$$IntentBuilder.AllSet();
  }

  public class AllSet {
    public Intent build() {
      intent.putExtras(bundler.get());
      return intent;
    }
  }
}

And this code doesn't compile.

Dart's @Optional annotation collides with butterknife.Optional

There're big chances that ButterKnife is used along Dart, and I spent 45 minutes to debug that "Optional" thing. I was using the Butterknife's annotation on my injected fields...

Because the name collides, I had to prefix those annotations with the package name, and my fields really looks ugly now.

Henson should ignore absract classes with @InjectExtra annotation

As I try to integrate Henson into my app I get a lengthy list of errors that follow this format: error: Unable to write henson navigator for types SomeAbstractClass: Illegal name .Henson.

I notice there's a unit test in place which says that Henson should ignore abstract classes in com.f2prateek.dart.henson.processor.HensonNavigatorGeneratorTest#henson_doesntGotoAbstractClasses

but it doesn't seem to be the case if there's an @InjectExtra annotation. Is there a way to work around this?

Android studio recent changes doesn't require separate artifacts anymotr

Hi @f2prateek,

I am back to dart 2. Hioefully thus time i can finish pour migration..and we can release dart 2 + Henson.

There were some recent changes in AS. We don't need the apt plugin and scope anymore. If an artifact contains both the annotation processor and runtime code, Android Studio will work fine. The annotation processor can be proguarded and the generated code can be called from AS.

Thus I would change dart 2 to get artifacts with both runtime and annotation processor bundled together. One for Henson, one for dart. Maybe one parent also.

Is it fine for you ?

[Dart 2.0] Do not release dart sample

It is currently shipped to sonatype for every release. I remember there is a simple release.skip to insert in the pom to prevent that from happening..

Parceler support is too strong

After merging : https://github.com/f2prateek/dart/pull/76/files
@johncarl81 @iainconnor

we see a problem : devs need Parceler to serialize something like an ArrayList. It would even try to use Parceler if it is not available, making the intentfactory and extrainjector fail.
Good catch @dlemures !

So, we would like to make things a bit more subtile :

  • for collections whose elements use Parceler, use Parceler
  • for collections that are serializable whose elements don't use Parceler, use serializable
  • for collections that are not serializable whose elements don't use Parceler, they are not accepted
  • for types that use Parceler, use it (e.g. @Parceler class House)

[Dart 2.0] Add @Henson annotation

so that even if a class doesn't contain @InjectExtra annotated fields, Henson can still allow navigation to it (@Henson would be added at the class level).

Otherwise those activities would have to be started the standard way which make code less homogenous, and may be more error-prone when an @InjectExtra annotated field is added.

Automatically generate extra key

If I may suggest a new feature, it would be great to have the ability to inject extras without giving an 'extra key' the same way FragmentArgs works :
https://github.com/sockeqwe/fragmentargs

It generates default keys if none is given.
It would avoid boilerplate code when creating an intent such as intent.putExtra(SampleActivity.EXTRA_INT, anInt);
The intent could then be created like proposed in the issue :
#13

What do you think?

Remove javapoet from non-processor modules

The compile dependency graph for dart looks like this:

build.gradle:

compile "com.f2prateek.dart:dart:2.0.0-RC1"
apt "com.f2prateek.dart:dart-processor:2.0.0-RC1"
./gradlew :app:dependencies:

{...}

+--- com.f2prateek.dart:dart:2.0.0-RC1
|    +--- com.f2prateek.dart:dart-annotations:2.0.0-RC1
|    |    \--- com.squareup:javapoet:1.0.0
|    \--- com.squareup:javapoet:1.0.0

Both the dart-annotations and dart-common modules include a dependency on com.squareup:javapoet, which isn't needed (as far as I can tell from scanning the source code). Please consider leaving this dependency in only for the processor portion of the library.

EDIT: As a quick fix, one can exclude javapoet explicitly for the compile artifact:

compile ("com.f2prateek.dart:dart:2.0.0-RC1") {
    exclude group: "com.squareup", module: "javapoet"
}
apt "com.f2prateek.dart:dart-processor:2.0.0-RC1"

Dart 2.0 Spec

  • Split compiler and API artifacts
  • Use JavaPoet
  • Add a Gradle plugin module that Automagically™ sets up the compiler and API artifacts as dependencies with the right scope (see Hugo for example)
  • IntentBuilder DSL (https://cloudup.com/cdZ8PWTSiEH)

These might be done before v2 lands:

  • An intent builder that works on top of the generated bundler
  • A fragment builder that works on top of the generated bundler

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.