Categories
discuss

Gradle: Only resolve dependencies for the desired variant

I have a test app with three flavors:

  • dev: Uses a local copy of the library during development
  • qa: Uses a snapshot during QA
  • rc: Uses a prerelease build for release candidate testing.

dependencies {
  devCompile project(':library')
  qaCompile 'com.example:library:1.0.0-SNAPSHOT@aar'
  rcCompile 'com.example:library:1.0.0@aar'
}

I run Gradle, and expect it to do the minimum amount of work necessary to build just what I want:

./gradlew :test-app:connectedAndroidTestDevDebug

However, the build fails, because it is trying to resolve dependencies for all build flavors, not just the one I am building.

FAILURE: Build failed with an exception.

* What went wrong:

A problem occurred configuring project ‘:test-app’.

Could not resolve all dependencies for configuration ‘:test-app:_qaDebugCompile’.

Could not find com.example:library1.0.0-SNAPSHOT.

Searched in the following locations:
     https://repo1.maven.org/maven2/com/example/library/1.0.0-SNAPSHOT/maven-metadata.xml
     https://repo1.maven.org/maven2/com/example/library/1.0.0-SNAPSHOT/library-1.0.0-SNAPSHOT.pom
     https://repo1.maven.org/maven2/com/example/library/1.0.0-SNAPSHOT/library-1.0.0-SNAPSHOT.aar
     http://oss.sonatype.org/content/repositories/snapshots/com/example/library/1.0.0-SNAPSHOT/maven-metadata.xml
     http://oss.sonatype.org/content/repositories/snapshots/com/example/library/1.0.0-SNAPSHOT/library-1.0.0-SNAPSHOT.pom
     http://oss.sonatype.org/content/repositories/snapshots/com/example/library/1.0.0-SNAPSHOT/library-1.0.0-SNAPSHOT.aar
     file:/opt/android-sdk-macosx/extras/android/m2repository/com/example/library/1.0.0-SNAPSHOT/maven-metadata.xml
     file:/opt/android-sdk-macosx/extras/android/m2repository/com/example/library/1.0.0-SNAPSHOT/library-1.0.0-SNAPSHOT.pom
     file:/opt/android-sdk-macosx/extras/android/m2repository/com/example/library/1.0.0-SNAPSHOT/library-1.0.0-SNAPSHOT.aar
     file:/opt/android-sdk-macosx/extras/google/m2repository/com/example/library/1.0.0-SNAPSHOT/maven-metadata.xml
     file:/opt/android-sdk-macosx/extras/google/m2repository/com/example/library/1.0.0-SNAPSHOT/library-1.0.0-SNAPSHOT.pom
     file:/opt/android-sdk-macosx/extras/google/m2repository/com/example/library/1.0.0-SNAPSHOT/library-1.0.0-SNAPSHOT.aar
 Required by:
     project-name:test-app:unspecified

The SNAPSHOT that the qa flavor is trying to resolve doesn’t exist yet, and that should be fine, because I’m not trying to build the qa flavor. If that SNAPSHOT build is present, then everything works fine.

Questions:

  1. Why are all build flavors having their dependencies resolved?
  2. How can I accomplish building just one flavor without encountering this problem?
  3. Is there some better way to do this that will be more “Gradley”?

Answer

I finally solved this by checking the list of tasks and if there is a task for the desired build variant, adding the dependency.

dependencies {
  gradle.startParameter.taskRequests.each { taskRequest ->
    taskRequest.args.each { taskName ->
      String flavorName = "qa";
      if (taskName.toLowerCase().endsWith(flavorName+"debug") ||
          taskName.toLowerCase().endsWith(flavorName+"release")) {
        qaCompile 'com.example:my-library:1.0.0-SNAPSHOT@aar'
      }
    }
  }
  devCompile project(':localLibrary')
//qaCompile 'com.example:my-library:1.0.0-SNAPSHOT@aar' // What I used to do.
  rcCompile 'com.example:my-library:1.0.0@aar'
}

Keep in mind that the task list will not contain dependent task names, so if you aren’t invoking a task that contains your build flavor name, it won’t work. This is just something I got working.

Categories
discuss

Scala testable code with inheritance and mixins

I’ve developed a lot of code in Java and dabbled in Groovy and Haskell which has now led me to Scala.

I feel relatively comfortable with the functional side of Scala, but I’m finding myself a bit shaky on object oriented design in Scala, because it feels a bit different to Java, in particular due to traits/mix-ins.

I aim to write code that is as testable as possible, which in my Java development has always translated into focus on

  • Immutability where possible
  • Prefer injection of state by constructors
  • ALWAYS go for composition instead of inheritance (heavily influenced by, and likely an over-reaction to this post on SO)

Now I’m trying to land on my feet in this new Scala territory, and I’m having a hard time figuring out what approach I should go for here, in particular whether I should start using inheritance for some purposes.

Programming Scala (Wampler and Payne; O’Reilly, 2nd Edition) has a section with considerations (“Good Object-Oriented Design: A Digression”), and I’ve read a number of posts on SO, but I haven’t seen explicit mentions of the design consideration of testability. The book offers this advice on using inheritance:

  1. An abstract base class or trait is subclassed one level by concrete classes, including case classes.
  2. Concrete classes are never subclassed, except for two cases:
    • Classes that mix in other behaviors defined in traits (…)
    • Test-only versions to promote automated unit teting.
  3. When subclassing seems like the right approach, consider partitioning behaviors into traits and mix in those traits instead.
  4. Never split logical state across parent-child type boundaries.

Some digging on SO also suggests that sometimes mix-ins are preferable to composition.

So in essence I have two questions:

  1. Are there common cases where it would be better, even considering testability, to use inheritance?

  2. Do mix-ins offer good ways to enhance the testability of my code?

Answer

The trait usage in the Q/A you referenced was really dealing with the flexibility provided by mixing in traits.

In example, when you extend a trait explicitly the compiler locks the types of the class and the super-class at compile time. In this example MyService is a LockingFlavorA

trait Locking { // ... }

class LockingFlavorA extends Locking { //... }

class MyService extends LockingFlavorA {

}

When you used a typed self reference (as shown in the Q/A you pointed to):

class MyService {
   this: Locking =>
}

.. the Locking can refer to Locking itself, or any valid subclass of Locking. The author then mixes in the locking implementation at the call site, without explicitly creating a new class for that purpose:

val myService: MyService = new MyService with JDK15Locking

I think when they say you can ease testing, they’re really talking about using this functionality to emulate what we Java developers would normally do with composition and mock objects. You simply make a mock Locking implementation and mix that one in during test, and make a real implementation for runtime.

To your question: is this better or worse than using a mocking library and dependency injection? It would be hard to say, but I think in the end a lot of it is going to come down to how well one technique or the other plays with the rest of your codebase.

If you’re already using composition and dependency injection to good effect, I would reckon that continuing with that pattern may be a good idea.

If you’re just starting out and don’t really have the need for all that artillery yet, or haven’t philosophically decided that dependency injection is right for you, you can get you a lot of mileage from mixins for a very small cost in runtime complexity.

I think the true answer will prove to be highly situational.

TL;DR below

Question 1) I think it’s a situationally useful alternative to composition/dep-inj, but I don’t think it provides any major gain other than perhaps simplicity.

Question 2) Yes it can improve testability, largely by emulating mock objects via trait implementations.

Categories
discuss

django: how to pass template variable to javascript onclick routine?

The concept comes from this http://www.prepbootstrap.com/bootstrap-template/real-estate-list-map-dynamic

I enable 2 blocks in a django template, left blockshows device info (device name and location info),right block shows device map location.When user can click on left panels, the right map will change by passing Django template variable to Javascript routine. It seems the passed variable is not accepted by init_map.

when user click on left column, the right map will switch according to latlon, which is passed by onclick routine.

template page is as follows:

{% block content %}
{% for device in devices %}  
<div class="col-xs-6 col-sm-6 col-md-4 col-lg-4 ">    
<div class="row">
    <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 ">
        <div class="panel panel-default"  onclick="init_map( {{ device.coordinates.latitude }}, {{device.coordinates.longitude }} );return false;">
            <div class="row padall">                
                <div class="col-xs-12 col-sm-12 col-md-3 col-lg-3">
                    <span></span>                                                           
                    <img src="{{ device.thumbnail.url }}">
                </div>
                <div class="col-xs-12 col-sm-12 col-md-9 col-lg-9">
                    <div class="clearfix">
                        <div class="pull-left">
                            <span class="fa fa-dollar icon">{{device.name}}</span>
                        </div>
                        <div class="pull-right">
                            {{device.coordinates  }} 
                        </div>
                    </div>
                    <div>
                        <h4><span class="fa fa-map-marker icon"></span>{{ device.coordinates }}</h4>
                        <span class="fa fa-lock icon pull-right">{{  device.coordinates  }}</span>
                        {% with lat_lon=device.coordinates %}       
                         new is   {{ lat_lon }}
                        {% endwith %}
                        </div>                 
                    </div>
                </div>
            </div>
        </div>
   </div>
</div>

<div class="col-xs-12 col-sm-12 col-md-6 col-lg-6">
    <div class="row padbig">  
        <div id="map" class="map"></div>       
    </div>
 </div>
 {% endfor %}
 {% endblock content %}



{% block extra_js %}
<script type="text/javascript"  src="http://webapi.amap.com/maps?v=1.3&key=a23b5e94cecc8e98acd039aba6cd064c"></script>  
<script type="text/javascript">
  var lat_lon  = {{ device.coordinates | js  }};  
function init_map(lat,lon) {

    var imageLayer = new AMap.ImageLayer({
    url:'http://developer.amap.com/wp-content/uploads/2014/06/dongwuyuan.jpg',
        bounds: new AMap.Bounds(  
            new AMap.LngLat(116.327911, 39.939229),
            new AMap.LngLat(116.342659, 39.946275)),

        zooms: [15, 18] 
  });
    var map = new AMap.Map('map',{
           resizeEnable: true,

       scrollWheel: true,

       doubleClickZoom: true, 
       layers: [
           new AMap.TileLayer(),
           imageLayer
       ],

       view: new AMap.View2D({
           //center: new AMap.LngLat(116.342659, 39.946275),
          center: new AMap.LngLat(lat,lon),
           zoom:15
       })
      });  
    }
    //init_map(0);    
</script>
{% endblock %}

if I enabled “center: new AMap.LngLat(116.342659, 39.946275),” the map will show up, while with “center: new AMap.LngLat(lat,lon),” , no map show up.

Answer

If you are passing a coordinate, most probably you have a tuple consisting of latitude and longitude. You must separate them while passing to the Javascript function.

You may try this:

<div onclick=init_map({{ variables.0 }}, {{ variables.1 }})> 
Categories
discuss

android.content.Context.getPackageName()’ on a null object reference

I am working with Fragments which implements an interface.

public class SigninFragment extends Fragment implements SigninInterface 

The interface’s method implementation in the fragment class is as follows.

@Override
public void afterSubmitClicked(String userId, Bundle bundle) {

    Log.d(TAG,"Calling time afterSubmitClicked called"+bundle);
    
    if(!userId.equals("-1")){
        //Logged in successfully
        //Move to MusicHome
        
        Intent mIntent = new Intent(getActivity(),MusicHome.class);
        mIntent.putExtra("SigninFragment.user_details", bundle);
        startActivity(mIntent);
        
    }else{
        //Logging in failed
        //show error dialog
    }
    
}

This method is called after exectuting a AsynchronousTask (which extends AsyncTask) class.

But I am getting crash. And the error message shows

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference

Logcat

   02-14 16:37:04.648: E/AndroidRuntime(28177): Process: com.raaga.android, PID: 28177
02-14 16:37:04.648: E/AndroidRuntime(28177): java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
02-14 16:37:04.648: E/AndroidRuntime(28177):    at android.content.ComponentName.<init>(ComponentName.java:77)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at android.content.Intent.<init>(Intent.java:3996)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at com.raaga.fragments.SigninFragment.afterSubmitClicked(SigninFragment.java:152)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at com.raaga.asynctask.SignInAsyncTask.onPostExecute(SignInAsyncTask.java:92)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at com.raaga.asynctask.SignInAsyncTask.onPostExecute(SignInAsyncTask.java:1)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at android.os.AsyncTask.finish(AsyncTask.java:632)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at android.os.AsyncTask.access$600(AsyncTask.java:177)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at android.os.Handler.dispatchMessage(Handler.java:102)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at android.os.Looper.loop(Looper.java:135)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at android.app.ActivityThread.main(ActivityThread.java:5221)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at java.lang.reflect.Method.invoke(Native Method)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at java.lang.reflect.Method.invoke(Method.java:372)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
02-14 16:37:04.648: E/AndroidRuntime(28177):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

Answer

I have found the mistake what I did. We need to get the activity instance from the override method OnAttach() For example,

public MainActivity activity;

@Override
public void onAttach(Activity activity){
    this.activity = activity;
}

Then pass the activity as context as following.

Intent mIntent = new Intent(activity, MusicHome.class);
Categories
discuss

AngularJS: How to prevent “code flash” in page while loading

I have created a simple app using AngularJS. When I open the page for a second I see the screen below:

enter image description here

However, after the load is complete I see the loaded and styled content which is fine:

enter image description here

How do I prevent the flash of AngularJS code on my page ? Is this related to FOUC ?

Here is the HTML code:

<!doctype html>
<html class="no-js" lang="en" ng-app="MainApp">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Foundation | Welcome</title>
    <link rel="stylesheet" href="css/foundation.css" />
    <script src="js/vendor/modernizr.js"></script>

    <style>
    .row.full-width {
        width: 100%;
        margin-left: auto;
        margin-right: auto;
        max-width: initial;
    }
    </style>

</head>

<body ng-controller="MainCtrl">
    <div class="off-canvas-wrap" data-offcanvas>
        <div class="inner-wrap">
            <nav class="tab-bar">
                <section class="right-small">
                    <a class="right-off-canvas-toggle menu-icon" href="#"><span></span></a>
                </section>
                <section class="left tab-bar-section">
                    <h1 class="title">Salary Calculator</h1>
                </section>
            </nav>

            <aside class="right-off-canvas-menu">
                <ul class="off-canvas-list">
                    <li>
                        <label>Location</label>
                    </li>
                    <li><a href="#">United Kingdom</a>
                    </li>
                </ul>
            </aside>

            <section class="main-section">


                <div class="row full-width">
                    <div class="large-4 columns">

                        <ul class="tabs" data-tab>
                            <li class="tab-title active"><a href="#panel1">Annual Salary</a>
                            </li>
                            <li class="tab-title"><a href="#panel2">Monthly Expenses</a>
                            </li>
                        </ul>
                        <div class="tabs-content">
                            <div class="content active" id="panel1">
                                <div class="row">
                                    <div class="large-12 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Salary" ng-model="salary"/>
                                    </div>
                                </div>
                            </div>
                            <div class="content" id="panel2">
                                <div class="row">
                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Rent" ng-model="rent" />
                                    </div>
                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Wireless, TV, Home Phone" ng-model="telecom"/>
                                    </div>

                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="TV License" ng-model="tv" />
                                    </div>
                                </div>

                                <div class="row">
                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Mobile Phone" ng-model="mobile"/>
                                    </div>
                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Subscription" ng-model="subscription"/>
                                    </div>

                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Electricty" ng-model="electricity" />
                                    </div>
                                </div>

                                <div class="row">
                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Food" ng-model="food"/>
                                    </div>
                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Transport" ng-model="transport" />
                                    </div>

                                    <div class="large-4 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Charity" ng-model="charity"/>
                                    </div>
                                </div>

                                <div class="row">
                                    <div class="large-12 columns">
                                        <input ng-change="calculate()" type="text" placeholder="Other" ng-model="other"/>
                                    </div>
                                </div>

                            </div>
                        </div>

                    </div>
                    <div class="large-8 columns"  ng-cloak >
                        <table >
                       <thead>
                            <tr>
                                <th width="200"></th>
                                <th width="250">Yearly</th>
                                <th width="250">Monthly</th>
                                <th width="250">Weekly</th>
                                <th width="250">Daily</th>
                            </tr>
                        </thead>
                        <tbody ng-repeat="val in results">
                            <tr>
                                <td>{{val.rowType}}</td>
                                <td>{{val.yearly}}</td>
                                <td>{{val.monthly}}</td>
                                <td>{{val.weekly}}</td>
                                <td>{{val.daily}}</td>

                            </tr>
                        </tbody>
                        </table>

                    </div>
                </div>



            </section>

            <a class="exit-off-canvas"></a>

        </div>
    </div>

    <script src="../bower_components/angularjs/angular.js"></script>


    <script src="js/app-service.js"></script>
    <script src="js/app-controller.js"></script>
    <script src="js/app-directives.js"></script>
    <script src="js/app.js"></script>

    <script src="js/vendor/jquery.js"></script>
    <script src="js/foundation.min.js"></script>

    <script>
    $(document).foundation();
    </script>
</body>

</html>

EDIT:

Please see my answer as well for an alternative solution in addition to the accepted one.

Answer

ng-cloak will help to some extent, but you can fully prevent it using ng-bind directive instead of using {{ }}.

e.g.

<td ng-bind="val.monthly"> </td>

not

<td>{{val.monthly}}</td>
Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..