Pobyty na Moravě: úvodní přehled
Důvody, proč jsem vytvořil aplikaci Pobyty na Moravě, jsou dva. Samozřejmě, je to jedna z položek ze seznamu témat, která chci zpracovat. Ale hlavně při programování poslední verze H15 jsem zjistil, že patnáctka už mi nic nedává. De facto jsem jenom programoval, aniž bych se cokoli nového učil. Pobyty na Moravě byl pro mne skok rovnýma nohama přímo do novinek.
Programování samo o sobě bylo velmi jednoduché a přímočaré. De facto se jednalo jenom o definici datové struktury, která bude reprezentovat jednotlivé příspěvky a jejich kategorie. Plus nějaký ten obslužný kód kolem. Ale design, to byla pravá alchymie!
Načítání obsahu webu
Inspirací pro strukturu aplikace mi byl tutoriál - jednoduchá RSS čtečka využívající IntentService
pro načítání obsahu webu. Aplikaci jsem vystavěl podobně.
Vlastní načítání obsahu webu jsem chtěl původně implementovat s využitím rozhraní WordPress XML-RPC, což by znamenalo prakticky nulový zásah do stávající struktury webu. Pro tohle rozhraní již existuje hotová knihovna canbican wordpress-java. Menší nevýhodou je nutnost použít ještě knihovny Redstone XML-RPC library a SLF4J, bez nichž aplikace nešla zkompilovat. Hlavní nevýhoda však spočívá v tom, že pro XML-RPC přístup potřebuji definovat uživatele, který bude mít k příspěvkům práva zápisu. Docela silný kanón na to, že chci vytvořit pouze čtečku. A navíc tohoto uživatele s téměř administrátorskými právy předám každému, kdo si aplikaci stáhne z Google Play™. Nesystémové a bezpečnostní díra.
Pro účel blogu však řešení nezavrhnu úplně. Android má sice vlastní XML parser, knihovna Redstone XML-RPC používá klasický SAX. A ten je potřeba správně nastavit:
System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver");
Načítání obsahu webu jsem proto implementoval pomocí WordPress pluginu JSON Api. Odpadla tím nutnost přidávat do aplikace další tři knihovny: JSON parser je součástí přímo Android API. Ale hlavně odpadla nutnost vytvářet a distribuovat nového uživatele s administrátorskými právy. Nevýhodou je nižší rychlost - WordPress JSON Api je poměrně pomalé. A zatímco XML-RPC vrací příspěvky v surové podobě, jak jsou uloženy v databázi, JSON Api je vrací již zformátované. Tedy perex včetně tlačítka "read more" a tělo příspěvku včetně tlačítek pro sdílení na sociálních sítích. To se však dá snadno vyřešit použitím knihovny jsoup - Java HTML Parser.
Pomocí WordPress JSON Api lze provádět i zápis, to však lze v administrátorském rozhraní WordPressu zakázat. Respektive v případě potřeby je nutno zápis povolit, protože je implicitně zakázaný.
Pro úplnost ještě komponenta pro zobrazování HTML: SufficientlySecure html-textview. Umí zobrazit HTML, avšak zachovává možnost klasického TextView
vlastního načítání obrázků a vlastního zpracování odkazů.
Práce s obrázky
Obrázky načítám a zpracovávám prakticky stejně jako v H15, jenom místo AsyncTask
využívám IntentService
. Obrázkovou cache jsem převzal z H15 jen s minimálními úpravami. Pro vlastní načítání však používám knihovnu Picasso. Odpadá tím potřeba programovat vlastní načítání a zmenšování obrázků, což se hodí zejména při stahování obrázků z Internetu. Knihovnu Picasso doporučují různé Internetové zdroje. A já ji také doporučuji.
Ovládání aplikace
Snad s výjimkou levého šuplíku bylo programování UI jednoduché a přímočaré. Implementovat nekonečný scroll znamenalo pouze správně použít OnScrollListener
:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
View view = findViewById(R.id.article_list);
if(view instanceof ListView) {
ListView listView = (ListView) view;
...
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount!=0) {
loadMore();
}
showUpButton(firstVisibleItem > 0);
}
});
}
...
}
private void loadMore() {
if(!isLoading && !finishedLoading && articles != null) {
isLoading = true;
...
Intent intent = new Intent(this, ArticleListReadService.class);
intent.setAction(ArticleListReadService.ACTION_LOAD_MORE);
intent.putExtra(ArticleListReadService.ARTICLE_OFFSET, articles.size());
intent.putExtra(ArticleListReadService.ARTICLE_RECEIVER, loadMoreReceiver);
startService(intent);
}
}
Některé zdroje doporučují implementovat threshold, aby načítání dalších položek začalo ještě před srolováním na poslední položku. Každopádně je důležité implementovat flag isLoading
, který zabrání vícenásobnému spuštění načítání, a flag finishedLoading
, který indikuje, že seznam načtených položek je kompletní.
Podobně jednoduché bylo i plovoucí tlačítko. Ani nebylo potřeba využít CoordinatorLayout
, postačil FrameLayout
. Pro zobrazení a skrytí plovoucího tlačítka jsem použil metody show()
a hide()
, které zajistí základní animaci - zvětšení a zmenšení. Pro účely aplikace dostačující.
private void showUpButton(boolean visible) {
View v = findViewById(R.id.button_up);
if(v instanceof FloatingActionButton) {
if(visible) {
((FloatingActionButton) v).show();
} else {
((FloatingActionButton) v).hide();
}
}
}
Rolování seznamu nahoru coby reakce na stisk plovoucího tlačítka obstarala metoda smoothScrollToPosition()
. Opět včetně animace rolování nahoru.
public void scrollToTop(View view) {
View v = findViewById(R.id.article_list);
if(v instanceof ListView) {
((ListView) v).smoothScrollToPosition(0);
}
}
Složitější byl levý šuplík. Oficiální tutoriál zřejmě bude fungovat, ale jenom s poslední verzí Androidu. Při použití appcompatu je lepší tenhle tutoriál. Aby byl šuplík zobrazen nad toolbarem, bylo potřeba toolbar explicitně definovat v Activity
. A jak jsem psal, že design byla alchymie, pak největší alchymie nastala právě tady, aby tlačítka a texty v toolbaru měly správnou barvu a pozadí toolbaru byl požadovaný gradient.
Plány do budoucna
I plány do budoucna se nesou ve znamení učení se nových věcí:
- Offline prohlížení - práce s databází plus implementace souborové cache pro obrázky
- Upozorňování na nové příspěvky na webu -
Service
spuštěná jako daemon plus práce s notifikační lištou
Plus další drobné úpravy, aby byla aplikace hezčí, lepší a aby se uživatelům líbila. Věřím, že se to podaří.
Tagy: Android, Pobyty na Moravě, Java