Dart for Java developers: putting it all together

Welcome back to my small series of posts about Dart for Java developers. In the previous installment I promised to actually use the Model class soon. A very simple scenario can be seen in the file main2.dart. If main2.dart is invoked from the command line, one must pass exactly three arguments:

  1. input temperature unit
  2. value of the input temperature
  3. output temperature unit
The program is quite simple. We have two import statements as we need both model.dart and converter.dart. The first one gives us (among other things) the definition of a class named Model. We instantiate it using the familiar new keyword. After that we set the unit for both input and output temperature. enumFor() is a top-level function defined in model.dart. It checks if one of the enum values ends with the string passed as the only formal parameter. Remember that we pass them to the program via the command line. So to satisfy the string comparison, we need to enter exactly degreesCelsius, degreesFahrenheit or kelvin.

The temperature value itself is converted from String to double through stringToDouble(). This function can be found in converter.dart. It uses an internationalization package named intl. This package is capable of honoring locale-specific settings like the decimal mark and the thousands separator. My example explicitly sets the locale to German, which means that english 1,234.56 has to be entered as 1.234,56. Feel free to experiment with this. Why not reading the name of the locale from the command line?

Once the model has been set up, calculateOutTemperature() can be called to do the actual computation. After that, the result can be printed from the getter outTemperatureAsString(). Dart has first-class support of getters and setters, so no method parenthesis are needed.


Dart for Java Developers: The Model class

In my previous post, Dart for Java Developers: Into the code, we looked at two Dart source files, converter.dart and main.dart. Both contained so-called top level functions, that is, making code available without the need to put it in a class. Recall that each Dart file is a library. A library with a top level main() function is a script. Libraries are combined or grouped to form so-called packages. Packages can be easily distributed and reused. The Dart SDK comes with a package and asset manager called pub. Packages are described in a specification file named pubspec.yaml. It consists of, among other entries, a name, a version and a list of dependencies. For example, Temperature Converter relies on the internationalization package intl. A package can live anywhere. Some packages are on GitHub. Others reside at pub.dartlang.org. You can publish your packages there, too. Here is a description what you need to do: https://www.dartlang.org/tools/pub/publishing. The pub tool is invoked either through the plugin of your IDE (if you open a pubspec in IntelliJ you get a commands list at the top of the editor window), or from the console. If you fancy the shell, remember to include /bin in your PATH environment variable.

Now, let's turn to code. Recall that my original Temperature Converter app was written in Java using JavaFX. There is a Model class that uses Converter. So, Model has both state and behavior. The class is used as follows:

  1. Instantiate it
  2. Set the domain data (unit of input and output temperature and the temperature itself)
  3. Perform the calculation
  4. Grab the output string
  5. Back to 2.

Let's see how this looks like in Dart. We start with a library statement (which gives the library a name), followed by an import. We rely on the converter library you have encountered in the previous post. After that you see an enum definition. Compared to, for example Java, Dart enums allow less customization. Currently the string representation of the enum evaluates to enum_name.enum_value. To be able to more easily map user interface elements to enum values (you will see that later) I implemented a convenience method named enumFor(). Dart enums cannot be defined inside classes. Now let's take a look at the Model class (it's inside model.dart). Besides the lack of access level modifiers (more on that soon) the code looks comfortingly familiar. With two very welcomed exceptions. Have you spotted the get and set keywords? Dart has language level support for getters and setters.

In the next installment we will actually use the new Model class. But if you cannot wait to try it out, just grab the code from GitHub and start playing.


Dart for Java Developers: Into the code

In a previous post, Dart for Java Developers: First Contact I offered you a glimpse at the language by creating a very basic project using the project creation wizard of IntelliJ IDEA. Today I would like to dig a little deeper by showing you how to rewrite a Java program in Dart. I will use a small temperature conversion app which I wrote for a series of talks about Java on mobile devices. You can find the JavaFX version on GitHub.

The program consists of four classes, a user interface definition and a resource bundle. TemperatureConverter is the main class. It loads the ui from an fxml file and instantiates a controller class called FXMLDocumentController. This controller binds ui components and actions to a model class named Model. This class holds the actual domain data and invokes code from the Converter class. It contains a couple of static methods that do the actual temperature calculation. Let us start with this one.

As you can see in the source, although doing different computations, the innards of the methods are mostly the same, that is, doing some arithmetics using the primitive double data type. The method stringToDouble() converts a string to a double value honoring locale specific settings like the decimal mark and the thousands separator. doubleToString() creates a string consisting of a double value with its fractional part omitted if it is zero, and a suffix. How could we do this in Dart?

For your convenience I set up a GitHub repository. Please take a look at converter.dart. Possibly to a bit of a surprise, it does not contain a class, but several top level functions. unitDegreesCelsius, unitDegreesFahrenheit and unitKelvin are compile time constants. _f is declared final, so its value can be assigned only once, but obviously not during compile time. I really like the compact function definition using =>, which takes an expression. If more statements are needed, the traditional body using curly braces comes into play. Also very nice is the string interpolation you can see in _doubleToString(). You can access the value of an expression inside a string by using ${expression}. If the expression is an identifier, the {} can be omitted.

To see the calculations in action I have provided main.dart. If a dart file contains a toplevel main()-function it is called a script. The following screenshot shows the execution of the program in Visual Studio Code.
Editing and running the script in Visual Studio Code

Dart programs and libraries are often distributed as packages. Packages follow certain rules regarding structure and content. You can see a bit of this in the screenshot. I might go into a little more detail in a future post. The json file you can see in the screenshot is not part of that package but helps running the program in Visual Studio Code. Want to try for yourself? Great. Just clone the repo and start playing.


TKWeek 1.9.0 released to Google Play

It has been far too long since I last updated TKWeek. Finally, 1.9.0 is now available in the Play store. A remarkable new feature, in fact the hightlight of this version, are notifications about upcoming events. Here is how this looks like:

Summarized notifications on Android 7.1

Expanded notifications on Android 7.1

The notifications are bundled notifications on Android 7.1. Older versions show the traditional bigview notifications, which unfortunately cannot be expanded.

Android Wear knows stacked notifications. Here is how this looks like:

Partly visible notification

Collapsed notification stack

Expanded notification stack