Przesiadka z Eclipse ADT na Android Studio.

Korzystając ponad dwa lata z Eclipse do tworzenia aplikacji na Androida przyzwyczaiłem się do myśli, że póki co nie ma nic lepszego i z przymrużeniem oka patrzyłem na wszystkie niedociągnięcia i błędy, które utrudniały codzienną pracę. Kiedy Android Studio pojawiło się w wersji Alpha zarzekałem się, że póki co nie chcę tego używać do czasu czegoś stabilniejszego, a przy wersji Beta, że na pewno nie działa jeszcze tak idealnie. Wynikało to prawdopodobnie z przyzwyczajeń i niechęci do poznawania nowego IDE, jego wszystkich skrótów klawiszowych i ewentualnych błędów. Z wersją 1.0 postanowiłem jednak rozpocząć projekt w Android Studio… już na pewno nie wrócę do Eclipsa!


Gradle

Na pierwszy rzut oka w systemie plików podziało się coś strasznego. Ciężko znaleźć folder src, res czy assets, jest mnóstwo plików nieznanego pochodzenia. Wszystko za sprawą gradle, na którym teraz opierał będzie się Androidowy projekt. Gradle jest to narzędzie do automatycznego budowania projektu. Nie będę rozpisywał się jak to działa, bo i sam nie jestem mistrzem tego typu narzędzi, ale przedstawię kilka podstawowych rzeczy z których przy każdym projekcie na pewno będziecie korzystać. Po utworzeniu nowego projektu w Android Studio (kreator jest intuicyjny i zapewnia dużo wskazówek np. na temat minimalnej wersji SDK) powinniśmy zostać powitani takim widokiem:

Screen z Android Studio

Pierwszą rzeczą, do której zachęca nas Android Studio jest stworzenie layoutu. Jak widać podgląd tworzonego widoku ewoluował i dostajemy atrapę prawdziwego urządzenia. Niby mała rzecz, ale przy projektowaniu interfejsu naprawdę fajnie jest zobaczyć jak to wygląda w całości. Po lewej stronie, na pierwszym pasku znajdziemy strukturę naszego projektu. W zakładce Gradle Scripts mamy dwa pliki build.gradle. Ten odnoszący się do modułu dotyczy stricte naszej aplikacji, natomiast drugi, z nazwą projektu pozwala zmodyfikować konfigurację dla wszystkich pod projektów i submodułów. Wybierzmy i podejrzyjmy plik build.gradle, który odnosi się do naszego modułu, nie projektu.

Pierwszą rzeczą, która rzuca się w oczy jest to, że opcje dotyczące minimalnej wersji SDK, wersji którą kompilujemy projekt oraz docelowej pojawiają się teraz tutaj. Nie znajdziemy ich w AndroidManifest.xml w folderze manifests. Szczególnie warto zapamiętać minSdkVersion, ponieważ Gradle sam będzie weryfikował nam, czy biblioteki, których używamy pozwalają na tak niską wersję SDK i ewentualnie wyświetli błąd jeżeli tak nie jest. Także tu znajdziemy opcję do zmiany wersji kodu i wersji aplikacji. Opcje buildTypes odpowiadają za dodatkowe rzeczy wykorzystywane podczas budowania aplikacji (np. opcje ProGuard’a) i standardowo możemy je zostawić bez zmian.

Ostatnia opcja, dependencies, jest to miejsce gdzie w prosty sposób możemy dodać do naszego projektu biblioteki i projekty, które zostaną automatycznie dociągnięte i dołączone do naszej aplikacji. Wykorzystajmy np. znajdujący się na GitHubie projekt Horizontal ListView użytkownika sephitoth74. W opisie projektu zamieścił on taką linię:

Wystarczy, że skopiujemy ją pod dependencies, a Android Studio samo zorientuje się, że nastąpiła tam zmiana i zaproponuje nam synchronizację projektu, po której będziemy mogli już bez problemu korzystać z biblioteki. Inną metodą, zabierającą jeszcze mniej czasu aby skorzystać z pożądanej biblioteki jest wyszukanie jej z poziomu Android Studio. Aby to zrobić wybierzmy z prawego paska katalog app i wciśnijmy F4 (to tak jak wybrać Open Module Settings z menu kontekstowego). W nowym oknie wybierzmy Dependencies i spod symbolu plusa Library Dependency. Pojawi nam się okno, w którym możemy przeszukiwać najbardziej znane biblioteki i od razu je dodać, np. RoboGuice’a.

Android Studio Gradle

Jeżeli chcemy dodać do aplikacji bibliotekę, którą mamy w formacie *.jar wystarczy wkleić ją do folderu libs, linia compile fileTree(dir: ‚libs’, include: [‚*.jar’]) kompiluje i podłącza wszystkie znajdujące się tam pliki z tym rozszerzeniem. Warto w tym miejscu powiedzieć, że już nigdy więcej nie będzie potrzeby uciążliwego odświeżania zawartości katalogu projektu, które miało miejsce w Eclipsie po dodaniu czegoś nowego. Android Studio wykrywa to automatycznie.


IntelliJ

Android Studio to nic innego jak IntelliJ w wersji Community, odpowiednio zmodyfikowany i przygotowany przez Google. Warto więc zorientować się w możliwościach jakie oferuje nam to środowisko. Dla mnie też jest ono nowością i do teraz odkrywam nowe i przydatne opcje.

Ctrl + Shift + A – najprościej mówiąc jest to opcja do szukania innej opcji. Jeżeli szukasz autoimportu, podzielenia ekranu na dwa bloki czy czegoś, co wydaje Ci się, że ułatwiłoby pracę, a nie wiesz czy istnieje – wpisz w to okno, a znajdziesz to na pewno.

Ctrl + Alt + O / Alt + Enter – opcje do zarządzanie importami. O ile pierwsza z nich potrafi zorganizować importy nawet w całym projekcie po wybraniu odpowiedniego pola to druga służy do zaimportowania danej klasy w kodzie podczas np. jej pisania.

Alt + Insert – pozwala wstawić do kodu metody get() i set() do utworzonych pól, generować z nich konstruktory, dodawać metody wymagane przez interfejsy, toString(), equals() czy tekst o prawach własności.

Ctrl + Q – wyświetla okno z dokumentacją do metody na której znajduje się kursor.

Aby dodać pliki graficzne do res/drawables wystarczy skopiować je z eksploratora plików wprost do tego katalogu w Android Studio. Program zapyta nas wtedy w jakim katalogu chcielibyśmy umieścić obraz. Tworzenie tłumaczeń jest również o wiele bardziej intuicyjne. Przy podglądaniu pliku strings.xml Android Studio będzie proponowało nam jego przetłumaczenie w przygotowanym do tego edytorze. Po jego otworzeniu możemy dodawać nowe języki w wygodny i przejrzysty sposób mając ciągły podgląd na oryginalny tekst i możliwość oznaczenia go jako „nie do przetłumaczenia”

Android Studio Strings

Dodatkowe rzeczy, o których warto wspomnieć to:

  • podczas edycji layout’u za pomocą xml’a możemy skorzystać z opcji Preview. Wtedy, na prawo od okna z kodem pojawi się podgląd widoku, który dynamicznie będzie się odświeżał podczas pisania nowych widoków.
  • emulatory mają wreszcie obudowy, podobnie jak wizualizacje podczas tworzenia layoutów.
  • debbuger wreszcie nie kaleczy oczu i da się z niego bardzo efektownie korzystać! Kto korzystał z debbuger’a w Eclipsie na pewno pamięta jak bardzo nieintuicyjna, przepełniona i niewygodna była jego perspektywa. W IntteliJ’u debbuger to proste i ułatwiające bardzo pracę narzędzie.

 

Podsumowanie

Ten krótki tekst nie jest w stanie niestety oddać nawet małej części tego, co Android Studio może nam zaoferować. W wpisie skupiłem się tylko na niektórych rzeczach, które mnie osobiście zaciekawiły. IntelliJ to o wiele potężniejsze narzędzie niż Eclipse, oferujące szybką i komfortową pracę zaraz po włączeniu.

Jedyne co zostaje w takiej sytuacji dodać to propozycja odwiedzenia tej strony.

RoboGuice – wstrzykiwanie w Androidzie

W tym tutorialu zajmiemy się frameworkiem RoboGuice, który w prosty sposób pozwoli nam zredukować ilość koniecznego do napisania kodu i znacząco przyśpieszy produkcję aplikacji. Warto!


Rzut oka na RoboGuice

Żeby w najprostszy sposób wyjaśnić czym jest to całe wstrzykiwanie rozpatrzmy prosty przykład. Weźmy na to taką prostą aktywność i cały kod potrzebny do zebrania wszystkich potrzebnych nam informacji o niej:

Zakładamy, że mamy jakiś layout z komponentami takimi jak np. ImageView czy Button i odnosimy się do nich poprzez ich identyfikator. Standardowe działanie. Konieczne do wykonania przy tworzeniu każdej kolejnej aktywności czy fragmentu. Teraz zobaczmy ten sam kod z wykorzystaniem RoboGuice.

Nie pobieramy żadnych elementów – wszystko zostaje zdeklarowane na początku poprzez podanie odpowiedniego identyfikatora. Nawet odpowiadający aktywności layout. Od razu możemy przystąpić do pisania funkcjonalności aplikacji – całkowicie pomijając konieczność pobierania odpowiednich widoków.


Jak to właściwie działa

Przejdźmy teraz do właściwej analizy tego co tam się właściwie stało. Na samym początku warto zwrócić uwagę, że nasza aktywność nie dziedziczy już po Activity a po RoboActivity. Jest to konieczne jeżeli chcemy skorzystać ze wstrzykiwania. Pierwszą rzeczą, którą zapewniamy to odpowiedni identyfikator layoutu, z którego ma skorzystać aktywność poprzez @ContentView(int id) nad deklaracją klasy.

Pewną trudnością może być korzystanie z bibliotek, które również wymagają od nas dziedziczenia po ich implementacji aktywności czy fragmentu. Wiele z nich, w zakamarkach swoich stron, udostępnia na szczęście implementacje umożliwiające korzystanie z RoboGuice np. ActionBarSherlock.

Wróćmy jednak do naszego przykładu. Możemy teraz za pomocą wstrzykiwania utworzyć odpowiednie widoki, nie martwiąc się o inicjalizację ich dzięki @InjectView(int resID) View viewŻadnego więcej findViewByID(). Od teraz tuż po wywołaniu super w onCreate() możemy korzystać z gotowych obiektów.


Pobieranie zasobów

Za pomocą RoboGuice możemy pobierać od razu każdy plik z zasobów w naszej aplikacji. Załóżmy, że mamy napis w pliku strings.xml, obrazek w folderze drawables i kolor w colors.xml. Wstrzykujemy je za pomocą @InjectResources(int reID) Object object:

Warto zauważyć, że kolor został pobrany jako Integer. Możemy je od razu wykorzystać:


Obiekty, singleton

Tak naprawdę możemy użyć wstrzykiwania do zainicjalizowania każdego prostego obiektu. Stwórzmy klasę SimpleObject:

Musimy zapewnić pusty konstruktor. W nowej aktywności dodamy możliwość ustawiania wartości w naszym obiekcie i logowania go bez jakiegokolwiek wywołania wcześniej new.

RoboGuice pozwala nam też w bardzo łatwy sposób tworzyć singletony. Wystarczy adnotacja nad deklaracją klasy i kolejne jej wstrzykiwanie będzie tym samym obiektem. Istnieją trzy rodzaje takiej adnotacji:

  • @Singleton – raz utworzony nie jest niszczony przez garbage collector przez cały czas „życia” aplikacji
  • @ContextSingleton – utworzony w ramach aktywności, nie jest usuwany przez cały cykl jej „życia”, przydatny przy tworzeniu aplikacji z fragmentami
  • @FragmentSingleton – analogicznie jak wyżej, nie jest niszczony tak długo jak fragment.

Przykładem użycia może być:


Fragmenty

Pozostaje kwestia fragmentów. Warto zwrócić uwagę, że druga aktywność, którą napisaliśmy w poprzednim punkcie, dziedziczy po klasie RoboFragmentActivity, a fragment analogicznie będzie oczywiście po RoboFragment. Aby ich używać musimy standardowo zapewnić w metodzie onCreateView() zwrócenie poprawnego widoku. Dodanie jednak logiki (listenery, ustawianie napisów, obrazków, kolorów itd.) musi się odbyć po wyjściu z tej metody – w metodzie onStart(). W onCreateView() odwołanie się do wstrzykiwanego obiektu zakończyłoby się rzuceniem wyjątku.


Podsumowanie

Jak widać korzystanie z RoboGuice pozwala nam zaoszczędzić pisania wielu linii i tak nie wnoszącego nic kodu. W szybki sposób możemy pobierać wszystkie potrzebne zasoby, tworzyć singletony. Nie są to jednak wszystkie jego możliwości – chciałem zrobić krótki przelot po najfajniejszych funkcjonalnościach nie robiąc jednocześnie z tego wpisu spolszczenia dokumentacji. Po dokładne zaznajomienie się z wszystkimi funkcjonalnościami i zaletami wstrzykiwania odsyłam na tą stronę.

Kod, wraz z rozbudowanym kodem i przykładami, do pobrania TUTAJ.

 

Używanie TextView z własną czcionką i atrybutami w xml’u cz. 2

W poprzedniej części nadpisaliśmy TextView i w łatwy sposób mogliśmy z niego korzystać wraz z trzema podstawowymi stylami: normalnym, pogrubionym i kursywą. W tej części poznamy inną technikę – dodamy atrybut font, w którym będziemy mogli podać nazwę wybranej czcionki.


Na początek stwórzmy nową klasę CustomTextViewWithAttrs, która tak jak w poprzedniej części w każdym ze swoich konstruktorów wywoła metodę initFont.

Do napisania metody initFont jeszcze wrócimy, póki co zdefiniujmy nowy atrybut dla naszej klasy. W folderze res/values stwórzmy nowy plik xml o nazwie attrs.xml (o ile już go nie mamy w projekcie). Dodajmy tam następujący kod:

Deklarujemy styl dla naszego TextView z pojedynczym atrybutem o nazwie font. Nazwa pod parametrem font nie musi się koniecznie pokrywać z nazwą naszej klasy, ale wprowadza to porządek w kodzie i wiemy do czego odnosi się zdefiniowany styl. Możemy teraz skorzystać z naszego atrybutu i dodać go do naszego layoutu. Na początku musimy wykorzystać nasz plik attrs.xml jako przestrzeń nazw (czyli dodać go jako miejsce, z którego będą pobierane dodatkowe atrybuty i style używane w dalszym kodzie). Łatwo to pominąć, a jest bardzo ważne. Robimy to na samym początku, tak jak tu:

Od teraz, w każdym layoucie, w którym mamy wykonany poprzedni krok możemy użyć naszej klasy z atrybutem font i nazwą dowolnej czcionki w folderze assets:

Pozostaje kwestia pobrania atrybutu w kodzie naszej klasy, odnalezienia danej czcionki i wybrania jej jako tej używanej w TextView. Wracamy w takim razie do tworzenia metody initFont, która będzie wyglądać tak:

Kiedy upewniamy się, ze nasze TextView nie jest w trybie edycji, pobieramy tablicę atrybutów z którymi zostało ono zdefiniowane w pliku xml, odnajdujemy atrybut font i ustawiamy fonta powiązanego z wprowadzoną nazwą. Mówiąc szczerze ciężko mi sobie wyobrazić aplikację w której moglibyśmy użyć wielu czcionek i realnie skorzystać z napisanej przez nas funkcjonalności, ale na tym przykładzie prosto nauczyć się jak zdefiniować własne atrybuty – co można już wykorzystać w o wiele ciekawszy sposób.

Projekt, wraz z kodem części pierwszej, można pobrać TUTAJ.

Używanie TextView z własną czcionką i atrybutami w xml’u cz. 1

Niejednokrotnie podczas tworzenia dużych, złożonych aplikacji nasze layouty będą składały się w większości z tekstu. Problem zaczyna się kiedy chcemy skorzystać z własnej czcionki i używać jej w całym projekcie. Prymitywnym rozwiązaniem jest ustawianie jej za pomocą:

Jednak jeżeli mielibyśmy to robić w stu kolejnych miejscach  w naszym kodzie stałoby się to mega nieefektywne. Poniżej przedstawię dwa popularne rozwiązania, które możemy wykorzystać chcąc zdefiniować TextView z naszą czcionką.


Piszemy Text View

Najprostszą i najefektywniejszą metodą używania swojego fontu (tak, wiem, że czcionka i font to nie to samo, ale będę te pojęcia perfidnie mieszał) jest zdefiniowanie własnego TextView w trzech podstawowych stylach – normalnym, pogrubionym oraz kursywie – tak aby atrybut textStyle działał wraz z naszą czcionką (niestety, nie robi tego z automatu – potrzebujemy trzy osobne pliki czcionek po jedną dla każdego rodzaju).  Zaopatrujemy się więc w jakiegoś darmowego fonta (dafont FTW), a potem wrzucamy go do folderu assets naszego projektu. Jeżeli jesteśmy maniakami porządku możemy w folderze assets stworzyć folder fonts, wrzucić je tam, a następnie odwoływać się do naszej czcionki przez nazwę fonts/myFont.otf. Ja użyję dwóch pobranych czcionek: „łapkową”  Ennobled Pet oraz Linux Libertine (z czego z tych wybrałem po jednej reprezentującej kursywę, pogrubienie i regularny font). Tworzymy nową klasę w naszym projekcie. Ustawiamy ją tak, żeby dziedziczyła po TextView.

No dobra, nasze IDE powinno teraz krzyczeć, że musimy zapewnić konstruktor. TextView, posiada 3 rodzaje konstruktora- każdy kolejny z nowym parametrem. Dodajmy je wszystkie:

Nasza klasa zachowuje się teraz jak czyste, standardowe TextView. Pora dodać naszą czcionkę. Napiszmy metodę initFont, w której zmienimy czcionkę.

Na początku musimy stwierdzić, czy nasza czcionka nie jest w trybie edycji. isInEditMode to metoda klasy View (więcej na jej temat w dokumentacji), dzięki której wiemy, że możemy dokonać zmiany w naszym widoku podczas jego tworzenia. Nie zapewnienie tej funkcjonalności może skutkować rzuceniem wyjątku. Jeżeli już jesteśmy pewni, że możemy zmieniać nasze pole tekstowe tworzymy obiekt klasy Typeface otrzymując czcionkę z folderu assets, a następnie ustawiamy ją na naszym TextView.

initFont umieszczamy teraz w każdym konstruktorze, zaraz po wywołaniu metody super, tak jak w tym:

Teraz wystarczy już tylko zamiast TextView stosować w xml’u napisaną przez nas klasę:

 Cudnie, po dodaniu tego do swojego layoutu mamy:

customtextview_1


Działanie atrybutu textStyle

Zmodyfikujmy teraz działanie metody initFont tak, aby potrafiła wykorzystać atrybut textStyle i wczytała poprawną czcionkę. Jeżeli nie ma atrybutów (np. z konstruktora z samym kontekstem) to nadal używamy naszego „łapkowego” fonta.

Od teraz nasza metoda initFont jest metodą initFont( AttributeSet attrs), czyli pobiera zbiór atrybutów jakie podano w xml’u, wyciąga ten o nazwie textStyle i w zależności od niego ustawia konkretnego fonta. Przykładowy konstruktor wygląda teraz tak:


W tej części tutoriala to już wszystko. W następnej spróbujemy dodać własny atrybut do TextView dzięki któremu będziemy mogli z poziomu xml’a wybierać jakiej czcionki chcemy użyć.

Projekt, z dodatkowymi przykładami, można pobrać TUTAJ.