{"id":11796,"date":"2016-06-06T14:53:21","date_gmt":"2016-06-06T12:53:21","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=11796"},"modified":"2016-06-07T14:49:25","modified_gmt":"2016-06-07T12:49:25","slug":"butterknife-field-and-method-binding-for-android-views","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/butterknife-field-and-method-binding-for-android-views\/","title":{"rendered":"ButterKnife: Field and method binding for Android views"},"content":{"rendered":"<p>Durante lo <strong>sviluppo\u00a0di un&#8217;applicazione Android<\/strong>, uno degli aspetti cui \u00e8 necessario far caso \u00e8 la manipolazione dinamica del layout tramite codice Java includendo sia la gestione dei dati che degli eventi. Per fare ci\u00f2, \u00e8 necessario familiarizzare con due elementi:<\/p>\n<ul>\n<li>il metodo <em>findViewById<\/em> che recupera il riferimento ad una View in base all&#8217;id assegnatole;<\/li>\n<li>i <em>listener<\/em>, oggetti tramite i quali la nostra app organizza la sua reazione agli eventi.<\/li>\n<\/ul>\n<p>Tutto ci\u00f2 richiede molto codice, a volte ripetitivo, la cui quantit\u00e0 spesso mina la produttivit\u00e0 dello sviluppatore. In questo tutorial, vediamo pertanto un possibile antidoto che prende la forma di una libreria piccola, ma ricca di funzionalit\u00e0:\u00a0<a href=\"https:\/\/github.com\/JakeWharton\/butterknife\" target=\"_blank\">ButterKnife<\/a>.<\/p>\n<h2>ButterKnife: integrazione e tratti principali<\/h2>\n<p>Questo strumento deve prima di tutto essere incluso all&#8217;interno del nostro <strong>progetto Android Studio<\/strong>, operazione che grazie a Gradle risulta piuttosto agevole. Inseriamo il seguente elemento nel blocco <em>dependencies<\/em> del file <strong>build.gradle<\/strong> asservito al nostro modulo di progetto:<\/p>\n<pre class=\"lang:java decode:true \">compile 'com.jakewharton:butterknife:8.0.1'<\/pre>\n<p>La versione 8.0.1, come si presume, \u00e8 la pi\u00f9 recente al momento della stesura del tutorial: andr\u00e0 poi sostituita con quella opportuna in fase di utilizzo.<\/p>\n<p>Dopo la modifica il progetto deve essere sincronizzato con i file build.gradle tramite la pressione dell&#8217;apposito pulsante\u00a0<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/androidstudio_syncprojectwithgradle.jpg\" rel=\"attachment wp-att-11797\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-11797\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/androidstudio_syncprojectwithgradle.jpg\" alt=\"androidstudio_syncprojectwithgradle\" width=\"23\" height=\"27\" \/><\/a>\u00a0.<\/p>\n<p>ButterKnife viene utilizzato tramite <strong>annotazioni<\/strong> in base alle quali sar\u00e0 prodotto del codice senza ricorrere alla costosa (in termini di prestazioni) Reflection di Java.<\/p>\n<h2>L&#8217;esempio<\/h2>\n<p>L&#8217;esempio che segue illustra l&#8217;utilizzo delle libreria tramite un semplice layout:<\/p>\n<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_01.jpg\" rel=\"attachment wp-att-11798\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-11798 size-medium\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_01-274x300.jpg\" alt=\"butterknife-android_img_01\" width=\"274\" height=\"300\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_01-274x300.jpg 274w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_01-300x329.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_01.jpg 428w\" sizes=\"auto, (max-width: 274px) 100vw, 274px\" \/><\/a><\/p>\n<p>E&#8217; composto da tre elementi: una EditText, un Button ed una ListView. Al click del pulsante &#8220;Salva&#8221; il testo scritto nella EditText &#8211; a patto non sia vuota &#8211; viene accodato all&#8217;Adapter che alimenta la ListView. Inoltre, al click di un item della Listview apparir\u00e0 un Toast che dichiara quale elemento \u00e8 stato selezionato:<\/p>\n<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_02.jpg\" rel=\"attachment wp-att-11799\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-11799 size-medium\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_02-296x300.jpg\" alt=\"butterknife-android_img_02\" width=\"296\" height=\"300\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_02-296x300.jpg 296w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_02-50x50.jpg 50w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_02-300x304.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/02\/butterknife-android_img_02.jpg 423w\" sizes=\"auto, (max-width: 296px) 100vw, 296px\" \/><\/a><\/p>\n<p>L&#8217;esempio \u00e8 piuttosto immediato\u00a0in quanto non ha altra finalit\u00e0 se non quella di mostrare come ButterKnife pu\u00f2 semplificare la vita dello sviluppatore.<\/p>\n<h2>Il codice<\/h2>\n<p>Vediamo subito il <strong>layout<\/strong> (per noi \u00e8 il file \/res\/layout\/activity_main.xml):<\/p>\n<pre class=\"lang:xhtml decode:true \">&lt;RelativeLayout xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"\r\n    android:padding=\"@dimen\/activity_horizontal_margin\"&gt;\r\n    &lt;EditText\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:id=\"@+id\/txt\"\r\n        android:layout_alignParentTop=\"true\"\/&gt;\r\n\r\n    &lt;Button\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"wrap_content\"\r\n        android:id=\"@+id\/save\"\r\n        android:layout_below=\"@id\/txt\"\r\n        android:text=\"Salva\"\/&gt;\r\n\r\n    &lt;ListView\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\"\r\n        android:layout_below=\"@id\/save\"\r\n        android:id=\"@+id\/list\"\r\n        android:layout_marginTop=\"10dp\"\/&gt;\r\n\r\n&lt;\/RelativeLayout&gt;\r\n<\/pre>\n<p>Ricordiamo anche che abbiamo definito una <strong>risorsa stringa<\/strong>, nel file \/res\/values\/strings.xml, di nome msg:<\/p>\n<pre class=\"lang:xhtml decode:true\">&lt;resources&gt;\r\n    &lt;string name=\"app_name\"&gt;ButterKnife&lt;\/string&gt;\r\n    &lt;string name=\"msg\"&gt;Elemento cliccato:&lt;\/string&gt;\r\n&lt;\/resources&gt;\r\n<\/pre>\n<p>Nel codice Java che vedremo, ButterKnife fornir\u00e0 i seguenti contributi:<\/p>\n<ul>\n<li>con l&#8217;annotazione <em>@Bind<\/em> ci permetter\u00e0 di recuperare in automatico una View e collegarla ad un membro della classe senza il ricorso al metodo\u00a0<em>findViewByID,\u00a0<\/em>ma\u00a0semplicemente\u00a0indicando l&#8217;id del widget che ci interessa\n<pre class=\"lang:java decode:true\">@Bind(R.id.txt) EditText txt;\r\n<\/pre>\n<\/li>\n<li>con <em>@BindString<\/em> avremo istantaneamente il valore di una risorsa stringa in un membro String:\n<pre class=\"lang:java decode:true \">@BindString(R.string.msg) String msg;\r\n<\/pre>\n<p>Esiste un omologo per ogni altro tipo di risorse <em>valore<\/em>;<\/li>\n<li>i listener saranno gestiti con dei semplici metodi e l&#8217;annotazione premessa specificher\u00e0 evento e widget cui sono collegati. Questo, ad esempio, \u00e8 il click sul pulsante:\n<pre class=\"lang:java decode:true \">@OnClick(R.id.save)\r\n    public void submit() {\r\n        \/\/ codice da eseguire\r\n    }\r\n<\/pre>\n<p>mentre quest&#8217;altro \u00e8 l&#8217;organizzazione di un evento di click sull&#8217;item di una ListView:<\/p>\n<pre class=\"lang:java decode:true\">@OnItemClick(R.id.list)\r\n    void onItemSelected(int position) {\r\n        \/\/ codice da eseguire\r\n    }\r\n<\/pre>\n<\/li>\n<\/ul>\n<p>Chi \u00e8 abituato alla solita sintassi delle Activity Android riconoscer\u00e0 subito i benefici di questa libreria. Ecco il codice completo dell&#8217;<strong>Activity<\/strong>:<\/p>\n<pre class=\"lang:java decode:true\">public class MainActivity extends AppCompatActivity {\r\n\r\n    @Bind(R.id.txt)\r\n    EditText txt;\r\n\r\n    @Bind(R.id.list)\r\n    ListView list;\r\n\r\n    @BindString(R.string.msg) String msg;\r\n\r\n    private ArrayAdapter&lt;String&gt; adapter;\r\n\r\n    @Override\r\n    protected void onCreate(Bundle savedInstanceState) {\r\n        super.onCreate(savedInstanceState);\r\n        setContentView(R.layout.activity_main);\r\n\r\n        ButterKnife.bind(this);\r\n\r\n        adapter=new ArrayAdapter&lt;String&gt;(this, android.R.layout.simple_list_item_1);\r\n        list.setAdapter(adapter);\r\n\r\n    }\r\n\r\n    @OnClick(R.id.save)\r\n    public void submit() {\r\n        String t=txt.getText().toString();\r\n        if (t.length()&gt;0) {\r\n            adapter.add(t);\r\n            txt.setText(\"\");\r\n        }\r\n    }\r\n\r\n    @OnItemClick(R.id.list)\r\n    void onItemSelected(int position) {\r\n        Toast.makeText(MainActivity.this, msg+adapter.getItem(position), Toast.LENGTH_SHORT).show();\r\n    }\r\n}\r\n<\/pre>\n<p>Fondamentale notare che tutto ci\u00f2 che ha innescato il funzionamento di ButterKnife \u00e8 la chiamata al metodo statico <em>bind<\/em> nell&#8217;<em>onCreate<\/em>:<\/p>\n<pre class=\"lang:java decode:true\">ButterKnife.bind(this);<\/pre>\n<h2>Ulteriori aspetti<\/h2>\n<p>Quello che abbiamo visto ha gi\u00e0 molti vantaggi, ma non \u00e8 che una parte di tutto ci\u00f2 che ButterKnife mette a disposizione: sul <a href=\"http:\/\/jakewharton.github.io\/butterknife\/\" target=\"_blank\">sito\u00a0del progetto<\/a>\u00a0si possono trovare molti altri spunti.<\/p>\n<p>Uno dei principali vantaggi di ButterKnife \u00e8 l&#8217;immediatezza con cui la si inizia ad usare tanto che potremmo considerarla una versione &#8220;soft&#8221; di progetti molto pi\u00f9 corposi e complessi come <a href=\"http:\/\/google.github.io\/dagger\/\" target=\"_blank\">Dagger<\/a>, libreria ormai patrocinata da Google, ma creata da <a href=\"http:\/\/square.github.io\/\" target=\"_blank\">Square Inc.<\/a>, l&#8217;azienda che d\u00e0 lavoro a <a href=\"https:\/\/plus.google.com\/+JakeWharton\" target=\"_blank\">Jake Wharton<\/a>, il creatore di ButterKnife.<\/p>\n<p>Che si riferisca proprio a questo\u00a0la frase riportata sulla pagina GitHub del progetto &#8220;Remember: A <strong>butter knife<\/strong> is like a <strong>dagger <\/strong>only infinitely less sharp.&#8221; ossia &#8220;Ricorda: un coltello da burro \u00e8 come un pugnale solo infinitamente meno tagliente&#8221; ?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Durante lo sviluppo\u00a0di un&#8217;applicazione Android, uno degli aspetti cui \u00e8 necessario far caso \u00e8 la manipolazione dinamica&#8230;<\/p>\n","protected":false},"author":561,"featured_media":12063,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[1616,1615,917],"class_list":["post-11796","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorial-pratici","tag-dagger","tag-dependency-injection","tag-mobile-developers"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/11796","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/561"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=11796"}],"version-history":[{"count":8,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/11796\/revisions"}],"predecessor-version":[{"id":12074,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/11796\/revisions\/12074"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media\/12063"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=11796"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=11796"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=11796"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}