I was a bit dismayed that for a device not even a year old that these were my options. I was mulling over the options, and I flipped the watch over to see what tools I would need to take the watch apart (who doesn't like disassembling electronics), when I notice that the contact points on the watch were filthy (as one the NCOs on my infantry course used to say when inspecting rifles – "crud, corruption, and communism"). You can see the contacts for the charging dock right in the picture below:
I figured cleaning these contact points was easier than taking the watch apart and quicker than sending the watch back, so I grabbed an eraser and gave the contacts a quick scrub. I plugged the watch back into the charging cradle, and all of a sudden it started charging again.
I've had to do this a couple of times now. I recently found out that some erasers may leave a thin film of residue that may attract dirt. There are a couple of options available:
Anybody else experienced this problem with their watch? What solutions did you use?
]]>Just a warning - Android data binding is still a beta product, so as such things may or may not work when they should, as they should, and the documentation may or may not be accurate.
There were several steps/phases that I went through while I was learning this. Here's what I did:
The source code for this sample is up on Github.
First off, make sure you're running Android Studio 1.3 or higher. As long as you're keeping current with the Android Studio
Next I had to edit the project's build.gradle file, my dependencies
section looks like this:
dependencies { classpath 'com.android.tools.build:gradle:1.3.1' // TODO: when the final verison of dataBinder is release, change this to use a version number. classpath 'com.android.databinding:dataBinder:1.+'}
After that, I updated the build.gradle for the app module. The first two line in the file are:
apply plugin: 'com.android.application'apply plugin: 'com.android.databinding'
That's pretty much about it. Now that our project is aware of data binding, let's see about the code and UI changes I had to make.
From here, you might be best off reading Google's docs on data binding, just to get a feel for how things work. If you're familiar with data binding in XAML (say WPF or Xamarin.Forms), you might notice some simularities.
(Allow me digress a bit and offer this piece of advice again: think twice about binding directly to your data model. This is a perfect opportunity to bring some Model-View-ViewModel goodness into your Android application. I'm not going to talk to much about MVVM though.)
To keep my UI as code free as possible, I abstracted much of the data binding logic into the following class (his isn't all the code, just the parts relevant for this example):
1 | public class PhonewordViewModel extends BaseObservable { |
Here I've encapsulated logic into a view class that subclasses BaseObservable
. Subclassing isn't mandatory – a naked POJO will work too. However, by making a custom view BaseObservable
provides the infrastructure for setting up the data binding; and this custom view class can notify registered listeners as values change. As well, POJO's should be kept as dumb as possible without any intricate knowledge of views. By sticking the data binding logic in a view class like this I, honour the whole "separation of concerns" concept.
Notice that the getters are adorned with the @Bindable
annotation - this identifies how the listeners should retrieve values from the properties.
It's the responsibility of the bound class to notify clients when a property has changed. You can see this happening with the use of notifyPropertyChanged
. This causes a signal to be raised to listeners; this is how they find out the name has changed.
The BR
class is generated by the data binding library. It is to data binding what the R
class is to layout files. Each POJO field or method adorned with @Bindable
will have a constant declared in the BR
class at compile time corresponding to the name. So, getPhoneNumber()
becomes BR.phoneNumber
.
With the code out of the way, it's time to update the layout.
There were a couple of changes that I needed to make to my existing layout for things to work:
Android's data binding requires that <layout>
be the root element of the layout. My old layout started with a <LinearLayout>
. It's also necessary to add a <data/>
section that will declare variables and the classes that will be bound to.
We need to declare a variable that the data binding framework can... bind too. I had to add a <data>
element with a child <variable>
element that names the variable and identifies the type Android should use for the binding:
1 | <layout xmlns:android="http://schemas.android.com/apk/res/android" |
This declares a variable phonewordVM
that I can use inside my layout file.
Notice that the xmlns:app="http://schemas.android.com/apk/res-auto"
will automatically drag local namespaces into your XML. This helps you out a bit because you don't have to explicitly declare all the namespaces in layout file.
Next, I need to set up the binding. In this example, all I want to do is to bind setPhoneWord()
/getPhoneWord()
in my custom view class to an EditText
. This little XML snippet shows the binding in action:
1 | <EditText |
Notice the syntax to declare the binding: @{phonewordVM.phoneWord}
– this is how I setup the binding in the layout file. With this in place, the last thing to do is to setup the data binding in the activity.
Finally, setting up the data binding. This is a very minimal amount of code. We no longer have to first get a reference to a view, access properties on the view, and then manually transfer the value of that view to some domain object or variable in our application. Android Data Binding takes are of all that for me.
Below is a snippet from the fragment:
1 |
|
There are a couple of key things to notice here. First, observe that the fragment inflates a view called fragment_main.xml
. The data binding library generates the code of a class called FragmentMainBinding
. The name of the binding class is derived from the name of the layout file, with the work Binding
appended to it.
Once the binding is instantiated, I tell it what object to bind to. The data binding library created a setter called setPhonewordVM
– this is because we declared the variable phonewordVM
in our layout file above.
Another interesting thing is that the code for the fragment does not use findViewById
or hold a reference to any of the views layout. That is because the FragmentMainBinding
has those references. So, for example, if I want to get the value of an EditText
with the id +@id/phonewordText
, then mBinding.phonewordText.getText()
will do the trick.
I set the OnClickListener
for the buttons in a very traditional way. In theory, the data binding library should allow to bind event listeners to methods on a view model. However, I have't been able to get that to work yet. Hopefully I'll have more luck next version of the data binding library (and/or an update to the docs for the data binding library)
With all this, data binding has been accomplished. It may seem like a lot of code, and perhaps it is for such a trivial example. Where the true power of this comes into play is when you want to write tests for your code. Two way data binding lays the framework for the Model-View-View Model pattern, which in turn helps you create a loosely coupled app that is easier to test.
]]>The whole idea behind containers is to isolate an application in a known environment. This helps prevent strange interactions with other software or libraries installed as well. I think Docker has the best, concise description of what containers are:
Containers running on a single machine all share the same operating system kernel so they start instantly and make more efficient use of RAM.
and
... containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in.
So, while both containers and virtual machines provide isolation, they differ in how they do it. VM's will emulate the hardware; each VM thinks it's a computer with it's own CPU's, RAM, hard disk, kernel, etc. This isolation is provided by the virtualization host which runs on the hardware.
Containers, on the other hand, have a "host" that uses some kernel extensions to isolate software, but otherwise everything is running on the hardware. Containers share the host computer's RAM, CPUs, and even the kernel, however each container is secluded from the others and the host operating system. Because of this, containers can startup much faster and appear to be more responsive – they don't have to talk to a middle man to get access to the hardware.
Most modern Linux distros ship with somee extensions to support containers out of the box, so, in theory, you can just dive right and start creating containers without having to do anything extra on Linux.
In practice it's easier to use something like Docker to create and manage your containers. Docker also provides a way to share containers via DockerHub. You search DockerHub for something you need, like say Mono, and then you grab the Dockerfile (a recipe that tells Docker how to build the container), and away you go. Alternately, you can create your own custom Docker images based on an existing Dockerfile. It's kind of like subclassing a container, if you will.
]]>