Profile cover photo
Profile photo
Chris Broadfoot
15,226 followers -
Google Developer Relations (Android Maps)
Google Developer Relations (Android Maps)

15,226 followers
About
Chris's posts

Post has attachment
Pumped to talk at Google I/O this year with +Ankur Kotwal.

It's basically a tech talk on how we built Santa Tracker using a lot of the Google developer platform.

There's some great (technical) anecdotes in it, so please come along if you're attending I/O, or watch the recording afterwards on YouTube.

#santatracker #io14  

https://www.google.com/events/io/schedule/session/a578141e-b6bf-e311-b297-00155d5066d7

My dad, on Google driverless cars:
"They should study Thailand: most of the cars here already operate without drivers!!"

Post has attachment
#musicmonday

Classic jazz

Post has attachment
Aperol spritz by Sydney Harbour
Photo

Writing correct concurrent Java code is hard

See if you can spot what's wrong with this code I came across today, simplified here*:

class Foo {
Boolean myFlag = Boolean.valueOf(false);

void foo() {
  synchronized(myFlag) {
    ...
    myFlag = Boolean.valueOf(true);
  }
}

void bar() {
  synchronized(myFlag) {
    myFlag = Boolean.valueOf(false);
  }
}

Let me first provide a brief explanation of how the synchronized statement works in Java. Every Object has an intrinsic lock associated with it. The synchronized statement obtains the lock associated with the object, runs the code inside the block, then releases the lock.

In this case, the synchronized statement obtains the lock associated with the object in the "myFlag" field. The programmer has recognized that you can't lock over a primitive type (boolean), so has opted to use Boolean (which is a subclass of Object).

There are two things wrong in this example:
1) the value of the "myFlag" field is reassigned. In this case, it has one of two values: Boolean.TRUE and Boolean.FALSE.
2) if any code running in any thread also locks over either of these easily accessible values, the code running from this class is affected.

Three rules to prevent this mistake in your own Java code:
1) If possible, use synchronized methods instead of synchronized statements (they're simpler)
2) Only lock over fields marked as final, or the "this" object.
3) Create separate lock objects for fields that need this block, and in your source file, write a comment stating that as a contract. For example:
private final Object myFlagLock = new Object();
private boolean myFlag = false; // must synchronize on "myFlagLock".

In this case, an AtomicBoolean would work quitenicely, too:
private final AtomicBoolean myFlag = new AtomicBoolean(false);
synchronized(myFlag) {
   myFlag.set(true);
   ...
}

I've noticed that IntelliJ provides an inspection for this simple mistake. I can't recommend IntelliJ enough.

Read more about the synchronized statement/block here:
http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Get the fantastic "Java Concurrency in Practice" book by +Joshua Bloch and others:
http://amzn.com/0321349601

* Full code was from the Pebble SDK examples, found here: http://goo.gl/CDxPMA

#java   #concurrency  

Post has attachment
Sydney sunrise #pano
Photo

Post has shared content
Fans of lipids and cutlery rejoice, Butter Knife v5.0 has been released! Read on and learn about what's new:

@InjectViews
Views are frequently operated on in groups as a result of some event. Text views animate in on new screens, input fields are enabled and disabled for network calls, etc. Group multiple views together using the @InjectViews annotation into a List or array for easy operation.

  @InjectViews({ R.id.first_name, R.id.last_name })
  List<TextView> nameViews;

ButterKnife.apply
Coupled with the aforementioned annotation to aggregate views, apply provides a concise way to operate on those groups of views at once.

  ButterKnife.apply(nameViews, DISABLE);
  ButterKnife.apply(nameViews, ENABLED, false)

The Action[1] and Setter[2] interfaces provide easy ways to define operations.

  static final Action<View> DISABLE = new Action<>() {
    @Override public void apply(View view, int index) {
      view.setEnabled(false);
    }
  }
  static final Setter<View, Boolean> ENABLED = new Setter<>() {
    @Override public void set(View view, Boolean value, int index) {
      view.setEnabled(value);
    }
  }

You can use Android's Property[3] with apply as well.

  ButterKnife.apply(nameViews, View.ALPHA, 0);

New multi-callback listeners
* @OnItemSelected for AdapterView.OnItemSelectedListener's onItemSelected callback.
* @OnPageChange for ViewPager.OnPageChangeListener's onPageChange callback.
* @OnTextChange for TextWatcher's onTextChange callback.

Each of these new listeners have multiple callback methods. Change which callback your method is being bound to by supplying a callback argument.

  @OnItemSelected(R.id.list)
  void onItemSelected(long id) {
    // ...
  }

  @OnItemSelected(value= R.id.list, callback = NOTHING_SELECTED)
  void onNothingSelected() {
    // ...
  }

Enjoy! And #DeathToBoilerplate !

* Website: http://jakewharton.github.io/butterknife/
* Changelog: https://github.com/JakeWharton/butterknife/blob/master/CHANGELOG.md
* Javadoc: http://jakewharton.github.io/butterknife/javadoc/


[1]: http://jakewharton.github.io/butterknife/javadoc/butterknife/ButterKnife.Action.html
[2]: http://jakewharton.github.io/butterknife/javadoc/butterknife/ButterKnife.Setter.html
[3]: https://developer.android.com/reference/android/util/Property.html

Post has shared content
Next time you're in India, find your way around popular malls and shopping centres more easily with indoor #GoogleMaps

See where indoor maps are available: goo.gl/TJ15mL.

iPhone users: Get the app at goo.gl/4oENi.
Photo

Post has shared content
I hosted two interns this summer with +Anthony Morris  - check out their awesome work :-)
Marker clustering and heatmaps on Android
Check out new ways to visualize large amounts of geo data in your Android app. Read through the blog post for more info!

Post has shared content
Hansel. So hot right now
Wait while more posts are being loaded