Giter Site home page Giter Site logo

holdr's Introduction

[Deprecated]

View Binding does everything holdr does but is a first-party solution. I will still be maintaing this project and fixing any bugs, but I will not be adding any new features.

Holdr

What is Holdr?

Holdr generates classes based on your layouts to help you interact with them in a type-safe way. It removes the boilerplate of doing TextView myTextView = findViewById(R.id.my_text_view) all the time.

Doesn't Butter Knife/AndroidAnnotaions/RoboGuice already do that?

This is a different approach to solving the same problem, the important difference is your layout dictates what is generated instead of annotations on your classes. This means that it's much less likely for your code and layouts to get out of sync.

This approach also means zero reflection (and no proguard issues) and works equally as well in library projects.

Usage

Simply apply the gradle plugin and your done!

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'
        classpath 'me.tatarka.holdr:gradle-plugin:1.5.2'
    }
}

repositories {
    mavenCentral()
}

apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.holdr'

alternativly, you can use the new gradle 2.1+ syntax

plugins {
  id "me.tatarka.holdr" version "1.5.2"
}

Say you have a layout file hand.xml.

<!-- hand.xml -->
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:text="Hello, Holdr!"/>
</LinearLayout>

Holdr will create a class for you named your.application.id.holdr.Holdr_Hand. This class is basically a view holder that you can instantiate anywhere you have a view.

In an Activity

public class MyActivity extends Activity {
    private Holdr_Hand holdr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hand);
        holdr = new Holdr_Hand(findViewById(android.R.id.content));
        holdr.text.setText("Hello, Holdr!");
    }
}

In a Fragment

public class MyFragment extends Fragment {
    private Holdr_Hand holdr;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.hand, container, false);
    }
    
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        holdr = new Holdr_Hand(view);
        holdr.text.setText("Hello, Holdr!");
    }
    
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        holdr = null;
    }
}

In an Adapter

public class MyAdapter extends BaseAdapter {
    // other methods
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Holdr_Hand holdr;
        if (convertView == null) {
            holdr = new Holdr_Hand(inflater.inflate(R.layout.hand, parent, false));
            holdr.getView().setTag(holdr);
        } else {
            holdr = (Holdr_Hand) convertView.getTag();
        }
        holdr.text.setText(getItem(position));
        return holdr.getView();
    }
}

In a Custom View

public class MyCustomView extends LinearLayout {
    Holdr_Hand holdr;
    
    // other methods
    
    private void init() {
        holdr = new Holdr_Hand(inflate(getContext(), R.layout.hand, this));
        holdr.text.setText("Hello, Holdr!");
    }
}

Multiple layouts

You may have multiple instances of a layout (in layout and layout-land for example). In that case Holdr will merge the id's across them. If an id appears in one and not the other, a @Nullable annotation will be generated to warn you of this.

If the type of the view doesn't match, Holdr will take the most conservative route and use type View. If instead, they share a common superclass and you want to use that, you can use the app:holdr_class to override the view type so that they match.

<!-- layout/hand.xml -->
<TextView
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:text="Hello, Holdr!"/>

<!-- layout-land/hand.xml -->
<com.example.MyCustomTextView
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:text="Hello, Holdr!"
    app:holdr_class="TextView"/>

Callback Listeners

You can also specify listeners for your Activity/Fragment/Whatever to handle to make working with callbacks a bit nicer. For example, if you had the layout file hand.xml,

<!-- hand.xml -->
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:orientation="vertical" 
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <Button
      android:id="@+id/my_button"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Hello, Holdr!"
      app:holdr_onClick="true"/>
</LinearLayout>

The generated Holdr_Hand class will also have a listener interface for you to implement.

public class MyActivity extends Activity implements Holdr_Hand.Listener {
  private Holdr_Hand holdr;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.hand);
      holdr = new Holdr_Hand(findViewById(android.R.id.content));
      holdr.setListener(this);
  }
  
  @Override
  public void onMyButtonClick(Button myButton) {
      // Handle button click.
  }
}

Here is a list of all the listeners you can handle:

  • holdr_onTouch
  • holdr_onClick
  • holdr_onLongClick
  • holdr_onFocusChange
  • holdr_onCheckedChanged
  • holdr_onEditorAction
  • holdr_onItemClick
  • holdr_onItemLongClick

You can also specify a custom method name by doing app:holdr_onClick="myCustomMethodName" instead. You can also specify the same name on multiple views and they will share a listener (provided the listeners are of the same type).

Custom Superclass

Want to use a Holdr in a place where you need a specific subclass? (RecyclerView.ViewHolder for example). Just use the attribute app:holdr_superclass="com.example.MySuperclass and it will subclass that instead of Holdr. The only requirement is that the superclass must contain a constructor that takes a View.

Controlling What's Generated

If you don't like the idea of a whole bunch of code being generated for all your layouts (It's really not much, I promise!), you can add holdr.defaultInclude false to your build.gradle and then you can manually opt-in for each of your layouts.

The easiest way to opt-in is to add app:holdr_include="all" to the root view of that layout.

By default, every view with an id gets added to the generated class. You can use the attributes holdr_include and holdr_ignore to get more granular control. Both take either the value "view" to act on just the view it's used on or "all" to act on that view and all it's children. For example,

<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/container"
 android:orientation="vertical"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 app:holdr_ignore="all">

 <TextView
     android:id="@+id/text1"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     tools:text="Hello, Holdr!"
     app:holdr_include="view"/>
 `   
 <TextView
     android:id="@+id/text2"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     tools:text="Hello, Holdr!"/>
</LinearLayout>

would include only text1 in the generated class.

Note: The current implementation only allows you to nest these attributes 2 levels deep (ignore inside include inside ignore won't work). I don't think there is a use case complex enough to warrant this, but it may be fixed in a later version if there is a need.

Finally, if you don't like the field name generated for a specific id, you can set it yourself by using app:holdr_field_name="myBetterFieldName" on a view.

Android Studio Plugin

Tired of having to build your project after every layout change? With the intellij plugin the Holdr classes will be auto-generated as soon as you save!

Go to Settings -> Plugins -> Browse Repositories... and search for "Holdr".

The plugin will also allow you to do a refactor-rename on holdr fields and use goto-source (Ctrl-click or Ctrl-B) to go directly to the view in the layout.

(Requires Android Studio 0.6.0+ or Intellij 14)

If instead you feel like living on the edge, you can build install the plugin manually.

  1. Clone the repo
  2. Change studio.path in gradle.properties to point to your Android Studio/Intellij instalation directory
  3. Run ./gradlew intellij-plugin:build --configure-on-demand
  4. Go to Settings -> Plugins -> Install plugin from disk... and install the jar in ./intellij-plugin/build/libs/

holdr's People

Contributors

evant avatar intrications avatar orthographic-pedant avatar ramseyboy 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

holdr's Issues

Add option to strip library resource prefixes from generated class names.

If you have a library project, you can enforce a resource prefix like so:

android {
    resourcePrefix 'mylib_'
}

This can make the generated class names a bit verbose, there should be an option to strip that prefix. For example, if you had mylib_fragment_main you would get Holdr_FragmentMain instead of Holdr_MyLibFragmentMain.

Listener custom button

Hi! I have triedi listener "holdr_onClick" on custom button. The holdr generated class doesn't generate listener for it. Why???

maven

How about maven plugin, like Butterknife does?
I'd like to use Holdr but it does not work when including it as a maven dependency.
I also didn't find a way to run IDEA plugin. Can it work without gradle?

Better error reporting on invalid class generation

I had an xml file with:

android:id="@+android:id/icon"

and a -v17 with

android:id="@android:id/icon"

Obviously the inconsistent + is not needed and wrong, but it didn't cause any issues without using Holdr. I think it's completely reasonable for Holdr to be stricter about something like that, however the error message was not helpful.

> trying to create the same field twice: icon

Without letting me know which layout xml caused the problem. I hacked in a "creating Holdr_XXX.java" line before the "created Holdr_XXX.java" to assist in finding the issue, but it'd be great to have something officially in Holdr.

<include ..> tag

Sometimes I reuse layouts inside of other layouts. I use "include" tag. Holdr does not include ids from included xmls. I'd like it to include them.

The code I have:
dialog_record.xml


    <include layout="@layout/dialog_item_edit_actions" />
    <include layout="@layout/dialog_item_delete_actions" />
    <include layout="@layout/dialog_item_date_picker_actions" />

    h = new Holdr_DialogRecord(view);
    h.setListener(this);
    new Holdr_DialogItemEditActions(view).setListener(this);
    new Holdr_DialogItemDeleteActions(view).setListener(this);
    new Holdr_DialogItemDatePickerActions(view).setListener(this);

This looks like a boilerplate to me ;)

Is it possible to somehow mark my includes for Holdr to include them into parent xml?

Create one line to setup

I've felling when I' m writing my activity code like that:

    setContentView(R.layout.hand);
    holdr = new Holdr_HomeActivity(findViewById(android.R.id.content));

I'm writing way to much. I was thinking that it might nicer if we could leverage LAYOUT variable that is already in Holdr_HomeActivity instance.

We could generate methods like:

public static Holdr_HomeActivity setContent(Activity activity) {
    activity.setContentView(LAYOUT);
    return new Holdr_HomeActivity(activity.findViewById(android.R.id.content));
}

We might do sth similar for customViews:

public static Holdr_HomeActivity inflateView(ViewGroup view) {
    return new Holdr_HomeActivity(view.inflate(view.getContext(), LAYOUT, view));
}

This will also reduce number of bugs that sometimes appear when you change layout somewhere, or have sth copy pasted and on first run you crush and need to fix obvious overlook.

Callback Listeners

Allow you to define listeners like 'onClick' in your layout file and implement them in your Activity/Fragment/Whatever.

If you write this:

<!-- hand.xml -->
<Button
  android:id="@+id/button"
  app:holdr_onClick="true" />

(Can also use app:holder_onClick="onMyButtonClick" for a custom method name)

It generates this:

public class Holdr_Hand extends Holdr {
  public Button button;

  private Listener _holdrListener;

  public Holdr_Hand(View view) {
    super(view);
    button = (Button) view.findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        if (_holderListener != null) _holderListener.onButtonClick(button);
     }
    });
  }

  public void setListener(Listener listener) {
    _holderListener = listener;
  }

  public interface Listener {
    void onButtonClick(Button button);
  }
}

Which can by used like this:

public class MyActivity extends Activity implements Holdr_Hand.Listener {
  private Hold_Hand holdr;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.hand);
    holdr = new Holdr_Hand(findViewById(android.R.id.content));
    holdr.setListener(this);
  }

  @Override
  public void onButtonClick(Button button) {
    // Button clicked!
  }
}

Extracting Annotations Fails

Not extracting annotations (compilation problems encountered)
Error:/home/evan/android/Holdr/sample-library/src/main/java/me/tatarka/samplelibrary/LibraryExampleFragment.java:8: The import me.tatarka.samplelibrary.holdr cannot be resolved

It looks like the the generated Holdr classes aren't added to the classpath used by the annotation extractor. I'm using variant.registerJavaGeneratingTask(task, outputDir) though, so could this a bug in the android gradle plugin?

Fragment Holdr not generating

Android Studio 0.8.9
Java 8 (Retrolambda)

I'm attempting to use this library, and while it's generated a view for my activity, it's not generating anything for a newly created fragment. Is there something I'm missing? I've tried running and restarting AS. I've also tried installing the IntelliJ plugin.

Holdr generates menu layouts?

1.4.0

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android = "http://schemas.android.com/apk/res/android">
  <item
    android:id = "@+id/action_filter"
    android:icon = "@drawable/ic_logo"
    android:title = "Filter"
    android:showAsAction="always"
    />
</menu>
import android.view.View;
import me.tatarka.holdr.Holdr;

public class Holdr_Lesson extends Holdr
{
    public final static int LAYOUT = R.layout.lesson;
    /**
     * 
     */
    public android.widget.item actionFilter;

    /**
     * Constructs a new {@link me.tatarka.holdr.Holdr} for
     * 
     * @param view
     *     The root view to search for the holdr's views.
     */
    public Holdr_Lesson(View view) {
        super(view);
        actionFilter = ((android.widget.item) view.findViewById(R.id.action_filter));
    }
}

why? it breaks build ofc

Not compatible with android gradle plugin v1.1.0-rc1

No such property: defaultConfigData for class: com.android.build.gradle.LibraryPlugin
    at me.tatarka.holdr.gradle.HoldrPlugin.getManifestPackage(HoldrPlugin.groovy:74)
    at me.tatarka.holdr.gradle.HoldrExtension.getHoldrPackage(HoldrExtension.groovy:25)
    at me.tatarka.holdr.gradle.HoldrExtension_Decorated.getHoldrPackage(Unknown Source)
    at org.gradle.api.internal.BeanDynamicObject$MetaClassAdapter.getProperty(BeanDynamicObject.java:153)
    at org.gradle.api.internal.BeanDynamicObject.getProperty(BeanDynamicObject.java:107)
    at org.gradle.api.internal.CompositeDynamicObject.getProperty(CompositeDynamicObject.java:78)
    at me.tatarka.holdr.gradle.HoldrExtension_Decorated.getProperty(Unknown Source)
    at me.tatarka.holdr.gradle.HoldrPlugin$_applyHoldrPlugin_closure4_closure5.doCall(HoldrPlugin.groovy:55)
    at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:63)
    at org.gradle.util.ConfigureUtil.configure(ConfigureUtil.java:130)
    at org.gradle.util.ConfigureUtil.configure(ConfigureUtil.java:110)
    at org.gradle.api.internal.AbstractTask.configure(AbstractTask.java:482)
    at org.gradle.api.internal.project.AbstractProject.task(AbstractProject.java:879)
    at me.tatarka.holdr.gradle.HoldrPlugin$_applyHoldrPlugin_closure4.doCall(HoldrPlugin.groovy:54)
    at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:63)
    at org.gradle.listener.ActionBroadcast.execute(ActionBroadcast.java:39)
    at org.gradle.api.internal.DefaultDomainObjectCollection.doAdd(DefaultDomainObjectCollection.java:165)
    at org.gradle.api.internal.DefaultDomainObjectCollection.add(DefaultDomainObjectCollection.java:160)
    at com.android.build.gradle.LibraryExtension.addVariant(LibraryExtension.groovy:68)
    at com.android.build.gradle.internal.VariantManager.createApiObjects(VariantManager.java:625)
    at com.android.build.gradle.internal.VariantManager.createAndroidTasks(VariantManager.java:246)
    at com.android.build.gradle.BasePlugin.createAndroidTasks(BasePlugin.groovy:431)
    at com.android.build.gradle.BasePlugin$_createTasks_closure9.doCall(BasePlugin.groovy:373)
    at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:40)
    at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:25)
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:83)
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:31)
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy13.afterEvaluate(Unknown Source)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:79)

Holdr generating invalid classes from appcompat-v7 (21)

screenshot 2014-10-22 11 50 23

This is resulting in compilation errors. One of the generated lines is as follows:

public android.widget.ImageView android:icon2;

I attempted to add the holdr.defaultInclude false as recommended in the docs, though I'm not sure it's working/if I've put it in the right place in my build.gradle.

java.lang.NoSuchFieldError in Android Studio 2.2 Preview 1

When trying to compile in Android Studio 2.2 Preview 1, I get the following error:

 PicoPluginExtensionInitializationException: IDE_ANDROID_PROJECT
5:05:34 PM Gradle sync failed: Found interface org.jetbrains.plugins.gradle.service.project.ProjectResolverContext, but class was expected
           Consult IDE log for more details (Help | Show Log)

Once I view the log, I see:

java.lang.NoSuchFieldError: IDE_ANDROID_PROJECT
    at me.tatarka.holdr.intellij.plugin.HoldrDataService.<clinit>(HoldrDataService.java:24)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.picocontainer.defaults.InstantiatingComponentAdapter.newInstance(InstantiatingComponentAdapter.java:193)
    at org.picocontainer.defaults.ConstructorInjectionComponentAdapter$1.run(ConstructorInjectionComponentAdapter.java:220)
    at org.picocontainer.defaults.ThreadLocalCyclicDependencyGuard.observe(ThreadLocalCyclicDependencyGuard.java:53)
    at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:248)
    at com.intellij.util.pico.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:59)
    at com.intellij.openapi.extensions.impl.ExtensionComponentAdapter.getComponentInstance(ExtensionComponentAdapter.java:77)
    at com.intellij.openapi.extensions.impl.ExtensionComponentAdapter.getExtension(ExtensionComponentAdapter.java:119)
    at com.intellij.openapi.extensions.impl.ExtensionPointImpl.processAdapters(ExtensionPointImpl.java:249)
    at com.intellij.openapi.extensions.impl.ExtensionPointImpl.getExtensions(ExtensionPointImpl.java:194)
    at com.intellij.openapi.extensions.Extensions.getExtensions(Extensions.java:100)
    at com.intellij.openapi.extensions.Extensions.getExtensions(Extensions.java:87)
    at com.intellij.openapi.extensions.ExtensionPointName.getExtensions(ExtensionPointName.java:49)
    at com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager$1.compute(ProjectDataManager.java:73)
    at com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager$1.compute(ProjectDataManager.java:68)
    at com.intellij.openapi.util.NotNullLazyValue.getValue(NotNullLazyValue.java:39)
    at com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager.prepareDataToUse(ProjectDataManager.java:379)
    at com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager.access$100(ProjectDataManager.java:55)
    at com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager$4.consume(ProjectDataManager.java:307)
    at com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager$4.consume(ProjectDataManager.java:304)
    at com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.visit(ExternalSystemApiUtil.java:349)
    at com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager.ensureTheDataIsReadyToUse(ProjectDataManager.java:304)
    at com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsDataStorage.validate(ExternalProjectsDataStorage.java:111)
    at com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsDataStorage.load(ExternalProjectsDataStorage.java:93)
    at com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager.init(ExternalProjectsManager.java:121)
    at com.intellij.openapi.externalSystem.service.ExternalSystemStartupActivity.runActivity(ExternalSystemStartupActivity.java:77)
    at com.intellij.ide.startup.impl.StartupManagerImpl$2.run(StartupManagerImpl.java:149)
    at com.intellij.ide.startup.impl.StartupManagerImpl.runActivity(StartupManagerImpl.java:344)
    at com.intellij.ide.startup.impl.StartupManagerImpl.access$700(StartupManagerImpl.java:60)
    at com.intellij.ide.startup.impl.StartupManagerImpl$3.run(StartupManagerImpl.java:167)
    at com.intellij.openapi.project.DumbServiceImpl.notifyUpdateFinished(DumbServiceImpl.java:326)
    at com.intellij.openapi.project.DumbServiceImpl.access$1300(DumbServiceImpl.java:52)
    at com.intellij.openapi.project.DumbServiceImpl$4.run(DumbServiceImpl.java:304)
    at com.intellij.openapi.project.DumbPermissionServiceImpl.allowStartingDumbModeInside(DumbPermissionServiceImpl.java:37)
    at com.intellij.openapi.project.DumbService.allowStartingDumbModeInside(DumbService.java:283)
    at com.intellij.openapi.project.DumbServiceImpl.updateFinished(DumbServiceImpl.java:302)
    at com.intellij.openapi.project.DumbServiceImpl.access$1100(DumbServiceImpl.java:52)
    at com.intellij.openapi.project.DumbServiceImpl$12.run(DumbServiceImpl.java:511)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:301)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:857)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:658)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:386)
    at com.intellij.ide.IdeEventQueue.pumpEventsForHierarchy(IdeEventQueue.java:944)
    at com.intellij.openapi.progress.util.ProgressWindow.startBlocking(ProgressWindow.java:210)
    at com.intellij.openapi.progress.util.ProgressWindow.startBlocking(ProgressWindow.java:197)
    at com.intellij.openapi.application.impl.ApplicationImpl.runProcessWithProgressSynchronously(ApplicationImpl.java:649)
    at com.intellij.openapi.progress.impl.CoreProgressManager.runProcessWithProgressSynchronously(CoreProgressManager.java:354)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.runProcessWithProgressSynchronously(ProgressManagerImpl.java:76)
    at com.intellij.openapi.progress.impl.CoreProgressManager.runProcessWithProgressSynchronously(CoreProgressManager.java:230)
    at com.intellij.openapi.progress.impl.CoreProgressManager.runProcessWithProgressSynchronously(CoreProgressManager.java:183)
    at com.intellij.openapi.project.impl.ProjectManagerImpl.openProject(ProjectManagerImpl.java:372)
    at com.intellij.openapi.project.impl.ProjectManagerImpl.loadAndOpenProject(ProjectManagerImpl.java:468)
    at com.intellij.ide.impl.ProjectUtil.openProject(ProjectUtil.java:182)
    at com.intellij.ide.RecentProjectsManagerImpl.doOpenProject(RecentProjectsManagerImpl.java:60)
    at com.intellij.ide.ReopenProjectAction.actionPerformed(ReopenProjectAction.java:61)
    at com.intellij.openapi.wm.impl.welcomeScreen.RecentProjectPanel$2.onClick(RecentProjectPanel.java:126)
    at com.intellij.ui.ClickListener$1.mouseReleased(ClickListener.java:73)
    at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:290)
    at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
    at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)
    at java.awt.Component.processMouseEvent(Component.java:6533)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at com.intellij.openapi.wm.impl.welcomeScreen.RecentProjectPanel$MyList.processMouseEvent(RecentProjectPanel.java:355)
    at java.awt.Component.processEvent(Component.java:6298)
    at java.awt.Container.processEvent(Container.java:2236)
    at java.awt.Component.dispatchEventImpl(Component.java:4889)
    at java.awt.Container.dispatchEventImpl(Container.java:2294)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
    at java.awt.Container.dispatchEventImpl(Container.java:2280)
    at java.awt.Window.dispatchEventImpl(Window.java:2746)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:857)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:654)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:386)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
2016-05-19 17:05:11,192 [  15540]  ERROR - nsions.impl.ExtensionPointImpl - Android Studio 2.2 Preview 1  Build #AI-145.2878421 
2016-05-19 17:05:11,193 [  15541]  ERROR - nsions.impl.ExtensionPointImpl - JDK: 1.8.0_76-release 
2016-05-19 17:05:11,193 [  15541]  ERROR - nsions.impl.ExtensionPointImpl - VM: OpenJDK 64-Bit Server VM 
2016-05-19 17:05:11,193 [  15541]  ERROR - nsions.impl.ExtensionPointImpl - Vendor: JetBrains s.r.o 
2016-05-19 17:05:11,193 [  15541]  ERROR - nsions.impl.ExtensionPointImpl - OS: Mac OS X 
2016-05-19 17:05:11,193 [  15541]  ERROR - nsions.impl.ExtensionPointImpl - Last Action:  
2016-05-19 17:05:11,219 [  15567]   INFO - dea.updater.SdkComponentSource - Downloading https://dl.google.com/android/repository/sys-img/x86/addon2-1-x86.xml 

Build on Windows crashes with java.lang.IllegalArgumentException

Holdr crashes on Windows with

     Caused by: java.lang.IllegalArgumentException: character to be escaped is missing
            at me.tatarka.holdr.compile.HoldrCompiler.packageToFile(HoldrCompiler.java:158)

(full log is below). I'm not sure whe are you using replaceAll instead of simple replace it should fix that. The exception is caused with regexp acording to this: http://stackoverflow.com/questions/23869613/how-to-replace-one-or-more-in-string-with-just

 it will find match for regex you will see exception

java.lang.IllegalArgumentException: character to be escaped is missing
It is because in replacement (second argument in replaceAll method) you can also use special formula

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:generateDebugHoldr'.
> character to be escaped is missing

* Try:        
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:generateDebugHoldr'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69
)
    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.ja
va:42)
    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.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:305)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java
:79)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java
:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:8
0)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:36)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
    at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:51)
    at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:171)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
    at org.gradle.launcher.Main.doAction(Main.java:33)
    at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
    at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
    at org.gradle.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:33)
    at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:130)
    at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:48)
Caused by: java.lang.IllegalArgumentException: character to be escaped is missing
    at me.tatarka.holdr.compile.HoldrCompiler.packageToFile(HoldrCompiler.java:158)
    at me.tatarka.holdr.compile.HoldrCompiler.outputFile(HoldrCompiler.java:150)
    at me.tatarka.holdr.compile.HoldrCompiler.compile(HoldrCompiler.java:56)
    at me.tatarka.holdr.compile.HoldrCompiler.compile(HoldrCompiler.java:28)
    at me.tatarka.holdr.compile.HoldrCompiler$compile.call(Unknown Source)
    at me.tatarka.holdr.gradle.HoldrTask.execute(HoldrTask.groovy:51)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(Annotati
onProcessingTaskFactory.java:235)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationPro
cessingTaskFactory.java:211)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(Annotation
ProcessingTaskFactory.java:222)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationPro
cessingTaskFactory.java:200)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)

    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61
)
    ... 47 more

Holdr support bind data

Holder cand bind data is an interesting thing 👍

In layout file

<!-- hand.xml -->
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

Bean class

public class User{
    private String username;
    private String password;
}

and holdr support some thing like this

holdr = new Holdr_Hand(rootView);
holdr.bind(user);

onItemClicked AdapterView<?> bug?

xml

public class EdgeEffectListView extends android.widget.ListView  <--

<uk.co.androidalliance.edgeeffectoverride.EdgeEffectListView
    android:id = "@+id/events_list"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    app:edgeeffect_color = "@color/overscroll"
    app:holdr_onItemClick = "true"
    />

Holdr_EventList wont compile because of this import:

import android.widget.AdapterView<?>;

error ';' expected

Holdr plugin breaks on gradle build tools 2.2.0-alpha3

Trying to build with the holdr plugin on build tools 2.2.0-alpha3 causes the following error

Failed to notify ProjectEvaluationListener.afterEvaluate(), but primary configuration failure takes precedence.
java.lang.IllegalStateException: buildToolsVersion is not specified.
    at com.google.common.base.Preconditions.checkState(Preconditions.java:176)
    at com.android.build.gradle.BasePlugin.createAndroidTasks(BasePlugin.java:650)
    at com.android.build.gradle.BasePlugin$10.call(BasePlugin.java:617)
    at com.android.build.gradle.BasePlugin$10.call(BasePlugin.java:614)
    at com.android.builder.profile.ThreadRecorder$1.record(ThreadRecorder.java:55)
    at com.android.builder.profile.ThreadRecorder$1.record(ThreadRecorder.java:47)
    at com.android.build.gradle.BasePlugin.lambda$createTasks$1(BasePlugin.java:613)
    at com.android.build.gradle.BasePlugin$$Lambda$28/867341034.execute(Unknown Source)
    at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:93)
    at org.gradle.internal.event.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:82)
    at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:44)
    at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:79)
    at org.gradle.internal.event.BroadcastDispatch.dispatch(BroadcastDispatch.java:30)
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy10.afterEvaluate(Unknown Source)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:67)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:61)
    at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:510)
    at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:90)
    at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:42)
    at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:35)
    at org.gradle.initialization.DefaultGradleLauncher$2.run(DefaultGradleLauncher.java:125)
    at org.gradle.internal.Factories$1.create(Factories.java:22)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:122)
    at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
    at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:48)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
    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)
    at java.lang.Thread.run(Thread.java:745)

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/bgriffey/Development/HAMobile-Android3/HomeAway-app/build.gradle' line: 29

* What went wrong:
A problem occurred evaluating root project 'HomeAway-app'.
> Failed to apply plugin [id 'me.tatarka.holdr']
   > com.android.build.gradle.AppPlugin cannot be cast to groovy.lang.GroovyObject

Generating Holdr after changes too slow/inconsistent in Android Studio... any tips?

Android Studio 0.8.12
SDK 21
Mac OS X 10.9.2

I'm finding the generation of the Holdr classes to be a little slow/inconsistent when doing day-to-day development. I'm using your suggested IntelliJ plugin, too.

Especially when making changes to an existing layout, I find myself needing to attempt recompiling/running the app before the class is updated/re-generated. It's a little frustrating, as it breaks the flow of development.

Do you have any tips for improving this?

Support <include/>

An <include/> with an id breaks things.
Also would be nice to include all the id's in the <include/>.

How about custom view attrs?

Just an idea. For me, holdr is a perfect place to wrap around a boilerplate of reading custom attrs.

1.processor will gather custom attrs from styleable xmls and add it to Holdr_ template
2. init with new Holdr_MyCustomView(inflatedView, attributeSet);

what do you think?

Support <view/> tags

<view class="com.example.MyCustomView"/> should generate a field of type com.example.MyCustomView

Uses bad path for WebView

Unlike other components WebView is in different package. In generated package it tries to include WebView using "android.widget" package instead of "android.webkit".

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.