GithubHelp home page GithubHelp logo

johncarl81 / transfuse Goto Github PK

View Code? Open in Web Editor NEW
219.0 12.0 28.0 13.34 MB

:syringe: Transfuse - A Dependency Injection and Integration framework for Google Android

Home Page: http://androidtransfuse.org/

License: Apache License 2.0

Java 100.00%
java android android-architecture dependency-injection framework annotation-processor

transfuse's Introduction

Transfuse Transfuse

transfuse Build Status Maven Central

Transfuse is a Java Dependency Injection (DI) and integration library geared specifically for the Google Android API.

There are several key features that make Transfuse a great framework to use with Android:

  • Dependency Injection - Transfuse implements the JSR-330 standard annotations and passes the included unit tests.

  • POJO Components - Transfuse gives users the ability to develop Android components in Plain Old Java Objects (POJO), enabling a testable, decoupled and flexible style.

  • Compile Time Code Generation - Transfuse is remarkably small, lightweight and fast due to the technique of generating supporting code at compile time.

  • Manifest Management - Transfuse manages the Android Manifest, eliminating the duplicated effort of declaring and registering components.

All of these features help eliminate boilerplate plumbing code and make Android applications much easier to write.

Example

Using Transfuse, an Android Activity looks like the following:

@Activity(label = "@string/app_name")
@Layout(R.layout.main)
public class HelloTransfuse {

    @Inject @View(R.id.textview)
    TextView textView;

    @Inject @Resource(R.string.hello)
    String helloText;

    @OnCreate
    public void hello() {
        textView.setText(helloText);
    }
}
  1. Now, Activities no longer extend the android.app.Activity class.

  2. The Android Activity lifecycle is handled via lightweight events. Any component within the injection graph may define event methods to be called during those phases of the lifecycle.

  3. All specialty injections, such as injecting View elements, are designated with qualifier injections (@View, @Resource, etc.).

  4. Activity Manifest metadata, such as the label, are now defined on the class level instead of the AndroidManifest.xml file. This puts all the relevant information regarding the Activity in one place. Transfuse handles the job of registering the Activity and all the associated metadata in the AndroidManifest.xml file.

Interested? Check out the website for details.

Download

You may download Transfuse as a Maven dependency:

<dependency>
    <groupId>org.androidtransfuse</groupId>
    <artifactId>transfuse</artifactId>
    <version>${transfuse.version}</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.androidtransfuse</groupId>
    <artifactId>transfuse-api</artifactId>
    <version>${transfuse.version}</version>
</dependency>

or Gradle:

apt "org.androidtransfuse:transfuse:${transfuseVersion}"
compile "org.androidtransfuse:transfuse-api:${transfuseVersion}"

Or from Maven Central.

License

Copyright 2011-2015 John Ericksen

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.

transfuse's People

Contributors

dbachelder avatar dependabot[bot] avatar gitter-badger avatar goodsoft avatar johncarl81 avatar loganj avatar mingfai avatar raayu83 avatar rehos 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

transfuse's Issues

Exception when parsing AndroidManifest with glEsVersion

Our existing manifest has this uses-feature declaration

    <uses-feature android:glEsVersion="0x00020000" android:required="true" />

Which I think is the required format for that version number:
http://developer.android.com/guide/topics/manifest/uses-feature-element.html#glEsVersion

We end up with the following exception on Transfuse processing:

Caused by: java.lang.NumberFormatException: Not a number: 0x00020000
    at com.sun.xml.internal.bind.DatatypeConverterImpl._parseInt(DatatypeConverterImpl.java:101)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$17.parse(RuntimeBuiltinLeafInfoImpl.java:713)
    at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$17.parse(RuntimeBuiltinLeafInfoImpl.java:711)
    at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.parse(TransducedAccessor.java:230)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:194)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:486)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:465)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:135)
    at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
    at org.apache.xerces.parsers.AbstractXMLDocumentParser.emptyElement(Unknown Source)
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
    at org.androidtransfuse.util.ManifestSerializer.readManifest(ManifestSerializer.java:44)
    at org.androidtransfuse.TransfuseAnnotationProcessor.process(TransfuseAnnotationProcessor.java:119)

Custom interfaces in generated activities delegate to transfuse activity

We use the pattern in our existing app where Fragments require an interface on the containing activity to communicate back to the activity so that in onAttach we can validate that the Activity is of a type that can support the given fragment:

if(!(activity instanceOf CustomInterface)) {
    throw new RuntimeException("Fragment must belong to an Activity that implements CustomInterface.");
}

So that we can later delegate to the activity to handle intra-fragment communication. Is there an existing way to cause transfuse to wire up the delegation from the generated activity to the transfuse activity to support this, or is there a better pattern to achieve this same mechanic?

Assisted Injection

Generate the code behind idenfied interfaces to implement Assisted Injection:

public interface Assistant{
     Output buildOutput(Value v);
}

public class Output{
    @Inject
    public Output(@Assissted Value v, SecondInjectedValue v2){...}
}

Generated:

public class AssistantImpl{
     @inject
     public AssistantImpl(SecondInjectedValue v2){...}
     public Output buildOutput(Value v){
        return new Output(v, v2);
     }
}

Module reconfiguration

Switch @TransfuseModule configuration to use annotations instead of empty interface:

@TransfuseModule
@Bind(bind=TypeToBind.class, to=TypeToBindImpl.class)
@BindInterceptor(interceptor=AOPInterceptor.class, methodInterceptor=AOPMethodInterceptor.class)
@BindProvider(bind=Provided.class, provider=ProvidedProvider.class)
public class Module{

}

Also, adding multiple module configurations would requre a holder annotation:

@Bindings(
{@Bind(...), @Bind(...)})

Another option that comes with this is a @Provides configuration:

@TransfuseModule
public class Module{
    @Provides public Provided getProvided(Dependency dep){
         return new ProvidedImpl(dep);
    }
}

Missing @OnCreateView for Fragment

It is mentioned in the doc but missing from the source.

For now, I'm looking for a way to hook in the moment after layout is inflated in onCreateView. There are two examples, ListFragmentExample and DetailFragment, that they use @OnActivityCreated only.

I do see the onCreateView event is different from the other events as it happens in a different time. If there is a @OnCreateView i would wonder whether i can override the layout inflating. So, I am expect a @Post/AfterCreateView event

Should I go for legacy approach and make my fragment class extend a android.support.v4.app.Fragment for now?

Allowing a Service to be bound through injection.

This is a feature request to allow for a Service to be bound through injection. This requires a bit of thought though. This is because a Service can be both started and bound to. So, the semantics of the injection need to allow for this flexibility and to explicitly state whether the component at the point of injection wishes to start a service, or be bound to it. In the traditional approach, this is distinguished by using startService() versus bindService().

The "first-cut" approach that comes to mind is as follows:

    public interface ServiceOnBind{
        public IBinder onBind(Intent intent);
    }

    @Service
    @RegisterListener
    public class Example implements ServiceOnStartCommand, ServiceOnBind{

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            return return android.app.Service.START_STICKY;
        }

        @OnDestroy
        public void cleanup(){
            //Do some cleanup
        }

        public IBinder onBind(Intent intent){
            return new MyCustomBinder();
        }
    }

But maybe there are better ways of doing this (like @OnBind(clazz=MyCustomBinder.class))?

javax.annotations.Nullable is part of transfuse-bootstrap

I would like to ask you to remove class javax.annotations.Nullable from transfuse-bootstrap and use dependency com.google.code.findbugs:jsr305:1.3.9 instead.

It makes me trouble because Android DEX complains about duplicated class and I can't easily exclude this dependency when it is inside JAR file.

Thanks in advance
Tom

Validate api version against processor version

During annotation processing, to avoid problems that arise from not using the proper transfuse-api version, validate that the trasfuse-api version is the same as the annotation processor transfuse version.

Rework code generation to accommodate external annotation processors.

Code generated by other annotation processors and referenced by code analyzed or referenced by Transfuse causes an ErrorType to be encountered by the ASTTypeBuilderVisitor, which throws a RuntimeException. Instead of throwing a RuntimeException and failing, Transfuse should store the given work for retry in a later round. Additionally, Transfuse should attempt to do as much work as possible to avoid any deadlocks if that code generated by transfuse is needed by other code generators. The idea is to store the work in a Transaction which surrounds the work execution with a try/catch block. If an ErrorType is encountered, Transfuse will throw a specific TransactionRuntimeException which will flag the Transaction for retry in a later round. Transactions should be as fine grained as possible to avoid the mentioned deadlock. To retry a transaction, the Element that was originally used to process from must be reloaded to update any error state.

Example:

Round 1: Executing 1-6

1๏ธโƒฃ---------------------------- โœ…
2๏ธโƒฃ---------------------------- โœ…
3๏ธโƒฃ---------- ๐Ÿ’ฅ
4๏ธโƒฃ---------------------------- โœ…
5๏ธโƒฃ-----------------๐Ÿ’ฅ
6๏ธโƒฃ---------------------------- โœ…

Round 2: Retry 3 and 5

3๏ธโƒฃ---------------------------- โœ…
5๏ธโƒฃ----------------------๐Ÿ’ฅ

Round 3: Retry 5
5๏ธโƒฃ---------------------------- โœ…

Finishing all transactions may trigger actions on aggregate code generations.

Of course, if Transfuse makes it to the last round and Transactions are still in an error state, Transfuse will throw an exception containing the errors to report out.

Change Guava 14.0.1 to 13.0.1 for Intellij IDEA users

New Android-archetype-generated Maven project with Transfuse cannot compile in Intellij IDEA. Android Maven project normally includes:

<dependency>
            <groupId>com.google.android</groupId>
            <artifactId>android</artifactId>
            <version>4.1.1.4</version>
            <scope>provided</scope>
</dependency>

The above dependency depends on an older version of Guava that doesn't have FluentIterable.toSet() that is using by AnnotationProcessorBase.java:44 in transfuse support.

java: java.lang.NoSuchMethodError: com.google.common.collect.FluentIterable.toSet()Lcom/google/common/collect/ImmutableSet;

Remarks: I don't know why but it seems the com.google.android:android depended on the Guava 11.0.2 using by Maven 3.

The compilation does work when running with Maven in command line. So you can say it is a problem specific to Intellij IDEA's compiler. In Intellij IDEA project settings, if i move the platform dependency below the transfuse dependency, I can get pass the NoSuchMethodError. (but will get other problems)

I would say it's not a fault of Transfuse at all to use the latest Guava. Instead, Intellij IDEA shouldn't include the old Guava in Maven when Android platform dependency is included. But it seems easier to make Transfuse to be compatible with Guava 11.0.2 13.0.1 to allow Intellij uses to give it Transfuse a try. Notice that the new Android Studio by Google is Intellij IDEA and the same problem does exist. i.e. anyone who use Android Studio Maven project will get error when trying Transfuse.

Would you accept my pull request if I patch Transfuse to drop Guava from 14 to 11 13? or you think we should just hope Jetbrains fix the problem in IDEA?

Separate Core and Bootstrap

Separate the core of Transfuse (transfuse-core?) so that we may replace Guice as the DI framework within Transfuse with either transfuse-core or a transfuse-bootstrap project. This will help avoid any confusion around using transfuse as a dependency.

Regular Component Manifest Management

Incorporate regular Android API Components into Manifest generation:

@Activity
public class MyActivity extends Activity {
...
}

adds MyActivity to the Manifest

No analog to the Service#onStartCommand() lifecycle method?

Going through the documentation for @Service, I see that the following lifecycle events are defined for a Service

@OnCreate
@OnStart
@OnDestroy

However, onStart() is deprecated and one should now use onStartCommand(). I do not see any direct analog to onStartCommand() in transfuse. Is this intended?

Update doc about "type" attribute in @Activity and @Fragment (maybe others)

It may be a good idea to add a short pointer in the Activity to link to or mention the legacy support section

e.g.

@Activity(type = FragmentActivity.class, label = "Fragments")
@Layout(R.layout.mainfragment)
public class FragmentMain {
}

and

@Fragment(type = ListFragment.class)
public class ListFragmentExample {

Leverage Android Bundle Lifecycle

Register variables to be bundled and save/restored through the onSaveInstanceState()/onRestoreInstanceState() methods. Investigation required.

Need an Activity event before content view is created

AFAIK, @OnCreate is the first event after @Activity class constructor. It happens after setContentView. the majority of logic can be implemented after setContentView/at @OnCreate. However, there does exist at least one corner case as exception.

Certain Android feature requires calling requesWindowFeature before setContentView. e.g.

requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

The line cannot be use in constructor. (that will result as NPE in Android platform class), also it doesn't take effect after setContentView.

As Transfuse provides @OnCreate only, and it happens after setContentView. This is quite a critical case as, if it is true, prohibit the use of certain Android features (and thus require using legacy approach.

A @BeforeSetContentView or @PreCreate/@BeforeCreate will do. Ideally, the annotation can be used in a non-Activity class to run on the Activity class, similar to @OnActivityCreate of Fragment.

Support for extended Activity types

Support the core activity types:

Activity
AccountAuthenticatorActivity
ActivityGroup
AliasActivity
ExpandableListActivity
FragmentActivity
ListActivity
NativeActivity (maybe?)
AccountAuthenticatorActivity
ActivityGroup
AliasActivity
ExpandableListActivity
FragmentActivity
ListActivity
NativeActivity
LauncherActivity
PreferenceActivity
TabActivity
MapActivity

and allow for additional activity types to be configured through the @TransfuseModule

Action Bar Sherlock integration

Action Bar Sherlock, among other libraries, could be integrated better into Transfuse.

First of all, the ActionBar could be injected. This would delegate to ABS for creation and the switch between the support library and ABS' own implementation:

@Inject ActionBar actionbar

Second, ActionBarSherlock could be an injection on its own. This would allow us to accommodate the following configuration methods:

public void setSupportProgress(int progress)
public void setSupportProgressBarIndeterminate(boolean indeterminate)
public void setSupportProgressBarIndeterminateVisibility(boolean visible)
public void setSupportProgressBarVisibility(boolean visible)
public void setSupportSecondaryProgress(int secondaryProgress)

with:

@Inject ActionBarSherlock sherlock
...
sherlock.setProgress(progress);
sherlock.setProgressBarIndeterminate(indeterminate);
sherlock.setProgressBarIndeterminateVisibility(visible);
sherlock.setProgressBarVisibility(visible);
sherlock.setSecondaryProgress(secondaryProgress);

ABS also has a handful of methods that are candidates for the Call-through events. Specifically, the event methods that have ABS specific helper classes. The ABS Menu class is an example of this.

I wonder if we could avoid having to make the SherlockActivity a configuration of @Activity(type=SherlockActivity.class). This may require some work on the core of Transfuse, but would allow for us to integrate ABS into other Activity types. For instance:

    @Override
    protected void onPause() {
        sherlock.dispatchPause();
        super.onPause();
        delegate.onPauseCallback();
    }

could be written into the Activity generated class for:

@Activity
public class Delegate{
    @OnPause
    public void onPauseCallback(){...}
}

Without having to configure ABS at all. There are some details here, mainly around the setContentView methods. Properly delegating these methods may be a challenge.

What would be nice here is to make this integration a proper extension of Transfuse, in it's own library. This would allow people to either include it, if necessary, or avoid using it if it's not needed. We should be able to include the above configuration using a @TransfuseModule plugin.

Multiple application elements when integrating Transfuse into legacy app

I am trying to convert from RoboGuice to Transfuse a little bit at a time. The problem I am hitting is that once I have a Transfuse activity in place I end up with two application blocks in my manifest... one with my legacy stuff and one with the Transfuse stuff.

I am using gradle (1.9) and android-apt (1.2).

Registration annotations

Add annotations to register listeners to View events like the following:

Register the following OnClickListener to the R.id.button1 on the field:

@Register(R.id.button1)
View.OnClickListener handler = View.OnClickListener() {
    public void onClick(View v) {
        ...
        }
    }
}

on the injection itself:

@Inject
@Register(R.id.button1)
OnClickListener listener;

or on the type (for every time the listener is injected):

@Register(R.id.button1)
public class OnClickListenerExample implements View.OnClickListener {
    public void onClick(View v) {
        ...
        }
    }
}

Annotation Retention Policy

Where applicable, reduce the Annotation RetentionPolicy to CLASS. Most, if not all, annotations are not used in reflection or at runtime.

Activity Intent factory

Since we know what Activities require in terms of Extras, and which are optional (@nullable) we should be able to create a factory class for building Activity transition Intents. Additionally, since we can inject the current Activity context, the api of this factory could be the following:

class IntentFactory{
     public Intent buildActivityNameIntent(String extra1, int extra2){...}
}

with optional extras left to add as follows:

Intent intent = intentFactory.buildActivityNameIntent("blah", 42);
intent.putExtra("optionalValue", "hello");

Android API Level support

Tailor the API support level based on configuration in the TransfuseModule. This should include setting up a profile for each major version of the Android API and possibly allowing the user to select the compatibility library. Also, it would be handy to allow the user to define different modules for different api levels. This could turn this sort of code:

public class DoSomethingInAndroid{
...
    public void apply(){ 
        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.GINGERBREAD) {
            editor.apply();
        }
        else {
            editor.commit();
        } 
    }
}

info this:

//configured for pre-Gingerbread
public class DoSomethingInPreGingerbread{
....
    public void apply(){ 
        editor.commit();
    }
}

and:

//configured for Gingerbread
public class DoSomethingInGingerbread{
.... 
    public void apply(){ 
        editor.apply();
    }
}

Package Private and Protected injection helper class

Addition of a package private and protected accessor and mutator helper class would help avoid reflection. Here's the idea:

public class Tester{
    protected String value;
}

Currently, Transfuse sets this by calling the InjectionUtil method:

InjectionUtil.getInstance().setField(Tester.class, tester, "value", inputvalue);

Instead we could generate a helper class within the same package of the target class that would be able to access the protected or package private field:

public class InjectionHelper{
    public void setValueField(Tester tester, inputValue){
        tester.value = inputValue;
    }
}

And the coresponding injection call:

injectionHelper.setValueField(tester, inputValue);

Github pages site

Make a homepage for Transfuse with the following:
Quick Start
Examples
Documentation
Motivation
Pitfalls

Legacy Application support seems to be broken or unimplemented

Refer to the Google Group discussion.

the generated Application class doesn't have the annotation, e.g.

import android.app.Application;
@org.androidtransfuse.annotations.Application
@Debug
public class HelloApp extends Application {
}

The generated class looks like the following:

@Generated(value = "org.androidtransfuse.TransfuseAnnotationProcessor", date = "2013-06-17T00:58+0800")
public class HelloAppApplication
    extends Application
    implements ContextScopeHolder
{

    private Scope scope$0 = new ConcurrentDoubleLockingScope();

    @Override
    public void onCreate() {
        super.onCreate();
        Scopes scopes$0 = Transfuse$ScopesUtil.getInstance();
        HelloApp helloApp$0 = new HelloApp();
    }

    @Override
    public Scope getScope() {
        return scope$0;
    }

}

The annotation is a RUNTIME one

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Debug {
}

Abstract Layout Handler

Provide an interface for the user to define any layout switching code, based on the activity, intent, bundle, etc. This should help solve any issues around producing a Layout based on a calculation, switch statement, time of day...

Example:

@Activity
@LayoutHandler(LayoutHandlerClass.class)
public void SwitchLayoutActivity{ 
}

public class LayoutHandlerClass implements LayoutHander{

    @Inject Activity activity;

    public int getLayout(Bundle bundle)  {
        //...
    }
}       

Manifest ordering

When using the generated manifest I get this lint warning

Warning: <permission> tag appears after <application> tag [ManifestOrder]

Dealing with menus in fragments

Is there a correct way to deal with onOptionsItemSelected and onCreateOptionsMenu in transfuse? I don't see any related annotations unless there is something I can to with the Call Through stuff that I'm not understanding.

@Nullable Extras

Make extras annotated with the additional @nullable annotation optional. If they are provided, they are picked up, if not provided the injected Extra is null.

Inject into views (etc)

Inject into non-instantiated-by-Transfuse object including View objects created by android.

Clean integration test application

Convert the 'Simple App' (which has become not so simple) into a cleanly partitioned integration test of Transfuse leveraging robolectric (or some other unit testing style framework ) to verify all the modules of Transfuse work properly in a full application. This could be a good spot for additional features and bug proof.

0.2.1 compilation exceptions

After upgraded to 0.2.1, and removed my guava 14 hack, my new project with just a few classes got exception in "mvn compile". And the exception doesn't affect Maven build (all projects are SUCCESS in the maven Reactor Summary, but seems to make Intellij IDEA thinks there is build error.

Notice that

  • I can do "mvn compile" for the hello-transfuse project without problem.
  • the same project works in 0.2.0 (with the guava 14 hack)

Any idea?

[INFO] Compiling 9 source files to /MY_PATH/target/classes
Exception in thread "pool-4-thread-2" java.lang.AssertionError: Filling jar:file:/Users/mingfai/.m2/repository/com/google/android/android/4.1.1.4/android-4.1.1.4.jar!/android/app/ActionBar.class during ZipFileIndexFileObject[/Users/mingfai/.m2/repository/com/google/android/android/4.1.1.4/android-4.1.1.4.jar(android/widget/AbsListView$SelectionBoundsAdjuster.class)]
    at com.sun.tools.javac.util.Assert.error(Assert.java:133)
    at com.sun.tools.javac.jvm.ClassReader.fillIn(ClassReader.java:2197)
    at com.sun.tools.javac.jvm.ClassReader.complete(ClassReader.java:2139)
    at com.sun.tools.javac.code.Symbol.complete(Symbol.java:421)
    at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:821)
    at com.sun.tools.javac.code.Symbol$ClassSymbol.getAnnotationMirrors(Symbol.java:774)
    at com.sun.tools.javac.code.Symbol$ClassSymbol.getAnnotationMirrors(Symbol.java:702)
    at org.androidtransfuse.adapter.element.ASTElementFactory.getAnnotations(ASTElementFactory.java:203)
    at org.androidtransfuse.adapter.element.ASTElementFactory.buildType(ASTElementFactory.java:93)
    at org.androidtransfuse.adapter.element.ASTElementFactory.getType(ASTElementFactory.java:77)
    at org.androidtransfuse.adapter.element.ASTElementFactory.buildASTElementType(ASTElementFactory.java:61)
    at org.androidtransfuse.adapter.element.ASTTypeBuilderVisitor.visitDeclared(ASTTypeBuilderVisitor.java:60)
    at org.androidtransfuse.adapter.element.ASTTypeBuilderVisitor.visitDeclared(ASTTypeBuilderVisitor.java:34)
    at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:731)
    at org.androidtransfuse.adapter.element.ASTElementMethod$ASTMethodTypeLazyLoader.buildASTType(ASTElementMethod.java:57)
    at org.androidtransfuse.adapter.element.ASTElementMethod$ASTMethodTypeLazyLoader.buildASTType(ASTElementMethod.java:50)
    at org.androidtransfuse.adapter.element.ASTTypeLazyLoader.getASTType(ASTTypeLazyLoader.java:45)
    at org.androidtransfuse.adapter.element.ASTElementMethod.getReturnType(ASTElementMethod.java:68)
    at org.androidtransfuse.adapter.MethodSignature.makeDescriptor(MethodSignature.java:52)
    at org.androidtransfuse.adapter.MethodSignature.<init>(MethodSignature.java:32)
    at org.androidtransfuse.analysis.Analyzer.isOverridden(Analyzer.java:146)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:115)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:106)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:85)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:41)
    at org.androidtransfuse.gen.variableBuilder.IndependentInjectionNodeBuilder.buildInjectionNode(IndependentInjectionNodeBuilder.java:41)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:168)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:153)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionPoint(InjectionPointFactory.java:127)
    at org.androidtransfuse.analysis.astAnalyzer.InjectionAnalyzer.analyzeField(InjectionAnalyzer.java:79)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:121)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:106)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:85)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:41)
    at org.androidtransfuse.gen.variableBuilder.VariableInjectionNodeBuilder.buildInjectionNode(VariableInjectionNodeBuilder.java:41)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:181)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:153)
    at org.androidtransfuse.gen.componentBuilder.InjectionNodeFactoryImpl.buildInjectionNode(InjectionNodeFactoryImpl.java:69)
    at org.androidtransfuse.gen.ComponentGenerator.generate(ComponentGenerator.java:74)
    at org.androidtransfuse.gen.AnalysisGeneration.innerRun(AnalysisGeneration.java:47)
    at org.androidtransfuse.gen.AnalysisGeneration.innerRun(AnalysisGeneration.java:29)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
    at org.androidtransfuse.transaction.Transaction.run(Transaction.java:77)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
Exception in thread "pool-4-thread-1" org.androidtransfuse.TransfuseAdapterException: Proxy not initialized prior to use
    at org.androidtransfuse.adapter.ASTTypeVirtualProxy.getProxy(ASTTypeVirtualProxy.java:44)
    at org.androidtransfuse.adapter.ASTTypeVirtualProxy.isArray(ASTTypeVirtualProxy.java:79)
    at org.androidtransfuse.adapter.MethodSignature.makeTypeDescriptor(MethodSignature.java:79)
    at org.androidtransfuse.adapter.MethodSignature.makeDescriptor(MethodSignature.java:74)
    at org.androidtransfuse.adapter.MethodSignature.makeDescriptor(MethodSignature.java:56)
    at org.androidtransfuse.adapter.MethodSignature.makeDescriptor(MethodSignature.java:52)
    at org.androidtransfuse.adapter.MethodSignature.<init>(MethodSignature.java:32)
    at org.androidtransfuse.analysis.Analyzer.isOverridden(Analyzer.java:146)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:115)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:106)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:85)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:41)
    at org.androidtransfuse.gen.variableBuilder.IndependentInjectionNodeBuilder.buildInjectionNode(IndependentInjectionNodeBuilder.java:41)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:168)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:153)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionPoint(InjectionPointFactory.java:84)
    at org.androidtransfuse.analysis.astAnalyzer.InjectionAnalyzer.analyzeType(InjectionAnalyzer.java:55)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:112)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:106)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:85)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:41)
    at org.androidtransfuse.gen.variableBuilder.VariableInjectionNodeBuilder.buildInjectionNode(VariableInjectionNodeBuilder.java:41)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:181)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:153)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionPoint(InjectionPointFactory.java:127)
    at org.androidtransfuse.analysis.astAnalyzer.InjectionAnalyzer.analyzeField(InjectionAnalyzer.java:79)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:121)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:106)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:85)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:41)
    at org.androidtransfuse.gen.variableBuilder.VariableInjectionNodeBuilder.buildInjectionNode(VariableInjectionNodeBuilder.java:41)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:181)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:153)
    at org.androidtransfuse.gen.componentBuilder.InjectionNodeFactoryImpl.buildInjectionNode(InjectionNodeFactoryImpl.java:69)
    at org.androidtransfuse.gen.ComponentGenerator.generate(ComponentGenerator.java:74)
    at org.androidtransfuse.gen.AnalysisGeneration.innerRun(AnalysisGeneration.java:47)
    at org.androidtransfuse.gen.AnalysisGeneration.innerRun(AnalysisGeneration.java:29)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
    at org.androidtransfuse.transaction.Transaction.run(Transaction.java:77)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
Exception in thread "pool-12-thread-1" java.lang.AssertionError: Filling jar:file:/Users/mingfai/.m2/repository/com/google/android/android/4.1.1.4/android-4.1.1.4.jar!/android/view/ViewGroup$OnHierarchyChangeListener.class during ZipFileIndexFileObject[/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/lib/ct.sym(META-INF/sym/rt.jar/java/lang/ClassLoader.class)]
    at com.sun.tools.javac.util.Assert.error(Assert.java:133)
    at com.sun.tools.javac.jvm.ClassReader.fillIn(ClassReader.java:2197)
    at com.sun.tools.javac.jvm.ClassReader.complete(ClassReader.java:2139)
    at com.sun.tools.javac.code.Symbol.complete(Symbol.java:421)
    at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:821)
    at com.sun.tools.javac.code.Symbol$ClassSymbol.flags(Symbol.java:764)
    at com.sun.tools.javac.code.Symbol$TypeSymbol.getEnclosedElements(Symbol.java:584)
    at org.androidtransfuse.adapter.element.ASTElementType.loadMethods(ASTElementType.java:77)
    at org.androidtransfuse.adapter.element.ASTElementType.getMethods(ASTElementType.java:70)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:114)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:140)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:140)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:140)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:106)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:85)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:41)
    at org.androidtransfuse.gen.variableBuilder.ViewInjectionNodeBuilder.buildInjectionNode(ViewInjectionNodeBuilder.java:58)
    at org.androidtransfuse.gen.variableBuilder.InjectionNodeBuilderSingleAnnotationAdapter.buildInjectionNode(InjectionNodeBuilderSingleAnnotationAdapter.java:42)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:161)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:153)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionPoint(InjectionPointFactory.java:127)
    at org.androidtransfuse.analysis.astAnalyzer.InjectionAnalyzer.analyzeField(InjectionAnalyzer.java:79)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:121)
    at org.androidtransfuse.analysis.Analyzer.scanClassHierarchy(Analyzer.java:106)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:85)
    at org.androidtransfuse.analysis.Analyzer.analyze(Analyzer.java:41)
    at org.androidtransfuse.gen.variableBuilder.VariableInjectionNodeBuilder.buildInjectionNode(VariableInjectionNodeBuilder.java:41)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:181)
    at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:153)
    at org.androidtransfuse.gen.componentBuilder.InjectionNodeFactoryImpl.buildInjectionNode(InjectionNodeFactoryImpl.java:69)
    at org.androidtransfuse.gen.ComponentGenerator.generate(ComponentGenerator.java:74)
    at org.androidtransfuse.gen.AnalysisGeneration.innerRun(AnalysisGeneration.java:47)
    at org.androidtransfuse.gen.AnalysisGeneration.innerRun(AnalysisGeneration.java:29)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.CodeGenerationScopedTransactionWorker.innerRun(CodeGenerationScopedTransactionWorker.java:47)
    at org.androidtransfuse.transaction.AbstractCompletionTransactionWorker.run(AbstractCompletionTransactionWorker.java:35)
    at org.androidtransfuse.transaction.ScopedTransactionWorker.run(ScopedTransactionWorker.java:55)
    at org.androidtransfuse.transaction.Transaction.run(Transaction.java:77)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)

configurable naming strategy

I'd like to be able to name my Activities *Activity without having to reference *ActivityActivity in code... it would be cool if transfuse could use a configurable naming strategy... So ultimately I could end up with MyActivity -> MyTransfuseActivity and MyFragment -> MyTransfuseFragment ... or something like that, without spelling out said strategy on every single component.

Support injecting FragmentManager in FragmentActivity

There is an example that in a @Fragment class, it supports @Inject FragmentManager.

In a @Activity(type=FragmentActivity.class) class, it doesn't support injecting FragmentManager, and I expect it inject the getSupportingFragmentManager. Instead, it generated code that do new FragmentManager().

As a workaround, we can do:

 @TransfuseModule public static class MainModule{
        @Provides FragmentManager getFragmentManager(FragmentActivity fa){
            return fa.getSupportFragmentManager();
        }
    }

I do it in a similar way in Dagger, but I think Transfuse may potentially make it even simpler without the need to create a Module.

Arbitrary binding annotations

Allow for abitrary binding annotations, including @Name("blah"), but also user defined @Blah annotations to identify specific instances/providers for dependency injection

@ImplementedBy functionality

Implement the specification on an interface which type should be used when the injection of that interface is requested:

@ImplementedBy(ExampleImpl.class)
public interface Example{}

Context needed for failures

I have some stuff misconfigured somewhere... but since I'm doing a huge migration all in one go, it's really hard to track down these errors without more context around what is breaking... can you catch exceptions at some level where you can pump out enough context with the stack to let me know what transfuse was working on when it encountered the error?

16:34:13.238 [ERROR] [system.err] Exception in thread "pool-37-thread-1" java.lang.NoClassDefFoundError: android/view/ViewGroup
16:34:13.238 [ERROR] [system.err]   at java.lang.ClassLoader.defineClass1(Native Method)
16:34:13.238 [ERROR] [system.err]   at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
16:34:13.238 [ERROR] [system.err]   at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
16:34:13.238 [ERROR] [system.err]   at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
16:34:13.239 [ERROR] [system.err]   at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
16:34:13.239 [ERROR] [system.err]   at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
16:34:13.239 [ERROR] [system.err]   at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
16:34:13.239 [ERROR] [system.err]   at java.security.AccessController.doPrivileged(Native Method)
16:34:13.239 [ERROR] [system.err]   at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
16:34:13.239 [ERROR] [system.err]   at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
16:34:13.240 [ERROR] [system.err]   at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
16:34:13.240 [ERROR] [system.err]   at java.lang.Class.forName0(Native Method)
16:34:13.240 [ERROR] [system.err]   at java.lang.Class.forName(Class.java:190)
16:34:13.240 [ERROR] [system.err]   at com.sun.codemodel.JCodeModel.ref(JCodeModel.java:378)
16:34:13.240 [ERROR] [system.err]   at com.sun.codemodel.JCodeModel$TypeNameParser.parseTypeName(JCodeModel.java:472)
16:34:13.240 [ERROR] [system.err]   at com.sun.codemodel.JCodeModel.parseType(JCodeModel.java:424)
16:34:13.241 [ERROR] [system.err]   at org.androidtransfuse.gen.variableBuilder.FragmentViewInjectionNodeBuilder.buildInjectionNode(FragmentViewInjectionNodeBuilder.java:63)
16:34:13.241 [ERROR] [system.err]   at org.androidtransfuse.gen.variableBuilder.InjectionNodeBuilderSingleAnnotationAdapter.buildInjectionNode(InjectionNodeBuilderSingleAnnotationAdapter.java:42)
16:34:13.241 [ERROR] [system.err]   at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:161)
16:34:13.241 [ERROR] [system.err]   at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionNode(InjectionPointFactory.java:153)
16:34:13.241 [ERROR] [system.err]   at org.androidtransfuse.analysis.InjectionPointFactory.buildInjectionPoint(InjectionPointFactory.java:127)
16:34:13.241 [ERROR] [system.err]   at org.androidtransfuse.analysis.astAnalyzer.InjectionAnalyzer.analyzeField(InjectionAnalyzer.java:79)
1

Creating a @Singleton and with an Application injected into the constructor created an invalid class

Is there a correct pattern for creating an application scoped singleton? I also created a SO question for this....

http://stackoverflow.com/questions/21366373/how-do-i-inject-an-application-in-a-transfuse-singleton

@Singleton
public class DbHelper {
@Inject public DbHelper(Application app) {...}
}

generates:

import javax.inject.Provider;
import org.androidtransfuse.scope.Scopes;
import org.androidtransfuse.util.Generated;

@Generated(value = "org.androidtransfuse.TransfuseAnnotationProcessor", date = "2014-01-26T09:22-0800")
public class DbHelper$$UnscopedProvider$$0
    implements Provider<com..rentals.cache.DbHelper>
{

    private Scopes scopes$$1;

    public DbHelper$$UnscopedProvider$$0(Scopes scopes$$2) {
        scopes$$1 = scopes$$2;
    }

    public com..rentals.cache.DbHelper get() {
        com..rentals.cache.DbHelper DbHelper$$0 = new com..rentals.cache.DbHelper(this);
        return DbHelper$$0;
    }

}

The compile error is on the DbHelper construction, as the generated class is not of type Application...

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.