<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Daniele Campogiani</title>
		<description>Daniele Campogiani</description>
		<link>https://danielecampogiani.com/blog/</link>
		<atom:link href="https://danielecampogiani.com/blog/feed.xml" rel="self" type="application/rss+xml" />
		
			<item>
				<title>Card Scanner on Android using CameraX and MLKit</title>
				<description>&lt;p&gt;Having to insert card details manually into an app could be a pain for users, but thanks to CameraX and MLKit, we can easily add a scanning feature in our app with minimal effort.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;camerax&quot;&gt;CameraX&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://developer.android.com/training/camerax&quot;&gt;CameraX&lt;/a&gt; is a Jetpack library to use camera APIs with device compatibility issues already handled for us and with lifecycle support.&lt;/p&gt;

&lt;p&gt;The library is based on uses cases and we are going to use two of them: Preview and Image Capture.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 id=&quot;library-setup&quot;&gt;Library Setup&lt;/h4&gt;

&lt;p&gt;For this post, we are going to use the following dependencies:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/c363e7a0ec0f3768207235deaccdf7b6.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 id=&quot;preview&quot;&gt;Preview&lt;/h4&gt;

&lt;p&gt;This use case will allow us to display on-screen what the camera is capturing in real-time.&lt;/p&gt;

&lt;p&gt;To do so, we need to add androidx.camera.view.PreviewView to our layout:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/adf7fdce76ff7fe6efad966354e22467.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Then in code, we can build the Preview use case as follows:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/c4ab58963843d472d9b0742f56c1007d.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;To run our use cases we need a CameraProvider and a CameraSelector, I’ve created some extension using Kotlin Coroutines to get a CameraProvider:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/ba31f3dce3dee62c1fe24850e096ce4e.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;While for the CameraSelector this is all we need:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/ab9356ece505656b21af79bfc0e2b5ca.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;We can now bind our use cases in this way:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/673d3c718728e256835050614ab51c79.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 id=&quot;image-capture&quot;&gt;Image Capture&lt;/h4&gt;

&lt;p&gt;This is another CameraX use case, and the setup is pretty similar to the previous one.&lt;/p&gt;

&lt;p&gt;We can create the use case in this way:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/f92b8dbe6f1b1d6e1549cc99c257b51f.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;It’s time to update our bindUseCases method and also use this new one, but since CameraX is using a callback, and we would like to use
kotlin coroutines let’s add a convenient extension method:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/45310c066867e20cb91024de8ab3a411.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Now we can update bindUseCases function like the following:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/e9dcc7d3aa216684c103ad34cafd9e20.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;mlkit&quot;&gt;MLKit&lt;/h3&gt;

&lt;p&gt;Now that we have our image is time to extract data from it. For this purpose, we are going to use &lt;a href=&quot;https://developers.google.com/ml-kit/vision/text-recognition&quot;&gt;MLKit Text Recognition.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 id=&quot;library-setup-1&quot;&gt;Library Setup&lt;/h4&gt;

&lt;p&gt;We need to add this dependency :&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/039730c31c3e3d7b6a049ad8dd0893f5.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;and update our Manifest to download the ML model to the device after our app is installed:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/880a645f3e5fab52001ab5b75ec44237.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Let’s create an ExtractDataUseCase to encapsulate the MLKit integration:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/d0dcbf2953bf9161ac3b1e4e5d95e19d.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;In this use case, we are accepting an instance of TextRecognizer that could be retrieved with &lt;code&gt;TextRecognition.getClient().&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To extract data from our image we first need to transform it into something MLKit can understand. Luckily for us, there is the
&lt;code&gt;InputImage.fromMediaImage(image, rotationDegrees)&lt;/code&gt; fatory method designed just for that.&lt;/p&gt;

&lt;p&gt;Now that we have an image MLKit can understand we can pass it to our textRecognizer and await the text result.&lt;/p&gt;

&lt;p&gt;Once again, we are using Kotlin coroutines so we can use &lt;a href=&quot;https://github.com/dcampogiani/CreditCardScanner/blob/4255757dead02cd472b98ac0249a64b59fc11a47/app/src/main/java/com/danielecampogiani/creditcardscanner/utils/TaskExtensions.kt#L18&quot;&gt;this extension&lt;/a&gt; as a bridge from Task (returned by textRecognizer) and our suspend method.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;data-extraction&quot;&gt;Data Extraction&lt;/h3&gt;

&lt;p&gt;Thanks to CameraX we got the image, and then thanks to MLKit we were able to extract the text on it.
Now is our turn to do some minimal logic and pass from raw data to some useful information.&lt;/p&gt;

&lt;p&gt;As a first step let’s define what we can extract from the image, and create a data class:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/adec3a13f37b58c930212804ac388a02.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;All fields are optional because I have several (debit) cards and on each of them I have a different layout, some of them have the owner
on the same side of the number, some of them no.&lt;/p&gt;

&lt;p&gt;Same for the expiration date, so ¯_(ツ)_/¯.&lt;/p&gt;

&lt;p&gt;Now we can encapsulate our data extraction logic inside a Kotlin Object:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/c69ce11196c83f68c88fba88084d8429.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Let’s extract some data:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/4eae9a66f18ae039991bd8368479846f.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Here the rationale is to try to get the string that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;contains at least a space char (between name and surname)&lt;/li&gt;
  &lt;li&gt;contains no digits (I think you can’t have them in a name)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we have more than one match, choose the longest one.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/da5ea7ce965c3d9d94fd22326ec34534.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;For the number, we are picking the first line that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;has at lease a space (between numbers)&lt;/li&gt;
  &lt;li&gt;has all the chars as digits&lt;/li&gt;
&lt;/ul&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/eb525de334e504cd1976acedd386035a.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Expiration could be something like 08/20 or, 08/2020 this is why I’m choosing the line with&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;5 chars (like 08/20) o 7 chars (like 08/2020)&lt;/li&gt;
  &lt;li&gt;’/’ as third char&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have found the expiration line we need to separate the month from the year&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/23ef44ae1ef274dca181d572cf6e733d.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;final-touches&quot;&gt;Final touches&lt;/h3&gt;

&lt;p&gt;We can now update the activity to use our ExtractDataUseCase&lt;/p&gt;

&lt;p&gt;Let’s create it&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/16b52e35a46501689edd927306b8978d.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;And then use it&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/4815bb1cc7800c401a41f40ac827bb8c.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;We can now finally bind our result to UI:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/b29ddfaf2d418688e489f2992224f448.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;That’s all folks!
You can find the complete source code at &lt;a href=&quot;https://github.com/dcampogiani/CreditCardScanner&quot;&gt;https://github.com/dcampogiani/CreditCardScanner&lt;/a&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 15 Aug 2020 08:00:00 +0200</pubDate>
				<link>https://danielecampogiani.com/blog/2020/08/card-scanner-on-android-using-camerax-and-mlkit/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2020/08/card-scanner-on-android-using-camerax-and-mlkit/</guid>
			</item>
		
			<item>
				<title>Use GitHub Pages and kscript to host and validate static JSON API</title>
				<description>&lt;p&gt;In Bologna, we have a &lt;a href=&quot;http://bit.ly/32VyE3w&quot;&gt;community about Functional Programming&lt;/a&gt;, and lately, I was looking for a quick and easy way to host all the data of the talks.&lt;/p&gt;

&lt;p&gt;In this post, we will see how we can use GitHub pages to host the JSON files, and kscript to validate the data before “deploy”.&lt;/p&gt;

&lt;h3 id=&quot;github-pages&quot;&gt;Github Pages&lt;/h3&gt;

&lt;p&gt;GitHub Pages is a quick way to host data for free so why don’t we use it also to store some static JSON and use it as API in an app?&lt;/p&gt;

&lt;p&gt;To use it we just need a Github repo and enable the feature as explained in &lt;a href=&quot;https://pages.github.com/&quot;&gt;this guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once done we can push the JSON file and it will be hosted for us for free.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;file in a git repo: &lt;a href=&quot;https://github.com/fp-in-bo/data/blob/master/events/all.json&quot;&gt;https://github.com/fp-in-bo/data/blob/master/events/all.json&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;same file hosted by GitHub Pages: &lt;a href=&quot;https://fp-in-bo.github.io/data/events/all.json&quot;&gt;https://fp-in-bo.github.io/data/events/all.json&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 id=&quot;kscript&quot;&gt;kscript&lt;/h4&gt;

&lt;p&gt;Kscript will bring enhanced scripting support for Kotlin on *nix-based systems, so we can use it fo validate our data before deploying it.&lt;/p&gt;

&lt;p&gt;After a quick &lt;a href=&quot;https://github.com/holgerbrandl/kscript#installation&quot;&gt;installation&lt;/a&gt; we can start to write our validation script.&lt;/p&gt;

&lt;p&gt;To write our first kscript here’s what we need to do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;create empty file&lt;/p&gt;

    &lt;p&gt;&lt;code&gt;touch script.kts&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;make a script automatically install kscript and its dependencies on the first run if necessary&lt;/p&gt;

    &lt;p&gt;&lt;code&gt;kscript --add-bootstrap-header script.kts&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;open the script with some IDE / text editor (I’ll use IntelliJ)&lt;/p&gt;

    &lt;p&gt;&lt;code&gt;kscript --idea script.kts&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;write our logic&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kscript allows us to use dependencies, so we’re going to use Jackson in this example.
To add the dependency in our script we just need to declare it directly inside the script like following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;//DEPS com.fasterxml.jackson.module:jackson-module-kotlin:2.10.1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In this example we are going to read a file from arguments, then parse it using Jackson, here is the full &lt;a href=&quot;https://github.com/fp-in-bo/data/blob/master/scripts/validateJson.kts&quot;&gt;script&lt;/a&gt;:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/f0d2f182f0397c779d23c28cf9ef0c97.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Another feature of kscript is to create standalone binaries, let’s do it because we’re gonna use it in our continuous integration:&lt;/p&gt;

&lt;p&gt;kscript –package script.kts&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 id=&quot;continuous-integration&quot;&gt;Continuous Integration&lt;/h4&gt;

&lt;p&gt;Our desired flow to publish a new talk to the repo is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;open a new branch&lt;/li&gt;
  &lt;li&gt;add a talk into the JSON&lt;/li&gt;
  &lt;li&gt;open a PR&lt;/li&gt;
  &lt;li&gt;waiting for checks in Continuous Integration&lt;/li&gt;
  &lt;li&gt;merge the PR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way once the PR will be merged to master, the new talk will be available in our API.
In this repository, I’m using Travis for CI, and all we need is to invoke our script passing the right file&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scripts/validateJson events/all.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;That’s all.
I find this approach and the mix of these two tools pragmatic and I suggest this approach if you need to host some data that will not change very frequently. &lt;a href=&quot;https://github.com/fp-in-bo/data&quot;&gt;You can find here the repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks &lt;a href=&quot;https://twitter.com/FChiusolo/&quot;&gt;@FChiusolo&lt;/a&gt; for the fish.&lt;/p&gt;

</description>
				<pubDate>Thu, 12 Mar 2020 07:00:00 +0100</pubDate>
				<link>https://danielecampogiani.com/blog/2020/03/use-github-pages-and-kscript-to-host-and-validate-static-json-api/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2020/03/use-github-pages-and-kscript-to-host-and-validate-static-json-api/</guid>
			</item>
		
			<item>
				<title>Android Functional Validation 4 - Validated</title>
				<description>&lt;p&gt;This is the last post of the &lt;a href=&quot;/blog/2018/02/android-functional-validation-1-intro/&quot;&gt;Functional Validation&lt;/a&gt; serie and we are going to use Validated, our last data type.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://arrow-kt.io/docs/datatypes/validated/&quot;&gt;Validated&lt;/a&gt; is like Either with some additional power, and using it we can finally aggregate all errors and give proper feedback to our users.&lt;/p&gt;

&lt;h3 id=&quot;lets-use-validated&quot;&gt;Let’s use Validated&lt;/h3&gt;

&lt;p&gt;Like Either, Validated will contain two possible values, one when the data is invalid, and one when the data is valid. But this time we are going to use different types.&lt;/p&gt;

&lt;p&gt;We will use&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;Validated&amp;lt;Nel&amp;lt;ValidationError&amp;gt;, String&amp;gt;&lt;/code&gt; for email&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;Validated&amp;lt;Nel&amp;lt;ValidationError&amp;gt;, String&amp;gt;&lt;/code&gt; for phone numbers&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;Validated&amp;lt;Nel&amp;lt;ValidationError&amp;gt;, Data&amp;gt;&lt;/code&gt; for the whole form&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ValidationError is a sealed class used to define all possible errors:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/24bc1899fe7c16888f18aa9736a3f249.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;And Nel is a &lt;a href=&quot;http://arrow-kt.io/docs/datatypes/nonemptylist/&quot;&gt;NotEmptyList&lt;/a&gt; that will aggregate errors.&lt;/p&gt;

&lt;p&gt;Validated has two possible values: Valid and Invalid and we will use the as following:&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 id=&quot;mail&quot;&gt;Mail&lt;/h4&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Validated1.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Validated2.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h4 id=&quot;phone-number&quot;&gt;Phone Number&lt;/h4&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Validated3.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Validated4.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Once again we will use kotlin extension methods invoking &lt;a href=&quot;/blog/2018/02/android-functional-validation-1-intro/&quot;&gt;validMail and validNumber functions we have discussed in the first post&lt;/a&gt; to build our instances.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/4f4221b3f149448feddb47234f0edbf2.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;if the validation function returns true we will wrap the value using the .valid() method, otherwise we will create a Nel with the correct error and wrap it using the .invalid() method.&lt;/p&gt;

&lt;h3 id=&quot;map-them&quot;&gt;Map them&lt;/h3&gt;

&lt;p&gt;By now we are experts of map, let’s use it&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/b1a3213da53deee236b7d058caae5235.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Using Validated our map finally has the desired behaviour and we get all input errors in the list:&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Validated5.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;android-ui&quot;&gt;Android UI&lt;/h3&gt;

&lt;p&gt;In our ViewModel we will use the previously discussed code to update a &lt;code&gt;&amp;lt;Validated&amp;lt;Nel&amp;lt;ValidationError&amp;gt;, Data&amp;gt;&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/54610009571b9c6628774d35818842ec.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;In the activity we retrieve the viewModel, register click listener and observe the result of the validation. Once we get the result we clear previous errors and then fold it.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/21671e076f123f981053b0034721d469.js&quot;&gt; &lt;/script&gt;

&lt;h4 id=&quot;fold&quot;&gt;Fold&lt;/h4&gt;

&lt;p&gt;Once again we are using method reference with the following methods:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/0c04304d56f6b27252296297a3490096.js&quot;&gt; &lt;/script&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/f390917f58a77a145d4cadede8c7ec25.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;In the invalid path we using kotlin &lt;code&gt;when&lt;/code&gt; to find the correct error message and TextInputLayout to notify the user, while in the valid path we just show data to user.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/dcampogiani/AndroidFunctionalValidation/pull/4&quot;&gt;You can find here the implementation using Either&lt;/a&gt;&lt;/p&gt;
</description>
				<pubDate>Sat, 10 Feb 2018 23:16:01 +0100</pubDate>
				<link>https://danielecampogiani.com/blog/2018/02/android-functional-validation-4-validated/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2018/02/android-functional-validation-4-validated/</guid>
			</item>
		
			<item>
				<title>Android Functional Validation 3 - Either</title>
				<description>&lt;p&gt;&lt;a href=&quot;/blog/2018/02/android-functional-validation-2-option/&quot;&gt;In the previous post&lt;/a&gt;  we saw the limitations of using Option and in this post we are going to solve them choosing a different data type.&lt;/p&gt;

&lt;p&gt;The issue with option was that when something goes wrong we have no information about the failure. We just know that our expected value is missing.&lt;/p&gt;

&lt;p&gt;So we need a data type that holds some representation of the result of a failed execution. This data type is called &lt;a href=&quot;http://arrow-kt.io/docs/datatypes/either/&quot;&gt;Either&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Option was like a box that could contain a value, Either instead is a magic box that can contains a value of a type or another value of an other type.&lt;/p&gt;

&lt;p&gt;By conventions those two possible values are called Left and Right, and usually we store the error in the left and the correct value in the Right.&lt;/p&gt;

&lt;h3 id=&quot;lets-use-either&quot;&gt;Let’s use Either&lt;/h3&gt;

&lt;p&gt;Like we did for Option, we are going to use one Either to represent the mail, one Either to represent the phone number and then we will &lt;em&gt;merge&lt;/em&gt; them to obtain the output of our validation&lt;/p&gt;

&lt;p&gt;In our representation we will use Right to wrap valid input and Left to wrap invalid input, so for example:&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Either1.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Once again to obtain such behaviour we can use kotlin extension methods invoking &lt;a href=&quot;/blog/2018/02/android-functional-validation-1-intro/&quot;&gt;validMail and validNumber functions we have discussed in the first post&lt;/a&gt;&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/f802341c805f30a1cdb0e3759dfbd695.js&quot;&gt; &lt;/script&gt;

&lt;h3 id=&quot;map-them&quot;&gt;Map them&lt;/h3&gt;

&lt;p&gt;We have already discusse how map works in &lt;a href=&quot;/blog/2018/02/android-functional-validation-2-option/&quot;&gt;the previous post&lt;/a&gt;, so let’s use it:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/8876147299beeff1c5d729dd029b087e.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;String&amp;gt;&lt;/code&gt; you are reading in the code is needed because we are using Strings to model errors.
Using valid mail and phone number the output will be:&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Either2.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;But the improvement compared with Option is that now we can also understand what goes wrong, so if we provide and invalid mail:&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Either3.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;or an invalid phone number:&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Either4.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;We finally have something to show to the user when he’s giving us wrong data!&lt;/p&gt;

&lt;p&gt;Cool, but…&lt;/p&gt;

&lt;h3 id=&quot;either-limits&quot;&gt;Either limits&lt;/h3&gt;

&lt;p&gt;What happens when all inputs are wrong?&lt;/p&gt;

&lt;p&gt;Map implementation of Either will give us just the first error, we don’t have (yet) a way to accumulate errors.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Either5.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;android-ui&quot;&gt;Android UI&lt;/h3&gt;

&lt;p&gt;Let’s update our android form to use Either.&lt;/p&gt;

&lt;p&gt;In our ViewModel we will use the previously discussed code to update a &lt;code&gt;LiveData&amp;lt;Either&amp;lt;String, Data&amp;gt;&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/a91242dd045dec5c06a51a0303886a1f.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;In the activity we retrieve the viewModel, register click listener and observe the result of the validation. Once we get the result we fold it.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/1eb74b2125073ac8a2f6cfcb5c580df4.js&quot;&gt; &lt;/script&gt;

&lt;h4 id=&quot;fold&quot;&gt;Fold&lt;/h4&gt;

&lt;p&gt;Once again we are using method reference with the following methods:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/68962a658ad3ea54b19b4e34f40bfe62.js&quot;&gt; &lt;/script&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/38f2be2734328f7dc359b0d9dea4d26f.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;This time we are getting an input in each method, in the first one we are getting a String that represents the error, while in the second we are getting the value of the Right, a Data instance in our implementation.&lt;/p&gt;

&lt;p&gt;But, as previously discussed, if the user will give us multiple invalid inputs we will notify him just the first error, so Either is not a great choice for validation.&lt;/p&gt;

&lt;p&gt;In the &lt;a href=&quot;/blog/2018/02/android-functional-validation-4-validated/&quot;&gt;next post&lt;/a&gt; we will use our last data type that will solve all our problems!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/dcampogiani/AndroidFunctionalValidation/pull/2&quot;&gt;You can find here the implementation using Either&lt;/a&gt;&lt;/p&gt;

</description>
				<pubDate>Fri, 09 Feb 2018 23:16:01 +0100</pubDate>
				<link>https://danielecampogiani.com/blog/2018/02/android-functional-validation-3-either/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2018/02/android-functional-validation-3-either/</guid>
			</item>
		
			<item>
				<title>Android Functional Validation 2 - Option</title>
				<description>&lt;p&gt;In this implementation of &lt;a href=&quot;/blog/2018/02/android-functional-validation-1-intro/&quot;&gt;Functional Validation&lt;/a&gt; we are going to use Option.&lt;/p&gt;

&lt;p&gt;Quoting Arrow doc:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Option&lt;a&gt; is a container for an optional value of type A. If the value of type A is present, the Option&lt;a&gt; is an instance of Some&lt;a&gt;, containing the present value of type A. If the value is absent, the Option&lt;a&gt; is the object None.&lt;/a&gt;&lt;/a&gt;&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So basically is a sealed class with two different implementations:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Some&lt;/li&gt;
  &lt;li&gt;None&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main idea is to wrap a value that can be present or absent. Wrapping this value in a container such as Option allows us to use this data without worrying to check each time if the value is present or not. We can just use some &lt;em&gt;standard&lt;/em&gt; functions like map and flatmap to manipulate the content and write less boilerplate code.&lt;/p&gt;

&lt;h3 id=&quot;lets-use-option&quot;&gt;Let’s use Option&lt;/h3&gt;

&lt;p&gt;We are going to use one Option to represent the mail, one Option to represent the phone number and then we will &lt;em&gt;merge&lt;/em&gt; them to obtain the output of our validation&lt;/p&gt;

&lt;p&gt;In our representation will use Some to wrap valid input and None for invalid input, so for example:&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Option1.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;To obtain such behaviour we can use kotlin extension methods invoking &lt;a href=&quot;/blog/2018/02/android-functional-validation-1-intro/&quot;&gt;validMail and validNumber functions we have discussed in previous post&lt;/a&gt;&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/619ee31c4dd3b84cf17f137688a56a8e.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;At this point we have a Option representation for each field, but what we really want is to validate the whole form!&lt;/p&gt;

&lt;h3 id=&quot;map-to-the-rescue&quot;&gt;Map to the rescue&lt;/h3&gt;

&lt;p&gt;Our goal is to obtain an instance of Data when the form is valid:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/2fb34a1b6404190612572d47a21fe095.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;but what we achieved so far are two Option.&lt;/p&gt;

&lt;p&gt;Luckily for us there is a useful method that accept two Option as inputs, and returns whatever we want. This method is called map and we can use to build our &lt;em&gt;Data&lt;/em&gt; instance&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/ebd2c82d44224c317dfdc9be45fc10c7.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;In this snippet we first wrap mail and phoneNumbers arguments to Option, then use map to merge them.&lt;/p&gt;

&lt;p&gt;With map we pass as last parameter a lambda that takes as input a Pair with the values of the two Options.
So in our case the lambda receives as input a Pair with two strings, the mail and the phone number, and returns a Data instance. (it.a is the first value of the pair, and it.b is the second value of the pair).&lt;/p&gt;

&lt;p&gt;If we take a look at the return type of the validateData we discover that we are returning a Option of Data and not a Data directly, but we are not creating an instance of Option&lt;Data&gt; anywhere, so it must be the map method that wraps our result in a Option!&lt;/Data&gt;&lt;/p&gt;

&lt;p&gt;The real power of map method is that it allows us to write just the happy path in the lambda we pass and it will handle all other scenarios for us. If all arguments are Some (and not None) it will execute our lambda and wrap the result in a Option.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Option2.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Cool, but…&lt;/p&gt;

&lt;h3 id=&quot;option-limits&quot;&gt;Option limits&lt;/h3&gt;

&lt;p&gt;What happens when at least one input is None?&lt;/p&gt;

&lt;p&gt;In this case our happy path lambda will be ignored and None is returned.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Option3.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;and exact same result for&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;/blog/assets/Option4.png&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Since we are getting None in both cases we can’t know which input is wrong!&lt;/p&gt;

&lt;h3 id=&quot;android-ui&quot;&gt;Android UI&lt;/h3&gt;

&lt;p&gt;Let’s use this code to build an android form.&lt;/p&gt;

&lt;p&gt;I’m using &lt;a href=&quot;https://developer.android.com/topic/libraries/architecture/index.html&quot;&gt;Android Architecture Components&lt;/a&gt;, so the glue code will be in a ViewModel, while the activity will do just UI rendering.&lt;/p&gt;

&lt;p&gt;In our ViewModel we will use the previously discussed code to update a &lt;code&gt;LiveData&amp;lt;Option&amp;lt;Data&amp;gt;&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/c511f06239b7a6d53a4cf27aced5a4db.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;In the activity we retrieve the viewModel, register click listener and observe the result of the validation. Once we get the result we fold it.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/2eb139a19b3307044d45c9fd24da1c34.js&quot;&gt; &lt;/script&gt;

&lt;h4 id=&quot;what-is-fold&quot;&gt;What is Fold?&lt;/h4&gt;

&lt;p&gt;Fold is a method defined on Option that takes to functions, the first one will be executed if the Option is empty, while the second one if the Option contains a value.&lt;/p&gt;

&lt;p&gt;In our case we are using method reference with the following methods:&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/a0ece7a02d6a2093ae0c08efbd814d7b.js&quot;&gt; &lt;/script&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/4230debf17ef25689c0d6f0cb96512c9.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;As you can see in the second method we receive as input the value of the Option, while in the first method we don’t get any input. So, as previously discussed, using Option we cannot notify our user which field is wrong.&lt;/p&gt;

&lt;p&gt;So, Option is not a great choice for validation, but don’t worry we will fix this issue in the &lt;a href=&quot;/blog/2018/02/android-functional-validation-3-either/&quot;&gt;next post&lt;/a&gt; using a different data type.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/dcampogiani/AndroidFunctionalValidation/pull/1&quot;&gt;You can find here the implementation using Option&lt;/a&gt;&lt;/p&gt;

</description>
				<pubDate>Thu, 08 Feb 2018 23:16:01 +0100</pubDate>
				<link>https://danielecampogiani.com/blog/2018/02/android-functional-validation-2-option/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2018/02/android-functional-validation-2-option/</guid>
			</item>
		
			<item>
				<title>Android Functional Validation 1 - Introduction</title>
				<description>&lt;p&gt;This year I’ve been at &lt;a href=&quot;http://scaladays.org/archive/copenhagen2017.html&quot;&gt;Scala Days 2017&lt;/a&gt; and because I’m a functional programer noob I attended all beginners’s talks.&lt;/p&gt;

&lt;p&gt;One talk that really got my attention and gave me the the intuition of the power of functional programming was &lt;a href=&quot;http://scaladays.org/archive/copenhagen2017.html#!#schedulePopupExtras-8053&quot;&gt;Easy and Efficient Data Validation with Cats&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;https://www.youtube.com/watch?v=P8nGAo3Jp-Q&quot;&gt;her talk&lt;/a&gt; Daniela gave an example of how functional abstractions can help us developer, even if we don’t know (yet) what a Monad is.&lt;/p&gt;

&lt;p&gt;Some months laters I’ve discovered &lt;a href=&quot;http://arrow-kt.io/&quot;&gt;Arrow&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Functional datatypes &amp;amp; abstractions for Kotlin&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and I started to study it, to grok some functional concepts and play with Android.&lt;/p&gt;

&lt;h3 id=&quot;ok-cool-but-what-has-to-do-all-of-this-with-android&quot;&gt;Ok cool, but what has to do all of this with Android?&lt;/h3&gt;

&lt;p&gt;In this serie of posts I’d like to replicate Daniela’s talk using kotlin and Android.&lt;/p&gt;

&lt;p&gt;We are going to build a simple form with two inputs:
	- Mail
	- Phone Number
and validate it.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;&lt;img src=&quot;https://github.com/dcampogiani/AndroidFunctionalValidation/blob/master/demo/validatedValidationError.gif?raw=true&quot; width=&quot;200&quot; /&gt;&lt;/div&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;We are going to achieve this using different data types, improving the current solution in each step choosing a new data type.&lt;/p&gt;

&lt;h3 id=&quot;wait-what-is-a-data-type&quot;&gt;Wait, what is a data type?&lt;/h3&gt;
&lt;p&gt;Quoting the (excelent) arrow documentation, a data type is:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;A datatype is a class that encapsulates one reusable coding pattern. These solutions have a canonical implementation that is generalised for all possible uses.
Some common patterns expressed as datatypes are absence handling with &lt;a href=&quot;http://arrow-kt.io/docs/datatypes/option/&quot;&gt;Option&lt;/a&gt;, branching in code with &lt;a href=&quot;http://arrow-kt.io/docs/datatypes/either/&quot;&gt;Either&lt;/a&gt;, catching exceptions with &lt;a href=&quot;http://arrow-kt.io/docs/datatypes/try/&quot;&gt;Try&lt;/a&gt;, or interacting with the platform the program runs in using &lt;a href=&quot;http://arrow-kt.io/docs/effects/io/&quot;&gt;IO&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don’t worry if you don’t understand the definition right now, we are going to use three of them we will discuss them.&lt;/p&gt;

&lt;h3 id=&quot;demo-application-structure&quot;&gt;Demo application structure&lt;/h3&gt;

&lt;p&gt;We are going to use one activity and one viewmodel for each data type, sharing the same xml view with two different TextInputLayout.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/da0665c4271cf4e2243a40aab6ee6fe6.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;The input of our validation will be a data class with two strings.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/2fb34a1b6404190612572d47a21fe095.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;To validate mail and phone number we are going to use two pure functions in a kotlin file.&lt;/p&gt;

&lt;noscript&gt;&lt;pre&gt;400: Invalid request&lt;/pre&gt;&lt;/noscript&gt;
&lt;script src=&quot;https://gist.github.com/5101541b8415d058d05b56f088bd6113.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Enough for first post, we can start to see some real code in following posts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/2018/02/android-functional-validation-2-option/&quot;&gt;Option&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/2018/02/android-functional-validation-3-either/&quot;&gt;Either&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/blog/2018/02/android-functional-validation-4-validated/&quot;&gt;Validated&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The source code for this article is available &lt;a href=&quot;https://github.com/dcampogiani/AndroidFunctionalValidation&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
				<pubDate>Wed, 07 Feb 2018 23:16:01 +0100</pubDate>
				<link>https://danielecampogiani.com/blog/2018/02/android-functional-validation-1-intro/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2018/02/android-functional-validation-1-intro/</guid>
			</item>
		
			<item>
				<title>Applicazioni Ibride e Native #6 – Confronto</title>
				<description>&lt;h2&gt;Dimensione Apk&lt;/h2&gt;
&lt;h3&gt;Applicazione Ibrida&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Per quanto riguarda l'applicazione ibrida il file &lt;i&gt;apk&lt;/i&gt; è stato generato due volte, una volta senza minimizzare il codice e una volta minimizzandolo ottenendo dei risultati non aspettati, come mostrato in tabella:&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;img title=&quot;tabella codice&quot; src=&quot;/blog/assets/tabella-codice.png&quot;/&gt;
&lt;p class=&quot;western&quot;&gt;Come si può notare, semplicemente minimizzando il codice otteniamo un file circa cinque volte più piccolo. Una volta installata sul dispositivo l'applicazione occupa 1,2 MB.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Applicazione Nativa&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Il file apk generato dal codice dell'applicazione nativa è di 2,1 MB. Nel codice utilizzo una libreria esterna per la gestione delle animazioni, senza usare questa libreria il file apk è di 2 MB.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Una volta installata l'applicazione occupa nel dispositivo 6,4 MB.&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Linee di Codice&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;Trattandosi di applicazioni scritte in linguaggi diversi il confronto è da considerarsi puramente indicativo, inoltre non viene preso in considerazione il codice di librerie utilizzate ma solo il codice effettivamente scritto per l'applicazione.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Applicazione Ibrida&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Sono stati scritti 10 file in Javascript per un totale di 649 righe di codice, un file CSS di 5 righe e 6 file HTML per un totale di 164 righe. Sommando tutti i file otteniamo 818 righe di codice.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Applicazione Nativa&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Per quanto riguarda l'applicazione nativa sono stati scritti 6 file Java per un totale di 828 righe di codice e 8 file XML per un totale di 180 righe di codice. Nel complesso sono state scritte 1008 righe di codice.&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Tempo necessario per scattare e memorizzare un'immagine&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;I seguenti risultati sono stati ottenuti utilizzando un Nexus 7 2013 con Android in versione 4.4.2 ( custom rom ParanoidAndroid 4.3-Beta7) dotato di CPU quad core a 1.5 GHz e 2GB di RAM.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Le foto in esame sono state scattate con la fotocamera frontale.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Ho calcolato due intervalli di tempo: il primo (chiamato &lt;i&gt;acquisizione&lt;/i&gt; nelle successive tabelle) è il lasso di tempo che trascorre tra la pressione del tasto per scattare una fotografia e la restituzione del controllo all'applicazione (sia nativa che ibrida) con la foto appena scattata, e il secondo (chiamato &lt;i&gt;salvataggio&lt;/i&gt; nelle tabelle) è il tempo necessario per memorizzare l'immagine nel filesystem e nel database dell'applicazione.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Ho eseguito questo test sia con le due applicazione &lt;i&gt;“pulite”&lt;/i&gt; (ossia senza nessuna foto ancora memorizzata) sia con cinque foto memorizzate senza riscontrare però cambiamenti degni di essere considerati.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Inoltre ho eseguito il test considerando il fatto che la foto che stessi scattando fosse la prima (dall'apertura dell'applicazione) oppure se fosse una foto successiva, e anche in questo caso non ci sono stati cambiamenti degni di nota.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Applicazione Ibrida&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;In tabella sono riportati in millisecondi i due intervalli sopra descritti nel caso di applicazione con zero foto memorizzate e prima foto scattata dall'apertura dell'applicazione&lt;/p&gt;
&lt;img title=&quot;tabella tempo foto ibrida&quot; src=&quot;/blog/assets/tabella-tempo-foto-ibrida.png&quot;/&gt;
&lt;p class=&quot;western&quot;&gt;In media sono necessari 3602 millisecondi per acquisire un immagine e 197 secondi per memorizzarla.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Non sono riportati i test con applicazione con cinque foto memorizzate oppure il caso in cui la foto scattata non fosse la prima dall'apertura dell'applicazione perché hanno differenze non significative rispetto al caso riportato.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Applicazione Nativa&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Analogamente all'applicazione Ibrida riporto in tabella i valori dei due intervalli ottenuti in cinque test&lt;/p&gt;
&lt;img title=&quot;tabella tempo foto nativa&quot; src=&quot;/blog/assets/tabella-tempo-foto-nativa.png&quot;/&gt;
&lt;p class=&quot;western&quot;&gt;Anche in questo caso non ho riscontrato cambiamenti degni di nota effettuando test con applicazione con cinque foto memorizzate, o scattando una foto che non fosse la prima dall'apertura dell'applicazione, per cui riporto solo il caso di applicazione &lt;i&gt;“pulita”&lt;/i&gt; e prima foto scattata.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;In media sono necessari 3254,6 millisecondi per scattare una fotografia e 50,4 millisecondi per memorizzarla nel filesystem e nel database.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Analisi dei risultati&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Per quanto riguarda l'acquisizione dell'immagine l'applicazione ibrida è leggermente più lenta, invece per quanto riguarda la memorizzazione impiega circa quattro volte il tempo impiegato dall'applicazione nativa.&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Utilizzo di memoria&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;Ho misurato l'utilizzo di RAM delle due applicazioni, e come si può notare in tabella l'applicazione ibrida richiede una quantità di memoria decisamente maggiore.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Apertura&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;È&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; qui di seguito riportata la RAM occupata all'apertura, al variare del numero di immagini memorizzare nell'applicazione:&lt;/span&gt;&lt;/p&gt;
&lt;img title=&quot;tabella ram apertura&quot; src=&quot;/blog/assets/tabella-ram-apertura.png&quot;/&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;L'applicazione ibrida richiede sempre almeno 106 MB di memoria, mentre l'applicazione nativa ne usa quasi un sesto.&lt;/span&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Scorrimento nella timeline&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Riporto in tabella l'utilizzo di RAM delle due applicazioni dopo aver visualizzato tutte le foto nella timeline (scorrendo la view fino in fondo e poi tornando in cima), anche in questo caso al variare di foto memorizzate:&lt;/span&gt;&lt;/p&gt;
&lt;img title=&quot;tabella ram timeline&quot; src=&quot;/blog/assets/tabella-ram-timeline.png&quot;/&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;L'applicazione nativa utilizza quindi circa un quarto della memoria richiesta dall'applicazione ibrida.&lt;/span&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Mappa&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Spostandosi nella view che mostra le foto sulla mappa abbiamo questi dati:&lt;/span&gt;&lt;/p&gt;
&lt;img title=&quot;tabella ram mappa&quot; src=&quot;/blog/assets/tabella-ram-mappa.png&quot;/&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Anche in questo caso l'applicazione ibrida risulta molto più &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;“pesante”&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;, richiedendo circa tre volte la memoria necessaria all'applicazione nativa.&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Considerazioni finali&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Il modello applicativo utilizzato per realizzare l'applicazione ibrida (utilizzando il framework AngularJS) è molto più semplice del modello usato da Android per la realizzazione di applicazioni native. In AngularJS oltre alle view HTML, &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;le directive&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; e &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;i &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;controller esistono i servizi, componenti software singleton che si occupano di tutto il resto. In Android invece esistono molto più componenti.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Risulta quindi più facile all'inizio sviluppare un'applicazione ibrida, ma una volta capiti i diversi componenti che Android fornisce, si riesce ad avere un'applicazione con una miglior &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;struttura&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;, e a scrivere meno codice perché Android realizza già molte funzionalità di base.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per quanto riguarda i tools forniti agli sviluppatori non c'è paragone, il supporto fornito a sviluppatori Cordova è praticamente inesistente e limitato all'uso del terminale attraverso lo strumento chiamato &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;Cordova Command-line Interface&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;. Per questo motivo mi sono trovato costretto ad utilizzare una serie di tool esterni per migliorare il workflow &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;come &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;Grunt&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;Bower&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; e &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;Yeoman&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;. &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Anche il debug è più complicato trattandosi di codice interpretato.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per lo sviluppo dell'applicazione nativa ho invece utilizzato &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;Android Studio&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; una soluzione completa fornita da google per lo sviluppo, il test e il deploy delle applicazioni.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Confrontando le performances delle due applicazioni risulta nettamente vincitrice l'applicazione nativa, sia per il consumo di memoria che per la fluidità ottenuta. L'applicazione ibrida in particolare ha uno scroll molto più lento nelle liste.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Punto a favore dell'applicazione ibrida invece è la possibilità di riutilizzo del codice scritto, infatti i componenti scritti possono essere utilizzati sia in una applicazione mobile/ibrida che un normale sito web. Ovviamente in un normale sito web non si hanno a disposizione le API fornite da Cordova, ma i componenti che non l&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; usano possono essere &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;“&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;portati”&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; anche su desktop, mi sono infatti spesso trovato a provare l'applicazione su browser desktop prima di effettuare il deploy su dispositivo per controllare velocemente le modifiche apportate. Nello specifico l'unica API che non &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;ho potuto&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; utilizzare da desktop è quella di accesso alla fotocamera, &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;mentre per la persistenza e la geo-localizzazione non ho avuto problemi poiché Chrome fornisce le stesse API che Cordova implementa su dispositivi mobili. &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Vale la pena ricordare inoltre ricordare che una applicazione scritta utilizzando Cordova può essere utilizzata su più piattaforme mobile, mentre nel caso di applicazione nativa si è limitati ad una sola piattaforma.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Android pur utilizzando codice Java forza lo sviluppatore a realizzare componenti estendendo quelli forniti dalla piattaforma, per cui questi componenti non possono essere &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;“portati”&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; su una normale &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;JVM&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; desktop.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Inoltre per la scrittura di una applicazione nativa, il produttore della piattaforma fornisce uno stack completo di supporto (dall'interfaccia grafica all'accesso all'hardware) mentre Cordova fornisce solo un set di API per l'accesso al dispositivo e nessun supporto per la realizzazione di UI, e ho dovuto quindi utilizzare un framework esterno.&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Fri, 01 Aug 2014 15:16:38 +0200</pubDate>
				<link>https://danielecampogiani.com/blog/2014/08/applicazioni-ibride-e-native-6-confronto/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2014/08/applicazioni-ibride-e-native-6-confronto/</guid>
			</item>
		
			<item>
				<title>Applicazioni Ibride e Native #5 – Realizzazione di una Applicazione Nativa</title>
				<description>&lt;h2&gt;Content Provider&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;In Android i &lt;i&gt;Content Provider&lt;/i&gt; sono utilizzati per disaccoppiare il layer di persistenza dal layer applicativo. Ogni applicazione ha accesso ad un database privato, usando i C&lt;i&gt;ontent Provider&lt;/i&gt; è possibile invece condividere i dati con altre applicazioni, ed è inoltre possibile eseguire query asincrone su di essi per ottenere un'applicazione &lt;i&gt;responsive&lt;/i&gt;. Android ha diversi &lt;i&gt;Content Provider built-in &lt;/i&gt;utilizzabili dagli sviluppatori, ad esempio &lt;i&gt;Media Store&lt;/i&gt;, &lt;i&gt;Contacts&lt;/i&gt;, &lt;i&gt;Calendar&lt;/i&gt; e &lt;i&gt;Call Log&lt;/i&gt;. &lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;È&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; inoltre possibile definire nuovi content provider.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/java/com/danielecampogiani/mynativephotodiary/persistence/PicturesProvider.java&quot;&gt;PicturesProvider&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per l'applicazione ho realizzato un provider per memorizzare e ottenere i dati relativi alle foto scattate dall'utente. Il provider al suo interno utilizza un database &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;SQLite&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; gestito estendendo la classe di &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;SQLiteOpenHelper&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; fornita da Android.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Il database ha una singola tabella che memorizza il path su filesystem dell'immagine, la descrizione inserita dall'utente, le coordinate geografiche ed un id univoco.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;È&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; possibile interrogare il provider per ottenere tutte le immagini attualmente memorizzate attraverso l'url &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;content://com.danielecampogiani.picturesprovider/pictures&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;, mentre se si desidera ottenere informazioni su una specifica foto è sufficiente inserire in fondo all'url 'id della foto : &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;content://com.danielecampogiani.picturesprovider/pictures/id&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Dopo aver fatto un match sull'url richiesto al provider (per discriminare se sono richieste tutte le immagini, o una specifica) il content provider delega il reperimento dei dati al database, e nel caso di modifiche notifica i &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;Content Resolver &lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;permettendo così di ottenere delle callback lato applicativo senza dover rieseguire query (come spiegato più avanti).&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Activity&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;Una &lt;i&gt;Activity&lt;/i&gt; rappresenta una schermata mostrata ad un utente solitamente occupando tutto lo schermo del dispositivo, per creare un'attività è sufficiente estendere la classe &lt;i&gt;Activity&lt;/i&gt; e definire i metodi di callback richiamati dal sistema Android per gestire il ciclo di vita dell'attività.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/java/com/danielecampogiani/mynativephotodiary/activities/MainActivity.java&quot;&gt;MainActivity&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Per l'applicazione ho creato una sola &lt;i&gt;Activity&lt;/i&gt;, poiché utilizzo all'intero di essa diversi &lt;i&gt;Fragment&lt;/i&gt; che vengono automaticamente mostrati/nascosti utilizzando un' &lt;i&gt;actionBar&lt;/i&gt; a &lt;i&gt;tabs&lt;/i&gt;.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Per gestire le transazioni di &lt;i&gt;Fragment&lt;/i&gt; ho creato la classe &lt;i&gt;TabListener&lt;/i&gt; che si occupa di instanziare quando necessario il &lt;i&gt;fragment&lt;/i&gt; che gestisce e di aggiungerlo e rimuoverlo dallo schermo utilizzando &lt;i&gt;FragmentTransaction&lt;/i&gt; quando l'utente seleziona il tab relativo.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Ho inoltre aggiunto un menu alla actionBar con un pulsante che quando selezionato crea &lt;i&gt;l'intent&lt;/i&gt; &lt;i&gt;Mediastore.Action_Image_Capture&lt;/i&gt; specificando un uri negli &lt;i&gt;extra&lt;/i&gt; dell'&lt;i&gt;intent&lt;/i&gt; poi &lt;i&gt;“lancia”&lt;/i&gt; questo intent aspettando la restituzione del controllo con il metodo &lt;i&gt;startActivityForResult&lt;/i&gt;. Così facendo verrà lanciata l'applicazione scelta dall'utente per scattare fotografie, e una volta che la foto è stata fatta sarà memorizzata nell'uri specificato negli extra dell'&lt;i&gt;intent &lt;/i&gt; e il controllo tornerà all'attività &lt;i&gt;MainActivity&lt;/i&gt;.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Ogni qual volta possibile ho eseguito le operazioni all'interno di &lt;i&gt;AsyncTask&lt;/i&gt;, questo permette di eseguire codice in background, senza quindi utilizzare il thread dedicato alla UI, e sincronizzare l'interfaccia grafica al termine della loro esecuzione.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;La classe &lt;i&gt;AsyncTask&lt;/i&gt; si occupa della creazione, gestione e sincronizzazione di thread, per cui lo sviluppatore si deve preoccupare solamente di scrivere la logica applicativa.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Nello specifico ho utilizzato &lt;i&gt;SavePictureAsyncTask&lt;/i&gt; per leggere le coordinate geografiche dall'immagine restituita dall'applicazione fotocamera e per memorizzare l'immagine nel content provider, e &lt;i&gt;NewPictureAsyncTask&lt;/i&gt; per le operazioni di I/O necessarie per creare il nuovo file sul filesystem.&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Fragments&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;I &lt;i&gt;fragment&lt;/i&gt; vengono utilizzati per creare UI dinamiche e flessibili che si adattano a diversi schermi. Ogni &lt;i&gt;fragment&lt;/i&gt; è un componente a se stante (con un suo ciclo di vita) utilizzabile da diverse activity. Per creare un nuovo &lt;i&gt;fragment&lt;/i&gt; è sufficiente estendere la classe &lt;i&gt;Fragment&lt;/i&gt;.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/java/com/danielecampogiani/mynativephotodiary/fragments/TimelineFragment.java&quot;&gt;TimelineFragment&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;È&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; il fragment collegato al tab &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;“Timeline”&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; e mostra in una lista (estende la classe &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;ListFragment)&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; le foto scattate in ordine cronologico. Sotto ogni foto è presente la descrizione e due pulsanti, uno per cancellare la foto e uno per condivide&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;rla.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per ottenere le foto da mostrare utilizz&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; un &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;loader&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; di &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;cursor&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; poiché le operazioni su database possono essere &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;time-consuming&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;I &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;loaders&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; sono un meccanismo per caricare dati in maniera asincrona e per monitorare le sorgenti di dati. Possono essere utilizzati per qualunque tipo di dato, nell'applicazione li ho utilizzati per caricare dei &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;cursor&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; ossia il risultato di query su database in Android.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per ottenere un comportamento asincrono all'interno del fragment ho implementato l'interfaccia &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;LoaderManager.LoaderCallbacks&amp;lt;Cursor&amp;gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; realizzando i metodi:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;onCreateLoader: responsabile di creare il loader (usando la classe &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;CursorLoader&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; di Android) specificando i parametri della query desiderata.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;onLoadFinished: richiamato quando la query asincrona restituisce dei risultati che vengono passati come parametro in questo metodo. Il metodo è invocato anche ogni qual volta cambiano i dati di interesse per la query specificata nel metodo onCreateLoader.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;onLoaderReset: &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;per resettare il loader.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;P&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;er lo specifico fragment, il loader creato interroga il &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;PicturesProvider&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; richiedendo l'id, la descrizione e il path su filesystem di ogni foto.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Nel metodo &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;onLoadFinished&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; aggiorno la grafica mostrando i risultati utilizzando come &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;adapter&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; della lista la classe &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;TimelinePicturesAdapter&lt;/i&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/java/com/danielecampogiani/mynativephotodiary/fragments/PlacesFragment.java&quot;&gt;PlacesFragment&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Il fragment collegato al tab &lt;i&gt;“Places”&lt;/i&gt; mostra sullo schermo una google map centrata sulla posizione attuale dell'utente e ogni foto nelle coordinate geografiche nelle quali è stata scattata.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Anche in questo &lt;i&gt;fragment&lt;/i&gt; ottengo dati in maniera asincrona implementando l'interfaccia &lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;LoaderManager.LoaderCallbacks&amp;lt;Cursor&amp;gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;richiedendo a &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;PicturesProvider&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; la latitudine, la longitudine e il path su filesystem per ogni foto.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Una volta ottenuti i dati provvedo ad aggiornare l'interfaccia grafica utilizzando l'&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;AsyncTask&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;AddMarkersAsyncTask&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; che elabora le foto restituite dal loader creando dei &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;marker&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; da mostrare sulla mappa.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per ottenere la posizione attuale dell'utente utilizzo la classe &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;LocationClient&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; e implemento le interfacce di Android &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;GooglePlayServicesClient.OnConnectionFailedListener e GooglePlayServicesClient.ConnectionCallbacks&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; e aggiornando l'interfaccia nella callback che restituisce la posizione dell'utente.&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Adapter&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;Gli &lt;i&gt;adapter&lt;/i&gt; sono usati per effettuare il binding tra i dati e le view che estendono &lt;i&gt;AdapterView&lt;/i&gt;, come ad esempio &lt;i&gt;ListFragment&lt;/i&gt; (che ho esteso per realizzare &lt;i&gt;TimelineFragment&lt;/i&gt;). Gli adapter sono responsabili di creare le view figlie per mostrare i dati.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/java/com/danielecampogiani/mynativephotodiary/adapters/TimelinePicturesAdapter.java&quot;&gt;TimelinePicturesAdapter&lt;/a&gt;&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Classe che estende &lt;i&gt;CursorAdapter&lt;/i&gt; e per ogni cursor (una foto) utilizza una &lt;i&gt;ImageView&lt;/i&gt; per visualizzare su schermo la foto, una &lt;i&gt;TextView&lt;/i&gt; per mostrare la descrizione e due pulsanti, uno per condividere la foto e uno per cancellarla. Il pulsante per la cancellazione mostra inoltre un &lt;i&gt;AlertDialog&lt;/i&gt; per chiedere conferma all'utente una volta selezionato. Il pulsante per la condivisione invece lancia l'&lt;i&gt;intent&lt;/i&gt; &lt;i&gt;Intent.Action_Send&lt;/i&gt; specificando come tipo di dato &lt;i&gt;image/jpeg&lt;/i&gt;, così facendo l'utente può scegliere con quale applicazione condividere il file.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Anche in questo caso ho utilizzato un &lt;i&gt;AsyncTask&lt;/i&gt; per non svolgere operazioni potenzialmente lunghe nel thread della UI. &lt;i&gt;DeletePicturesAsyncTask&lt;/i&gt; rimuove l'immagine dal content provider e dal filesystem.&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Layouts&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;I &lt;i&gt;Layouts&lt;/i&gt; permettono di separare il layer di presentazione dalla logica di business, specificando l'interfaccia grafica in file XML invece che crearla via codice.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Una volta definiti i file XML, questi possono essere &lt;i&gt;“inflated”&lt;/i&gt; nei rispettivi componenti (&lt;i&gt;Activity&lt;/i&gt; e &lt;i&gt;Fragment&lt;/i&gt;) usando il metodo &lt;i&gt;setContentView&lt;/i&gt; per le &lt;i&gt;Activity&lt;/i&gt; e il metodo &lt;i&gt;Inflator.inflate &lt;/i&gt;per i Fragment (l'oggetto &lt;i&gt;Inflator&lt;/i&gt; è passato al &lt;i&gt;fragment&lt;/i&gt; nel metodo &lt;i&gt;onCreateView&lt;/i&gt;).&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;L'utilizzo di &lt;i&gt;layouts&lt;/i&gt; è considerato una &lt;i&gt;best practice&lt;/i&gt; in Android, perché è un meccanismo che permette di creare interfacce ottimizzate per diversi tipi di hardware, ad esempio diverse dimensioni di schermo, o la presenza o meno di una tastiera o touchscreen.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Per l'applicazione ho realizzato i seguenti layout:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/res/layout/activity_main.xml&quot;&gt;activity_main.xml&lt;/a&gt; : contiene un holder in cui collocare i fragment selezionati scegliendo un tab dell'actionBar.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/res/layout/dialog_description_layout.xml&quot;&gt;dialog_description_layout.xml&lt;/a&gt; : utilizzato per creare un &lt;i&gt;AlertDialog&lt;/i&gt; in cui richiedere all'utente una descrizione testuale della foto appena scattata.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/res/layout/fragment_places.xml&quot;&gt;fragment_places.xml&lt;/a&gt; : usato dal &lt;i&gt;fragment&lt;/i&gt; &lt;i&gt;PlacesFragment&lt;/i&gt; contiene al suo interno un &lt;i&gt;MapFragment&lt;/i&gt; per mostrare la google map sullo schermo.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/res/layout/fragment_timeline.xml&quot;&gt;fragment_timeline.xml &lt;/a&gt;: usato dal &lt;i&gt;fragment&lt;/i&gt; &lt;i&gt;TimelineFragment&lt;/i&gt; contiene al suo interno una &lt;i&gt;ListView&lt;/i&gt; per mostrare tutte le fotografie.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Native-Photo-Diary/blob/master/MyNativePhotoDiary/src/main/res/layout/timeline_picture_layout.xml&quot;&gt;timeline_picture_layout&lt;/a&gt; : usato da TimelinePicturesAdapter responsabile di mostrare ogni singola fotografia nella lista sopra descritta. Per ogni foto mostra l'immagine vera e propria, la descrizione e due pulsanti, uno per cancellare la foto e uno per condividerla.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
				<pubDate>Wed, 16 Jul 2014 22:46:39 +0200</pubDate>
				<link>https://danielecampogiani.com/blog/2014/07/applicazioni-ibride-e-native-5-realizzazione-di-una-applicazione-nativa/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2014/07/applicazioni-ibride-e-native-5-realizzazione-di-una-applicazione-nativa/</guid>
			</item>
		
			<item>
				<title>Applicazioni Ibride e Native #4 – Realizzazione di una Applicazione Ibrida</title>
				<description>&lt;h2&gt;Strumenti Utilizzati&lt;/h2&gt;
&lt;h3&gt;Cordova e plugins&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Per realizzare l'applicazione è stato utilizzato Cordova 3.4.1 ed i seguenti plugin:&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin&quot;&gt;SocialSharing-PhoneGap-Plugin&lt;/a&gt;: per permettere all'utente di condividere le foto scattate. Documentazione ed ulteriori informazioni sono presenti presso la repository github: &lt;span lang=&quot;zxx&quot;&gt;&lt;a href=&quot;https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin&quot;&gt;https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span lang=&quot;zxx&quot;&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.camera&quot;&gt;Cordova Camera Plugin:&lt;/a&gt; per avere accesso alla fotocamera del dispositivo. Documentazione e ulteriori informazioni nella pagina del plugin: &lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.camera&quot;&gt;http://plugins.cordova.io/#/package/org.apache.cordova.camera&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span lang=&quot;zxx&quot;&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.device&quot;&gt;Cordova Device Plugin&lt;/a&gt;: fornisce una descrizione dell'hardware e del software del dispositivo. &lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;Documentazione e ulteriori informazioni nella pagina del plugin: &lt;/span&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.device&quot;&gt;&lt;span lang=&quot;zxx&quot;&gt;http://plugins.cordova.io/#/package/org.apache.cordova.device&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span lang=&quot;zxx&quot;&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.file&quot;&gt;Cordova File Plugin&lt;/a&gt;: per memorizzare nel filesystem locale le fo&lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;t&lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;o scatta&lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;t&lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;e. &lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;Documentazione e ulteriori informazioni nella pagina del plugin: &lt;/span&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.file&quot;&gt;&lt;span lang=&quot;zxx&quot;&gt;http://plugins.cordova.io/#/package/org.apache.cordova.file&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span lang=&quot;zxx&quot;&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.geolocation&quot;&gt;Cordova Geolocation Plugin&lt;/a&gt;: utilizzato per determinare la posizione dell'utente. &lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;Documentazione e ulteriori informazioni nella pagina del plugin: &lt;/span&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.geolocation&quot;&gt;&lt;span lang=&quot;zxx&quot;&gt;http://plugins.cordova.io/#/package/org.apache.cordova.geolocation&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span lang=&quot;zxx&quot;&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.statusbar&quot;&gt;Cordova StatusBar Plugin&lt;/a&gt;: permette di avere un'integrazione con la status bar di iOS 7, in modo tale da avere stesso look and feel di una applicazione nativa. &lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;Documentazione e ulteriori informazioni nella pagina del plugin: &lt;/span&gt;&lt;span lang=&quot;zxx&quot;&gt;&lt;a href=&quot;http://plugins.cordova.io/#/package/org.apache.cordova.statusbar&quot;&gt;http://plugins.cordova.io/#/package/org.apache.cordova.statusbar&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;Ionic&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Per realizzare l'interfaccia grafica dell'applicazione è stato utilizzato &lt;a href=&quot;http://ionicframework.com/&quot;&gt;Ionic&lt;/a&gt; un framework open source che utilizza AngularJS e fornisce agli sviluppatori componenti (HTML/CSS/Javascript) ed alcuni plugin per Cordova.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;I componenti forniti hanno &lt;i&gt;directive&lt;/i&gt; da utilizzare nelle view HTML ed &lt;i&gt;API&lt;/i&gt; da utilizzare nei corrispondenti controller.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Ionic è un framework molto giovane e nella fase iniziale di realizzazione e diffusione. All'inizio della scrittura dell'applicazione era stata da poco pubblicata la prima beta pubblica, ad oggi è stata rilasciata l'ottava beta.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Per l'applicazione sono stati utilizzati i seguenti componenti:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;http://ionicframework.com/docs/api/directive/ionNavView/&quot;&gt;ion-nav-view&lt;/a&gt;: componente che tiene traccia della storia di navigazione dell'utente all'interno dell'applicazione fornendo animazioni tra una view ed un altra. Utilizza UI-Router per gestire i vari stati dell'applicazione&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;http://ionicframework.com/docs/api/directive/ionNavBar/&quot;&gt;ion-nav-bar&lt;/a&gt;: per gestire l'header di ogni view inserendo titoli e pulsanti personalizzati&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;http://ionicframework.com/docs/api/directive/ionTabs/&quot;&gt;ion-tabs&lt;/a&gt;: permette di utilizzare il layout &lt;i&gt;a tabs&lt;/i&gt; ed associare ad ogni &lt;i&gt;tab&lt;/i&gt; una diversa view&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;http://ionicframework.com/docs/api/service/$ionicModal/&quot;&gt;i&lt;/a&gt;&lt;a href=&quot;http://ionicframework.com/docs/api/service/$ionicModal/&quot;&gt;onicModal&lt;/a&gt;: per la gestione di view modali&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;http://ionicframework.com/docs/api/service/$ionicPopup/&quot;&gt;ionicPopup&lt;/a&gt;: per notificare l'utente&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Estensioni AngularJS&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Sono state utilizzate anche le seguenti estensioni per AngularJS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/nlaplante/angular-google-maps&quot;&gt;Angular-google-maps :&lt;/a&gt; fornisce &lt;i&gt;directives&lt;/i&gt; per utilizzare google maps all'interno di applicazioni AngularJS&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/Pasvaz/bindonce&quot;&gt;Bindonce&lt;/a&gt;: utilizzato quando possibile per aumentare le performances&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;western&quot;&gt;A causa del two-way data binding di AngularJS la directive &lt;i&gt;ng-repeat&lt;/i&gt; causa dei deterioramenti di performances poiché AngularJS utilizza un meccanismo di &lt;i&gt;dirty checking&lt;/i&gt; per controllare se sono state effettuate modifiche negli elementi. Utilizzando bindonce viene “rotto” questo two-way data binding per gli elementi specificati, e dopo aver fatto il rendering degli elementi nella view AngularJS non controllerà eventuali modifiche. Ho utilizzato bindonce nella lista di fotografie visualizzate nella timeline.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Le future versioni di AngularJS dovrebbero utilizzare il metodo Object.observe() (non ancora supportato da tutti i browser) per velocizzare queste operazioni ed il team di AngularJS ha dichiarato di avere già ottenuto un &lt;a href=&quot;https://mail.mozilla.org/pipermail/es-discuss/2012-September/024978.html&quot;&gt;incremento delle prestazioni del 20-40%&lt;/a&gt;.&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Struttura dell'Applicazione&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;Per la scrittura dell'applicazione ho realizzato tre moduli AngularJS, ed ho organizzato i file in modo da avere un componente in ogni file separato, definendo tutti i moduli nel file &lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/app.js&quot;&gt;&lt;i&gt;app.js&lt;/i&gt;&lt;/a&gt; e utilizzando il metodo &lt;i&gt;getter&lt;/i&gt; &lt;i&gt;angular.module&lt;/i&gt; per ottenere in ogni file il modulo desiderato per poterci definire e registrare il componente.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Services&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Il modulo MyPhotoDiary.services è così definito:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;angular.module('MyPhotoDiary.services',[]);&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;ed è richiamato in ogni file dentro la cartella scripts/services per poter definire un servizio in ogni file separato (ho fatto questa scelta perché preferisco avere più file piccoli ognuno con limitate responsabilità, poi in fase di deploy i fari file &lt;i&gt;.js&lt;/i&gt; vengono concatenati e il file risultante viene minimizzato).&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Ho realizzato i seguenti &lt;i&gt;services&lt;/i&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/services/CameraService.js&quot;&gt;CameraService&lt;/a&gt;: utilizza le API fornite dal plugin Cordova Camera per scattare fotografie e restituisce una &lt;i&gt;promise&lt;/i&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/services/GeolocationService.js&quot;&gt;GeolocationService&lt;/a&gt;: utilizza le API fornite dal plugin Cordova Geolocation plugin per ottenere le coordinate gps e restituisce una &lt;i&gt;promise&lt;/i&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/services/PicturesService.js&quot;&gt;PicturesService&lt;/a&gt;: gestisce le fotografie dell'applicazione, utilizza il &lt;i&gt;local storage&lt;/i&gt; per memorizzare la descrizione, il path su filesystem locale e le coordinate di ogni fotografia. Per l'operazione di rimozione di fotografie dal filesystem utilizza StorageSettings e restituisce una &lt;i&gt;promise &lt;/i&gt;(le operazioni su filesystem in Javascript sono asincrone). Emette l'evento &lt;i&gt;NewPicture &lt;/i&gt;nel&lt;i&gt; &lt;/i&gt;&lt;i&gt;rootScope&lt;/i&gt; ogni volta viene realizzata una nuova fotografia, in modo tale che qualunque controller possa gestire questo evento una volta sottoscritto. (AngularJS rilascia un controller se l'utente non è nella view correlata, quindi ho scelto di avere un evento globale in modo tale da poterlo gestire indipendentemente dalla view corrente dell'utente)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/services/SettingsService.js&quot;&gt;SettingsService&lt;/a&gt;: memorizza le preferenze dell'utente utilizzando il &lt;i&gt;local&lt;/i&gt; &lt;i&gt;storage&lt;/i&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/services/StorageService.js&quot;&gt;StorageService&lt;/a&gt;: utilizza le API fornite dal plugin Cordova File e permette di memorizzare e cancellare le foto dal filesystem. Per le operazioni restituisce una &lt;i&gt;promise&lt;/i&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Controllers&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Il modulo MyPhotoDiary.controllers è così definito:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;angular.module('MyPhotoDiary.controllers',['MyPhotoDiary.services']);&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;e come già spiegato per il modulo relativo ai services è richiamato all'interno di ogni file dentro la cartella scripts/controllers.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Sono stati realizzati i seguenti controllers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/controllers/MainNavBarController.js&quot;&gt;MainNavBarController&lt;/a&gt;: gestisce la navigation bar presente in ogni view dove è situato un pulsante per scattare una nuova fotografia. Utilizza i services &lt;i&gt;CameraService&lt;/i&gt;, &lt;i&gt;GeolocationService&lt;/i&gt;, &lt;i&gt;PicturesService&lt;/i&gt; e &lt;i&gt;StorageService&lt;/i&gt; per catturare e memorizzare la nuova foto. Usa anche &lt;i&gt;ionicModal&lt;/i&gt; per mostrare all'utente una view modale per confermare o scartare la nuova fotografia, e &lt;i&gt;ionicPopup&lt;/i&gt; per visualizzare eventuali errori.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/controllers/PlacesController.js&quot;&gt;PlacesController&lt;/a&gt;: responsabile della creazione dei marker da visualizzare sulla mappa. Utilizza &lt;i&gt;GeolocationService&lt;/i&gt; per centrare la mappa nella posizione corrente dell'utente e &lt;i&gt;PicturesService&lt;/i&gt; per recuperare le foto da mostrare. Gestisce l'evento &lt;i&gt;NewPicture&lt;/i&gt; reindirizzando l'utente alla view timeline.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/controllers/SettingsController.js&quot;&gt;SettingsController&lt;/a&gt;: permette di scegliere di quante foto effettuare il prefetch per essere visualizzate nella timeline e di eliminare tutte le foto dell'applicazione. Usa &lt;i&gt;PicturesService&lt;/i&gt; per calcolare quante fotografie sono attualmente memorizzate e &lt;i&gt;SettingsService&lt;/i&gt; per memorizzare le preferenze utente. Anche questo controller gestisce l'evento &lt;i&gt;NewPicture&lt;/i&gt; reindirizzando l'utente alla view timeline.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/controllers/TimelineController.js&quot;&gt;TimelineController&lt;/a&gt;: gestisce la condivisione e l'eliminazione della foto selezionata nella corrispettiva view. Inoltre carica ulteriori foto e le aggiunge alla view non appena l'utente raggiunge il limite inferiore dello scroll della view, infatti per motivi di performances non vengono immediatamente caricate tutte le foto nella view. Utilizza &lt;i&gt;PicturesService&lt;/i&gt; per richiedere le foto memorizzate mano a mano che l'utente scorre la view e &lt;i&gt;SettingsService&lt;/i&gt; per sapere di quante foto effettuare il prefetch. Gestisce l'evento &lt;i&gt;NewPicture&lt;/i&gt; aggiungendo la nuova foto in cima alla view e tornando all'inizio della lista di fotografie.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Modulo Principale&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Il modulo MyPhotoDiary è così definito:&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;angular.module('MyPhotoDiary', ['ionic', 'MyPhotoDiary.controllers', 'MyPhotoDiary.services', 'google-maps', 'pasvaz.bindonce'])&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;Ed è configurato nel file &lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/scripts/app.js&quot;&gt;&lt;i&gt;app.js&lt;/i&gt;&lt;/a&gt; specificando per ogni stato dell'applicazione (usando UI-router) il rispettivo nome, url, template e controller.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Gli stati sono:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;tabs: stato astratto con template &lt;i&gt;tabs.html&lt;/i&gt;. Uno stato astratto non può mai essere direttamente attivato, sarà attivato uno dei suoi stati figli.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;tabs.places: mappato su url &lt;i&gt;/places&lt;/i&gt; utilizza il template &lt;i&gt;places.html&lt;/i&gt; ed il controller &lt;i&gt;PlacesController.&lt;/i&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;tabs.timeline: mappato su url &lt;i&gt;/timeline&lt;/i&gt; utilizza il template &lt;i&gt;timeline.html&lt;/i&gt; ed il controller &lt;i&gt;TimelineController&lt;/i&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;tabs.settings: mappato su url &lt;i&gt;/settings&lt;/i&gt; utilizza il template &lt;i&gt;settings.html&lt;/i&gt; ed il controller &lt;i&gt;SettingsController&lt;/i&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;western&quot;&gt;All'avvio dell'applicazione viene impostato lo stato tabs.timeline.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Views&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;I template di ogni view sono salvati all'interno della cartella &lt;i&gt;templates&lt;/i&gt; e sono:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/templates/confirmPhoto.html&quot;&gt;confirmPhoto&lt;/a&gt;: una view modale che visualizza la foto appena scattata e permette di confermarne il salvataggio oppure di scartarla. E' gestita da &lt;i&gt;MainNavController&lt;/i&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/templates/places.html&quot;&gt;places&lt;/a&gt;: contiene una google map e un marker per ogni foto nella posizione in cui è stata scattata. Utilizza la direttiva &amp;lt;google-map&amp;gt; fornita da &lt;i&gt;Angular-google-maps&lt;/i&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/templates/settings.html&quot;&gt;settings&lt;/a&gt;: attraverso uno slider permette all'utente di scegliere il numero di fotografie di cui fare il prefetch nella timeline ed ha un pulsante per eliminare tutte le foto memorizzate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/templates/tabs.html&quot;&gt;tabs&lt;/a&gt;: visualizza tre tab, uno per lo stato tabs.timeline, uno per lo stato tabs.places e uno per lo stato tabs.settings.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;https://github.com/dcampogiani/My-Photo-Diary/blob/master/app/templates/timeline.html&quot;&gt;timeline&lt;/a&gt;: mostra in una lista in ordine cronologico le fotografie memorizzate e sotto ognuna di essa due pulsanti, uno per eliminare ed uno per condividere la foto.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tools&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;Per velocizzare il workflow sono stati utilizzati alcuni tool open source, ne riporto in seguito una breve descrizione per ognuno.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Grunt&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;http://gruntjs.com/&quot;&gt;Grunt&lt;/a&gt; è un task runner scritto in Javascript con molti tool e plugin resi disponibili dalla comunità, tra i plugin che ho utilizzato segnalo &lt;i&gt;bower-install &lt;/i&gt;che inietta le dipendenze gestite con &lt;i&gt;bower&lt;/i&gt; nell'HTML, &lt;i&gt;concat&lt;/i&gt; che concatena diversi fine in uno unico, &lt;i&gt;ngmin&lt;/i&gt;, &lt;i&gt;cssmin&lt;/i&gt; che comprime i file CSS, &lt;i&gt;uglify&lt;/i&gt; per minimizzare il codice Javascript e &lt;i&gt;htmlmin&lt;/i&gt; che minimizza il codice HTML.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;È installabile attraverso &lt;a href=&quot;https://www.npmjs.org/&quot;&gt;npm&lt;/a&gt; (package manager di &lt;a href=&quot;http://nodejs.org/&quot;&gt;node.js&lt;/a&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Bower&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;http://bower.io/&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;ower&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; è &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;un package manager per componenti web. Per l'applicazione ho specificato come dipendenze &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;AngularJS&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;Ionic&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;angular-google-maps&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; e &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;angular-bindonce.&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; Bower provvede a scaricare in locale l'ultima versione (o la versione specificata) delle dipendenze, in modo tale che facendone il deploy sul dispositivo non sia necessaria alcuna connettività di rete.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;nche bower è reperibile attraverso npm.&lt;/span&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Yeoman&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;a href=&quot;http://yeoman.io/&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Yeoman&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; è &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;un tool che automatizza il setup degli &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;strumenti&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; precedentemente descritti &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;grazie a &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;generator&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; resi disponibili dalla comunità (attualmente ci sono più di 700 &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;generators&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;).&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;P&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;er lo sviluppo di questa applicazione ho utilizzato il &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;generator&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; chiamato &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;generator-ionic&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; disponibile in maniera open source all'indirizzo &lt;a href=&quot;https://github.com/diegonetto/generator-ionic&quot;&gt;https://github.com/diegonetto/generator-&lt;/a&gt;&lt;a href=&quot;https://github.com/diegonetto/generator-ionic&quot;&gt;ionic&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Anche yeoman è reperibile con npm.&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 09 Jul 2014 14:00:39 +0200</pubDate>
				<link>https://danielecampogiani.com/blog/2014/07/applicazioni-ibride-e-native-4-realizzazione-di-una-applicazione-ibrida/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2014/07/applicazioni-ibride-e-native-4-realizzazione-di-una-applicazione-ibrida/</guid>
			</item>
		
			<item>
				<title>Applicazioni Ibride e Native #3 – AngularJS</title>
				<description>&lt;p&gt;I hereby declare AngularJS to be MVW framework – Model-View-Whatever. Where Whatever stands for &quot;whatever works for you&lt;/p&gt;
&lt;p style=&quot;text-align: right;&quot;&gt;&lt;a href=&quot;https://plus.google.com/+IgorMinar/posts/DRUAkZmXjNV&quot;&gt;Igor Minar&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;ngularJS è un framework per applicazioni web &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;“single page” &lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;sviluppato da Google.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;S&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;i differenzia da&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; framework precedenti come &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;jQuery&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; nei quali lo sviluppatore doveva avere una conoscenza completa del DOM per poi manipolarlo scrivendo la logica in javascript, ad esempio:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;var btn = $(&quot;&amp;lt;button&amp;gt;Hi&amp;lt;/button&amp;gt;&quot;);&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;btn.on('click', function(evt) { console.log(&quot;Clicked button&quot;) }); &lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;$(&quot;#checkoutHolder&quot;).append(btn);&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;AngularJS invece aumenta il potere espressivo dell'&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;HTML&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; fornendo agli sviluppatori nuovi tag &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;built-in &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;e la possibilità di crearne degli altri.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Inoltre la libreria è di dimensioni veramente ridotte, appena 9KB (la versione minimizzata) ed è disponibile open source.&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;Data Binding&lt;/h2&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; framework web classici come Rails a partire da dati del modello &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;producono&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; una view per l'utente, &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;generando&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; una view &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;“single-way”&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;che riflette i dati del modello solo al momento al momento &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;dell'istanziazione&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;AngularJS invece adotta un approccio unico, creando dei &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;live templates &lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;come view che sono sempre aggiornati rispetto ai dati del modello. Questo ci permette di scrivere nell'HTML&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;input ng-model=&quot;name&quot; type=&quot;text&quot; placeholder=&quot;Your name&quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;h1&amp;gt;Hello &amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Le doppie parentesi graffe indicano un'espressione AngularJS, il framework valuterà l'espressione &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;per &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;effettuare il rendering del contenuto.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;S&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;enza scrivere nessuna riga di codice in Javascript abbiamo ottenuto un &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;i&gt;two-way data binding&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; direttamente nella view.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;In questo esempio, ogni volta che cambierà il valore del tag &amp;lt;input&amp;gt; verrà &lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;aggiornato&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; anche il contenuto del tag &amp;lt;h1&amp;gt; sottostante.&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;Scopes&lt;/h2&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;G&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;li &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;sc&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;opes&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; sono componenti core di ogni applicazione AngularJS, vengono utilizzati come &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;glue&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; tra i controller e le view. Grazie al &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;live binding&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; di AngularJS &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;uno&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;scope&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; è immediatamente aggiornato se l'utente interagisce con la view, e viceversa la view è immediatamente aggiornata se &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;modifichiamo&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; lo &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;scope&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; eseguendo qualche operazione nel codice Javascript.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;AngularJS gestisce i diversi &lt;i&gt;scope&lt;/i&gt; di una applicazione attraverso una relazione gerarchica che rispetta la composizione del DOM, all'avvio dell'applicazione viene infatti creato un &lt;i&gt;rootScope&lt;/i&gt; e tutti gli altri &lt;i&gt;scope&lt;/i&gt; discendono da questo.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot; align=&quot;JUSTIFY&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;L'oggetto &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;scope&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; è un &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;plain old Javascript object&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;, possiamo quindi aggiunge&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;re&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; tutte le &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;proprietà&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; di cui necessitiamo. Esso funge da &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;data model&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; e tutte le &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;sue &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;proprietà sono automaticamente accessibili dalla view:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;div ng-app=&quot;myApp&quot;&amp;gt; &amp;lt;h1&amp;gt;Hello &amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;angular.module('myApp', []) .run(function($rootScope) {&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;$rootScope.name = &quot;World&quot;;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;});&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 lang=&quot;zxx&quot;&gt;&lt;/h2&gt;
&lt;h2 lang=&quot;zxx&quot;&gt;Controllers&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;I &lt;i&gt;controllers&lt;/i&gt; in AngularJS sono funzioni definite dallo sviluppatore per aggiungere funzionalità allo scope della view. Attraverso la Dependency Injection AngularJS passa automaticamente lo scope associato ad ogni &lt;i&gt;controller&lt;/i&gt; al relativo costruttore. Nel costruttore può essere configurato lo stato iniziale dello scope, lo sviluppatore si deve preoccupare solamente di scrivere la funzione costruttore, poiché l'instanziazione dei controller è a carico del framework.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Ad esempio:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;function FirstController($scope) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;$scope.message = &quot;hello&quot;;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;}&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per creare delle azioni invocabili dalle view basterà creare delle funzioni sullo scope associato e poi effettuare il binding, ad esempio sfruttano la built-in directive ng-click che gestisce l'evento click del browser. Quindi volendo fare un esempio leggermente più complesso avremo nella view:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;div ng-controller=&quot;FirstController&quot;&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;h4&amp;gt;Il mio contatore&amp;lt;/h4&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;button ng-click=&quot;add(1)&quot;&amp;gt;Add&amp;lt;/button&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;a ng-click=&quot;subtract(1)&quot;&amp;gt;Subtract&amp;lt;/a&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;h4&amp;gt;Valore : &amp;lt;/h4&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;/div&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;E nel relativo controller:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;app.controller('FirstController', function($scope) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;$scope.counter = 0;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;$scope.add = function(amount) { $scope.counter += amount; };&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;$scope.subtract = function(amount) { $scope.counter -= amount; };&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;});&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Sia il bottone che il link sono collegati ad una azione definita nello scope, per cui quando verranno premuti/selezionati AngularJS chiamerà i rispettivi metodi.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Come si può notare nei &lt;i&gt;controll&lt;/i&gt;&lt;i&gt;ers&lt;/i&gt; scritti dal programmatore non c'è una modifica &lt;i&gt;manuale&lt;/i&gt; del DOM, il tutto viene gestito automaticamente da AngularJS.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Tutti gli scope che sono creati con ereditarietà prototipale, hanno cioè accesso agli scope &lt;i&gt;“avi”&lt;/i&gt;. Quindi ogni qual volta AngularJS non riesce a trovare una proprietà richiesta nello scope corrente risalirà questa catena di ereditarietà fino al &lt;i&gt;rootScope&lt;/i&gt; associato all'applicazione.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;È&lt;/span&gt; importante sapere che per motivi di gestione ottimale della memoria e di performances i controllers sono instanziati solo quando sono necessari, e deallocati quando non lo sono più. Per cui ogni volta che cambia lo stato di una applicazione o ricarichiamo una view, i controller correnti vengono deallocati e instanziati i nuovi controller.&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Directives&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;AngularJS fornisce molte built-in directives che servono ad aumentare l'espressività dell'HTML.Le &lt;i&gt;directives&lt;/i&gt;&lt;i&gt; &lt;/i&gt;&lt;i&gt;built-in&lt;/i&gt; sono tag che iniziano con il prefisso ng, per un elenco dettagliato si rimanda alla &lt;a href=&quot;https://docs.angularjs.org/api/ng/directive&quot;&gt;documentazione di AngularJS&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Inoltre AngularJS permette di definire nuove directive agli sviluppatori con le funzionalità desiderate e di unire diverse directive attraverso un processo chiamato composizione.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per creare una nuova directive bisogna definirla come segue:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;angular.module('myApp', []) .directive('myDirective', function() {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;return {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;restrict: 'E',&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;template: '&amp;lt;a href=&quot;http://google.com&quot;&amp;gt; Click me to go to Google&amp;lt;/a&amp;gt;'&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;} });&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Nell'esempio sono state utilizzate solo la proprietà &lt;i&gt;restrict&lt;/i&gt; e &lt;i&gt;template&lt;/i&gt; per semplicità, per l'elenco esaustivo si rimanda alla documentazione di AngularJS su come creare &lt;a href=&quot;https://docs.angularjs.org/guide/directive&quot;&gt;directives custom&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Avendo definito questa directive, ogni qual volta nell'HTML verrà incontrata la directive AngularJS invocherà la funzione associata. Possiamo quindi scrivere nella nostra view&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;my-directive&amp;gt;&amp;lt;/my-directive&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;e AngularJS provvederà a inserire nel DOM un tag &amp;lt;a&amp;gt; con link a google.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per poter passare dello stato ad una custom directive attraverso gli attributi:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;my-directive my-url=&quot;http://google.com&quot; my-link-text=&quot;Click me to go to Google&quot;&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;/my-directive&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;definendo opportunamente la directive:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;angular.module('myApp', []) .directive('myDirective', function() {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;return {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;restrict: 'E',&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;replace: true,&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;scope: {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;myUrl: '@', // binding strategy&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;myLinkText: '@' // binding strategy&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;},&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;template: '&amp;lt;a href=&quot;&quot;&amp;gt;' + '&amp;lt;/a&amp;gt;'&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;} })&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Così facendo la directive avrà uno scope interno contenente l'url e il testo del link. Ci sono diverse strategie di binding tra attributi passati nella view e lo scope interno, nell'esempio è stata utilizzata la strategia &lt;i&gt;@&lt;/i&gt; che copia il valore dell'attributo nella corrispondente proprietà dello scope.&lt;i&gt; &lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Views&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;I&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;n applicazioni &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;“single page”&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; la navigazione da una view ad un altra è un aspetto critico, vogliamo mostrare del nuovo contenuto all'utente senza forzarlo ad aspettare l'apertura di un altra pagina HTML. AngularJS &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;per ottenere questo risultato &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;permette di scrivere diversi templates, per poi mostrare il contenuto di interesse in base allo &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;“stato”&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; dell'applicazione.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;AngularJS fornisce il modulo &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;ngRoute&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; (da scaricare ed includere manualmente) che realizza la direttiva &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;ng-view &lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;utilizzata come placeholder per il contenuto della view dinamico, ad esempio:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;header&amp;gt; &lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; &amp;lt;h1&amp;gt;Header&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;div class=&quot;content&quot;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; &amp;lt;ng-view&amp;gt;&amp;lt;/ng-view&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt; &amp;lt;h5&amp;gt;Footer&amp;lt;/h5&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Così facendo l'header e il footer della pagina rimarranno sempre gli stessi, mentre il contenuto verrà aggiornato (senza ricaricare l'intera pagina) in base al valore corrente dell'URL.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per configurare quali template caricare e in che circostanza occorre configurare routeProvider come segue:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;angular.module('myApp', []). config(['$routeProvider', function($routeProvider) {&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;$routeProvider&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;.when('/', {&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;templateUrl: 'views/home.html',&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;controller: 'HomeController'&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;});&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;}]);&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;Si specifica l'url (&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;“/”&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; nell'esempio) e che template e controller verranno utilizzati. Per semplicità sono stati riportati solamente alcune proprietà esprimibili, per un elenco esaustivo si rimanda alla &lt;a href=&quot;https://docs.angularjs.org/api/ngRoute/service/$route&quot;&gt;documentazione &lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://docs.angularjs.org/api/ngRoute/service/$route&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;di ngRoute&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;Passando degli argomenti (con &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;“:”&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; ) attraverso l'URL, AngularJS provvederà ad effettuare il parsing e a creare un array chiamato &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt;&lt;i&gt;routeParams&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;&lt;span lang=&quot;it-IT&quot;&gt; utilizzabile dal controller che gestisce la view. E poiché l'utente deve solamente scrivere la funzione costruttore del controllore basterà inserirlo tra gli argomenti e AngularJS si preoccuperà di iniettarlo:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;$routeProvider&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;.when('/inbox/:name', {&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;controller: 'InboxController',&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;templateUrl: 'views/inbox.html'&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;})&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;app.controller('InboxController', function($scope, $routeParams) { &lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;// Qui è abbiamo accesso all'array $routeParams&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;});&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 lang=&quot;zxx&quot;&gt;UI-Router&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;UI-Router è una libreria che ci permette di organizzare l'interfaccia in stati invece che semplici url, questo ci da la possibilità di avere view innestate usando la directive &lt;i&gt;ui-view&lt;/i&gt; invece che &lt;i&gt;ng-view&lt;/i&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Infatti come accade usando &lt;i&gt;ngRoute,&lt;/i&gt; il template definito per lo stato corrente verrà utilizzato per visualizzare il contenuto all'utente, ma usando &lt;i&gt;ui-route&lt;/i&gt; i template possono a loro volta includere altre &lt;i&gt;ui-view&lt;/i&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;La configurazione è leggermente diversa, poiché si usa la keyword &lt;i&gt;“state”&lt;/i&gt; invece di &lt;i&gt;“when”&lt;/i&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;$stateProvider&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;.state('inbox', {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;url: '/inbox/:inboxId',&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;template: '&amp;lt;div&amp;gt;&amp;lt;h1&amp;gt;Welcome to your inbox&amp;lt;/h1&amp;gt;\&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;a ui-sref=&quot;inbox.priority&quot;&amp;gt;Show priority&amp;lt;/a&amp;gt;\&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;div ui-view&amp;gt;&amp;lt;/div&amp;gt;\&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;/div&amp;gt;',&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;controller: function($scope, $stateParams) { $scope.inboxId = $stateParams.inboxId;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;} })&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;.state('inbox.priority', {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;url: '/priority',&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;template: '&amp;lt;h2&amp;gt;Your priority inbox&amp;lt;/h2&amp;gt;'&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;});&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Abbiamo uno stato figlio (specificato usando il &lt;i&gt;“.”&lt;/i&gt;) chiamato &lt;i&gt;inbox.priority&lt;/i&gt;. La ui-view dentro la view padre verrà quindi popolata con il template di &lt;i&gt;inbox.priority&lt;/i&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Quando abbiamo più ui-view innestate possiamo dare un nome ad ognuna e collegare ad ognuna di esse un template diverso. Ad esempio:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;div&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;div ui-view=&quot;filters&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;div ui-view=&quot;mailbox&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;&amp;lt;/div&amp;gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;E ogni sub-view può avere il suo template e controller:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;$stateProvider&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;.state('inbox', {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;views: {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;'filters': {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;template: '&amp;lt;h4&amp;gt;Filter inbox&amp;lt;/h4&amp;gt;',&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;controller: function($scope) {} },&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;'mailbox': {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;templateUrl: 'partials/mailbox.html'&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;}&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;});&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 lang=&quot;zxx&quot;&gt;&lt;/h2&gt;
&lt;h2 lang=&quot;zxx&quot;&gt;Dependency Injection&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;AngularJS permette agli sviluppatori di utilizzare il pattern &lt;i&gt;dependency injection&lt;/i&gt; e specificare le dipendenze di ogni componente senza preoccuparsi di come reperire quest'ultime. A runtime l'&lt;i&gt;injector&lt;/i&gt; di AngularJS si occuperà di reperire le dipendenze specificate e se necessario instanziare i componenti richiesti. Possiamo ad esempio definire un servizio e poi specificare ad AngularJS che un controller ne avrà bisogno a runtime:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;angular.module('myApp', [])&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;.factory('greeter', function() {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;return {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;greet: function(msg) { alert(msg); }&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;} })&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;.controller('MyController', function($scope, greeter) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;$scope.sayHello = function() { greeter.greet(&quot;Hello!&quot;);&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;};&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;});&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Nel costruttore del controller &lt;i&gt;“MyController”&lt;/i&gt; è specificata la dipendenza dal servizio &lt;i&gt;“greeter”&lt;/i&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Annotazione Con Inferenza&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;AngularJS assume che i nomi degli argomenti siano i nomi delle risorse da reperire o instanziare a runtime, e &lt;span lang=&quot;it-IT&quot;&gt;per questo motivo questo approccio può funzionare solo con codice Javascript non minimizzato e non offuscato, poiché AngularJS ha bisogno di effettuare il parsing degli argomenti immutati.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Annotazione Esplicita&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Si possono comunque indicare manualmente i nomi delle dipendenze, per poter minimizzare il codice e non avere problemi specificando la proprietà &lt;i&gt;$inject&lt;/i&gt; di una funzione (che corrisponde ad un controller o un servizio).&lt;/span&gt;&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;var aControllerFactory =&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;function aController($scope, greeter) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;console.log(&quot;LOADED controller&quot;, greeter);&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;// ... Controller&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;};&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;aControllerFactory.$inject = ['$scope', 'greeter'];&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;In questo approccio diventa però importante l'ordine con il quale vengono specificati i parametri della funzione, che deve coincidere con l'ordine delle dipendenze specificate nell'array &lt;i&gt;$i&lt;/i&gt;&lt;i&gt;nject.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Annotazione Inline&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Questo tipo di annotazione è equivalente alla precedente ma permette di definire l'array di dipendenze inline alla definizione della funzione:&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;angular.module('myApp')&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;.controller('MyController',&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;['$scope', 'greeter', function($scope, greeter) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;}]);&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 lang=&quot;zxx&quot;&gt;NgMin&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;NgMin è un tool che sgrava lo sviluppatore dal definire le dipendenze in maniera esplicita e poter comunque minimizzare il codice, trasforma il seguente codice:&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;angular.module('myApp', [])&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;.controller('IndexController', function($scope, $q) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;});&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;automaticamente in questo:&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;angular.module('myApp', [])&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;.controller('IndexController', [ $scope', '$q',&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;function ($scope, $q) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;} ]);&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 lang=&quot;zxx&quot;&gt;&lt;/h2&gt;
&lt;h2 lang=&quot;zxx&quot;&gt;Services&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Prima di introdurre i &lt;i&gt;services &lt;/i&gt;vale la pena ricordare che i controllers sono volativi (e lo sviluppatore non ne controlla il ciclo di vita), quindi non idonei a contenere lo stato dell'applicazione. Per questo motivo, e per fornire una modalità di scambio di dati in maniera consistente esistono i &lt;i&gt;services&lt;/i&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;I &lt;i&gt;services&lt;/i&gt; sono oggetti singleton instanziati dall'injector di AngularJS e lazy-loaded. Come per le &lt;i&gt;directives&lt;/i&gt; AngularJS fornisce molti services built-in (ad esempio &lt;i&gt;$http&lt;/i&gt;) e permette agli sviluppatori di crearne di personalizzati.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per usare un &lt;i&gt;service&lt;/i&gt; è sufficiente elencarlo nelle dipendenze del &lt;i&gt;controller&lt;/i&gt;, &lt;i&gt;directive&lt;/i&gt; o altro &lt;i&gt;service&lt;/i&gt; che vuole invocarlo.&lt;/span&gt;&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Factory&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Il modo più semplice per creare e registrare (per essere trovato dall'injector) un nuovo &lt;i&gt;service&lt;/i&gt; è utilizzare l'API .&lt;i&gt;factory&lt;/i&gt; di &lt;i&gt;angular.module&lt;/i&gt;.&lt;/p&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;angular.module('myApp', []) .&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;factory('UserService', function($http) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;var current_user;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;return {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;getCurrentUser: function() {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;return current_user; },&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;setCurrentUser: function(user) {&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;current_user = user;&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote lang=&quot;zxx&quot;&gt;&lt;p&gt;} }&lt;/p&gt;&lt;/blockquote&gt;
&lt;p class=&quot;western&quot;&gt;La funzione &lt;i&gt;factory&lt;/i&gt; ha due argomenti: il primo specifica il nome del servizio, il secondo è una funzione che verrà eseguita da AngularJS una volta soltanto per instanziare il service&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Service&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;La funzione &lt;i&gt;service&lt;/i&gt; di &lt;i&gt;angular.module&lt;/i&gt; è simile alla funzione factory, ed ha come quest'ultima due argomenti, dei quali il primo indica il nome mentre il secondo è una funzione costruttore, che verrà invocata da AngularJS usando la keyword &lt;i&gt;new&lt;/i&gt;.&lt;/p&gt;
&lt;h3 class=&quot;western&quot;&gt;Provider&lt;/h3&gt;
&lt;p class=&quot;western&quot;&gt;Tecnicamente le funzioni &lt;i&gt;factory&lt;/i&gt; e &lt;i&gt;service&lt;/i&gt; sono solo delle &lt;i&gt;“scorciatoie”&lt;/i&gt; per la funzione &lt;i&gt;provider&lt;/i&gt; che è la vera responsabile per la creazione e registrazione dei vari &lt;i&gt;“services”&lt;/i&gt;.&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;Utilizzando però direttamente &lt;i&gt;provider&lt;/i&gt; è possibile configurare dall'esterno il servizio che si sta definendo attraverso la funzione &lt;i&gt;config&lt;/i&gt;, iniettando alcuni valori.&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Eventi&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per ottenere un accoppiamento più debole tra i diversi componenti dell'applicazione AngularJS mette a disposizione un meccanismo di creazione e propagazione di eventi.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Rispecchiando la gerarchia degli scope, le due operazioni basilari di propagazione degli eventi sono &lt;i&gt;$emit&lt;/i&gt; per risalire la catena di scope dai figli al &lt;i&gt;rootScope&lt;/i&gt; e &lt;i&gt;$broadcas&lt;/i&gt;t con funzionamento opposto, da uno scope ai suoi scope figli.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Quando si scatena un evento è possibile specificare oltre al nome anche degli argomenti.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per registrarsi ad un evento si utilizza la funzione &lt;i&gt;$on&lt;/i&gt; specificando il nome dell'evento di interesse e una funzione di gestione. Un gestore di un evento può anche decidere di interrompere la propagazione dell'evento.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Anche in questo caso AngularJS ha diversi eventi built-in, degno di nota è l'evento &lt;i&gt;$destroy&lt;/i&gt; che viene emesso sullo scope prima che venga distrutto e permette di pulire l'ambiente (ad esempio distruggendo un timeout che si era registrato). Per un elenco dettagliato degli eventi built-in si rimanda alla &lt;a href=&quot;https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on&quot;&gt;documentazione&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Attraverso questo meccanismo è inoltre possibile emettere eventi &lt;i&gt;“globali”&lt;/i&gt; poiché ogni componente dell'applicazione AngularJS può richiedere di farsi iniettare il &lt;i&gt;rootScope&lt;/i&gt; e poi utilizzarlo con la funzione di &lt;i&gt;$broadcas&lt;/i&gt;t.&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Moduli&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;In Javascript non è mai una buona idea utilizzare l'ambiente globale e per questo motivo AngularJS permette di dividere l'applicazione in moduli, nei quali racchiudere le funzionalità.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Quando vogliamo definire un nuovo modulo dobbiamo usare la funzione &lt;i&gt;angular.module&lt;/i&gt; a due argomenti, il primo specifica il nome del modulo, mentre il secondo è una lista di dipendenze da iniettare.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Per ottenere invece il riferimento ad un modulo utilizziamo la funzione &lt;i&gt;angular.module&lt;/i&gt; ad un solo parametro, il nome del modulo. Ottenuto il modulo possiamo definire i nostri componenti per quel modulo (controller/service/directive).&lt;/span&gt;&lt;/p&gt;
&lt;h2 class=&quot;western&quot;&gt;Promises&lt;/h2&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Una promise è un oggetto che rappresenta il valore di ritorno o un eccezione di di una funzione, può essere vista come un proxy per un oggetto.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Storicamente in Javascript sono state utilizzate funzioni di &lt;i&gt;callback&lt;/i&gt; per poter lavorare con dati non disponibili in maniera sincrona, come i dati ottenuti da una richiesta XHR, con le &lt;i&gt;promises&lt;/i&gt; possiamo invece interagire con i dati, supponendo che siano già stati restituiti.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Le &lt;i&gt;promises&lt;/i&gt; permettono di far sembrare funzioni asincrone come se fossero sincrone, permettendoci di catturare sia i valori di ritorno che le eventuali eccezioni, ma sono sempre eseguite in maniera asincrona, per cui possono essere usate senza preoccuparsi del fatto che possano bloccare l'esecuzione.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;AngularJS fornisce il &lt;i&gt;service&lt;/i&gt; &lt;i&gt;$q&lt;/i&gt; per semplificare la gestione delle &lt;i&gt;promises&lt;/i&gt;, una volta creata un &lt;i&gt;promise&lt;/i&gt; con il metodo &lt;i&gt;$q.defer()&lt;/i&gt; possiamo utilizzare il metodo &lt;i&gt;resolve(value)&lt;/i&gt; nel caso l'esecuzione sia andata come previsto e il metodo &lt;i&gt;reject(reason) &lt;/i&gt;per notificare invece l'errore. Un ulteriore metodo è &lt;i&gt;notify(value)&lt;/i&gt; che permette di mandare una notifica (ad esempio se l'esecuzione richiede un tempo lungo potremmo notificare il progresso attraverso questo metodo). Sia nel caso di successo che nel caso di errore la funzione ritornerà la promise creata al chiamante che può interagire con il risultato attraverso la funzione &lt;i&gt;then&lt;/i&gt;().&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;La funzione &lt;i&gt;then&lt;/i&gt;() accetta tre parametri, le funzioni che saranno eseguite in caso di successo, errore e ricezione di notifica. &lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;È&lt;/span&gt; importante notare che le funzioni di successo o fallimento saranno invocate in maniera asincrona appena la &lt;i&gt;promise&lt;/i&gt; è risolta, (solamente una delle due) e con un singolo parametro che indica il risultato in un caso o il motivo del fallimento nell'altro. Mentre la funzione di notifica può essere invocata anche più volte.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;western&quot;&gt;&lt;span style=&quot;font-family: Helvetica, sans-serif;&quot;&gt;Le &lt;i&gt;promises&lt;/i&gt; sono profondamente integrate in AngularJS, infatti anche i services built-in come &lt;i&gt;$http&lt;/i&gt; le utilizzano per restituire i risultati ai chiamanti.&lt;/span&gt;&lt;/p&gt;
</description>
				<pubDate>Wed, 02 Jul 2014 14:00:58 +0200</pubDate>
				<link>https://danielecampogiani.com/blog/2014/07/applicazioni-ibride-e-native-3-angularjs/</link>
				<guid isPermaLink="true">https://danielecampogiani.com/blog/2014/07/applicazioni-ibride-e-native-3-angularjs/</guid>
			</item>
		
	</channel>
</rss>
