Warsztaty Android, studenckie koło naukowe ISA 2 Artur Zochniak, Jan Kołaciński, Paweł Szczerbicki, Piotr Maćkowiak, Arkadiusz Szydełko, Łukasz Pijet pod merytoryczną opieką Pawła Kapały (Tieto), 2 czerwca 2011r
Plan prezentacji: 1. Co to jest SQLite i czym się różni od innych systemów baz danych 2. Tworzenie struktury baz danych, typy danych i DDL 3. Zapytania SQL 4. Android & SQLite, kursory 5. ListActivity 6. Adaptery
Co to jest SQLite i czym się róŝni od innych systemów baz danych Co to jest SQLite: System zarządzania bazą danych oraz biblioteka C implementująca taki system, obsługująca język SQL (ang. Structured Query Language). Biblioteka implementuje standard SQL, daje możliwość używania bazy danych bez konieczności uruchamiania osobnego procesu RDBMS. Bazy danych zapisywane są jako pliki binarne. Istnieje projekt oferujący szyfrowanie baz danych SQlite na bieżąco.
Co to jest SQLite i czym się róŝni od innych systemów baz danych Relacyjna baza danych baza danych skonstruowana z tabel (relacji), wyraźnie oddzielonych zbiorów, rodzaj DBMS (system zarządzania danymi), przechowująca informacje w postaci powiązanych tabeli. Źródło: http://www.webopedia.com/term/r/rdbms.html
Co to jest SQLite i czym się róŝni od innych systemów baz danych ACID - opis warunków, jakie powinny spełniać transakcje (zbiór operacji), w bazach danych. ACID jest skrótem od angielskich słów: atomicity - atomowość, consistency - spójność, isolation - izolacja, durability - trwałość. SQLite udostępnia transakcje ACID oraz implementuje większość standardu SQL 92 (strukturalny język zapytań używany do tworzenia, modyfikowania, oraz umieszczania i pobierania danych z bazy danych).
Co to jest SQLite i czym się róŝni od innych systemów baz danych Firmy wspierające rozwój SQLite
Co to jest SQLite i czym się róŝni od innych systemów baz danych Mozilla Firefox - w bazach danych przechowywane są profile użytkowników Android - przechowywanie danych użytkownika Avast! Antivir baza wirusów Mac OS X - od wersji 10.4 (Tiger), warstwa przechowywania danych dla Core Data API Trac - zintegrowany system zarządzania projektami, używa domyślnie SQLite do przechowywania danych Mozy - kopie zapasowych w trybie online, przechowywuje dane konfiguracyjne, ustawienia kopii, stanu danych itp.
Co to jest SQLite i czym się róŝni od innych systemów baz danych Zalety: rozmiar: około 300 kb, skompilowana i działająca biblioteka. brak dodatkowego procesu zarządzającego relacyjną bazą danych implementuje większość standardu SQL92 cała baza danych w jednym pliku (do 2TB), niezwykle prosta w utrzymaniu zapewnia transakcyjność (ACID) dostępna na licencji Open Source, kod źródłowy dostępny w całości 1000 identycznych zapytań SELECT * FROM tabela: SQLite - 0.77956 sek. SQLite (Memory) - 0.76029 sek. MySQL (MyISAM) - 0.86335 sek. MySQL (InnoDB) - 1.31506 sek. MySQL (Memory) - 0.77291 sek. Źródło: http://bukox.pl/php/sqlite-alternatywa-dla-mysql/
Tworzenie struktury bazy danych Artur Zochniak
Terminal bazy danych w Android SDK Dostęp do terminala bazy danych moŝna uzyskać uruchamiając: android-sdk-windows\tools\sqlite3 baza.db np. aby utworzyć bazę w pliku baza.db, sqlite3 baza.db
Terminal bazy danych SQLite3, tworzenie tabeli tworzymy bazę poleceniem: sqlite3 baza.db Jeśli zaszłaby potrzeba opuszczenia terminala, wystarczy wpisać exit poprzedzone kropką (dot-command):.exit baza jest pusta moŝna to sprawdzić komendą sqlite3 baza.db SELECT * FROM SQLITE_MASTER; SQLITE_MASTER to specjalna nazwa tabeli, do której odwołanie zwraca w wyniku tabele w bazie lub poleceniem-z-kropką w terminalu SQLite.tables tworzenie pierwszej tabeli: CREATE TABLE tabela(id INTEGER PRIMARY KEY, kol1 VARCHAR(10), kol2 SMALLINT);
SQLite3 wypisywanie tabel w bazie Wykonanie polecenia SELECT * FROM SQLITE_MASTER; zwróci informację o istniejącej juŝ tabeli, aby wypisywać dane w takiej postaci naleŝy wywołać:.mode line
SQLite3 operacje na tabelach Usunięcie tabeli: DROP TABLE nazwa_tabeli; Zmiana nazwy tabeli: sqlite>.tables tabela sqlite> ALTER TABLE tabela RENAME TO tbl; sqlite>.tables tbl
SQLite3 operacje na tabelach Zmiana nazwy kolumny w tabeli: SQLite3 nie pozwala na bezpośrednią zmianę nazwy kolumny, aby to uzyskać naleŝy stworzyć nową tabelę z nową strukturą, a następnie wypełnić nową tabelę danymi ze starej. CREATE TABLE bohaterowie (bohater VARCHAR(10)); INSERT INTO bohaterowie VALUES ('d''arc Joanna'); INSERT INTO bohaterowie (bohater) VALUES ('William'); CREATE TEMPORARY table kobiety (imie VARCHAR(10)); INSERT INTO kobiety SELECT bohater FROM bohaterowie WHERE bohater LIKE "%a"; DROP TABLE bohaterowie; --usuwamy tabelę SELECT * FROM kobiety;
SQLite3 dodawanie rekordów do tabeli wykonanie poleceń: CREATE TABLE tbl (sentence VARCHAR(10), pts INT NULL DEFAULT 0); INSERT INTO tbl VALUES ('hello!',10); INSERT INTO tbl (pts, sentence) VALUES (20, 'goodbye');.mode column SELECT * FROM tbl; doda do tabeli 2 rekordy
Podstawowe typy danych w bazie SQLite NULL - Pusta (niezdefiniowana) wartość, INTEGER - Liczba całkowita (ze znakiem) przechowywana na od 1 do 8 bajtów (w zaleŝności od potrzeby), REAL - Liczba zmiennoprzecinkowa przechowywana na 8 bajtach (notacja IEEE floating point number), TEXT - Tekst kodowany przy pomocy UTF-8, UTF-16BE lub UTF-16LE, BLOB - (ang. kropelka, kleks, akronim Binary Large Object) Dane przechowywane w postaci binarnej (tak jak pliki na dysku).
Typy danych SQLite, c.d. Boolean liczba całkowita (INTEGER), 0 (fałsz), 1 (prawda), Data moŝe być przechowywana jako: TEXT w konwencji ISO8601 ("YYYY-MM-DD HH:MM:SS.SSS"), REAL jako ilość dni (wraz z częścią ułamkową) kalendarza Juliańskiego (w którym średnia długość roku to 367,25 dni), które upłynęły od północy w Greenwich, 24. października 4714p.n.e. (w kalendarzu Gregoriańskim), INTEGER - czas Unix Time, ilość sekund, które upłynęły od północy 1. stycznia 1970, 1970-01-01 00:00:00 UTC (Coordinated Universal Time, Greenwich Mean Time).
Pokrewieństwo typów (type affinity) SQLite nie zmusza nas do definiowania jakiego typu dane będą przechowywane w danej kolumnie, jednak w celu zwiększenia kompatybilności z innymi bazami danych, moŝemy skłonić bazę, aby przechowywała dane w pewnej kolumnie uŝywając określonej grupy typów, jest 5 rodzin typów, które moŝemy nadać kolumnom: TEXT (tekstowy, zaliczamy doń równieŝ dane binarne), NUMERIC (numeryczny), INTEGER (całkowity), REAL (zmiennoprzecinkowy), NONE (dowolny; niezdefiniowany), jeśli zdefiniujemy typ danych w kolumnie, a następnie spróbujemy dodać inny typ danych, to, jeśli istnieje rozsądny sposób przekonwertowania dodawanej wartości do typu kolumny, konwersja zostanie wykonana.
Reguły pokrewieństw typów 1. Jeśli typ zawiera w nazwie INT, to zostaje przydzielony do rodziny INTEGER, 2. jeśli typ kolumny zawiera podciąg jednego z ciągów: "CHAR" lub "CLOB" lub "TEXT" to kolumna ta będzie z rodziny TEXT. NaleŜy zauwaŝyć, Ŝe VARCHAR zawiera "CHAR" i dlatego jest typu TEXT, 3. jeśli kolumna zawiera podciąg znaków "BLOB" lub nie ma zdefiniowanego typu, to zostaje ona przyporządkowana do rodziny typów NONE, 4. jeśli typ kolumny zawiera podciąg "REAL" lub "FLOA" lub "DOUB", to jest ona pokrewna z REAL, 5. w kaŝdym innym wypadku typ afiniczny to NUMERIC.
Typy danych w SQLite Nazwa typu danych uŝyteczna w poleceniu CREATE TABLE Pokrewieństwo typu, resulting affinity reguła przydzielania pokrewieństwa typu INT INTEGER TINYINT SMALLINT MEDIUMINT CHARACTER(20) VARCHAR(255) VARYING CHARACTER(255) NCHAR(55) BIGINT UNSIGNED BIG INT INT2 INT8 NATIVE CHARACTER(70) NVARCHAR(100) TEXT CLOB INTEGER 1 TEXT 2 BLOB lub nie sprecyzowano typu REAL DOUBLE NUMERIC DECIMAL(10,5) BOOLEAN DOUBLE PRECISION FLOAT DATE DATETIME NONE 3 REAL 4 NUMERIC 5
Przykłady przynaleŝności do pokrewieństwa typów CREATE TABLE t1( t TEXT, -- text affinity by rule 2 nu NUMERIC, -- numeric affinity by rule 5 i INTEGER, -- integer affinity by rule 1 r REAL, -- real affinity by rule 4 no BLOB -- no affinity by rule 3 ); do kaŝdego z pól wpisujemy tę samą wartość, jednak w rezultacie są one odpowiednio zamienione, niezaleŝnie jaki typ jest podany w definicji tabeli jeśli nie będzie odpowiedniej konwersji do typu kolumny, zostanie dodana do tabeli wartość typu dodawanego. dodanie rekordu ('500.0', '500.0', '500.0', '500.0', '500.0') spowoduje, Ŝe w bazie zostaną zapisane (text)500.0, (int)500, (int)500, (real)500.0, (text)500.0
Pliki baz danych i ich lokalizacja w systemie Android Jan Kołaciński
Lokalizacja plików baz danych Baza danych naszej aplikacji znajduje się na androidzie w katalogu: /data/data/nazwa.pakietu/databases/
Nazwa bazy danych Nazwa bazy danych będzie równocześnie nazwą pliku, który system Android przechowuje w folderze: /data/data/<nazwa_aplikacji>/databases/
SQLite SELECT INSERT DELETE UPDATE Paweł Szczerbicki
Zapytanie SELECT Jedno z najbardziej rozbudowanych zapytań w SQLite Zwraca dane z tabeli, bądź tabel (join) w wielu róŝnych konfiguracjach Wyniki mogą być odpowiednio filtrowane Przykładowe zapytanie SELECT (kolejność) SELECT DISCTINCT (*) FROM studenci WHERE wydzial='eka' OR imie='pawel'; SELECT pole1,pole2.. FROM nazwa_tabeli WHERE warunki;
Zapytanie SELECT Aliasy są uŝywane do nadawania kolumnom i tabelom opcjonalnej przy wyświetlaniu i edytowaniu SELECT imie_id AS 'imię' FROM tabela t WHERE t.imie LIKE 'A%' ; SELECT imie_id 'imię' FROM tabela WHERE imie LIKE 'A%' ;
Zapytanie SELECT Zapytanie agregujące(aggregate query) np: SELECT COUNT(*) AS "ilosc" FROM tabela WHERE imie LIKE 'A%' ; Zwracają podsumowanie tabeli np. liczą elementy, średnią itd.
Zapytanie SELECT Zapytanie nieagregujące(non-aggregate query) SELECT name "imię", postcode "kod" FROM tabela WHERE name='adam'; Zwraca wiersze bądź całą tabele danych
Zapytanie SELECT WHERE, ORDER BY: najpierw przetwarzane jest WHERE, wiersze dla których da ono wartość FALSE wyłączane są z przetwarzania SELECT last_name '"nazwisko", employee_id "numer pracownika" FROM employees WHERE employee_id BETWEEN 110 AND 120 ORDER BY employee_id DESC;
Zapytanie SELECT GROUP BY, agregacja: GROUP BY tworzy grupy danych o tych samych atrybutach i wyświetla je razem bez powtórzeń SELECT department_id "numer departamentu", COUNT(*) "ilosc pracownikow" FROM employees GROUP BY department_id ORDER BY "ilosc pracownikow" DESC;
Zapytanie SELECT SELECT department_id "numer departamentu", MIN(salary) "minimalna wyplata", MAX (salary) "maksymalna wyplata" FROM employees WHERE salary>7000 GROUP BY department_id ORDER BY department_id; Funkcja agregując bez GROUP BY zawsze zwróci jeden wiersz danych nawet gdy nie ma danych wejściowych
Zapytanie SELECT Wyświetlanie danych z kilku tabel (join) Bez JOIN (dane z dwóch tabel) SELECT d.department_name, l.city FROM departments d, locations l WHERE d.location_id=l.location;
Zapytanie SELECT JOIN ON ( dane z kilku tabel ) SELECT d.department_name, l.city FROM departments d JOIN locations l ON d.location_id=l.location_id; JOIN USING ( dane z kilku tabel ) SELECT department_name, city FROM departments JOIN locations USING (location_id);
Zapytanie SELECT NATURAL JOIN te same nazwy kolumn (ukryty using) SELECT department_name, city FROM departments NATURAL JOIN locations;
Zapytanie SELECT HAVING: Pozwala na przefiltrowanie wyników zgrupowanych klauzurą GROUP BY w zapytaniach agregujących. Schemat ogólny: SELECT department_id, COUNT(*) FROM employees WHERE department_id>20 GROUP BY department_id HAVING COUNT(*) > 5; SELECT pole1,.. FROM tabela WHERE warunki GROUP BY pole[x] HAVING kryteria_grupowania
Zapytanie SELECT Zapytania zagnieŝdŝone: Wewnętrzne zapytanie SELECT jest źródłem danych dla zewnętrznego SELECT EXISTS czy istnieje co najmniej jeden departament o mniejszym ID niŝ podany SELECT department_name FROM departments WHERE department_id > EXISTS (SELECT department_id FROM departments WHERE department_name='finance' LIMIT 1);
Kolejność działań SELECT department_id "numer departamentu", MIN(salary) "minimalna wyplata", MAX (salary) "maksymalna wyplata" FROM employees WHERE salary>7000 GROUP BY department_id ORDER BY department_id HAVING MAX(salary)>2000 LIMIT 5;
Zapytanie DELETE SłuŜy do usuwania danych z tabel Usuwa wiersze wg podanych warunków Schemat ogólny: DELETE FROM table_name WHERE some_column=some_value;
Zapytanie DELETE Trigger to funkcja, która jest uruchamiany w momencie wykonania pewnej akcji na bazie danych. Zawiera ona szereg instrukcji lub zapytań, które mają zostać wykonane po lub przed wywołaniem danej akcji. DELETE w triggerze moŝe być wykonane tylko dla tabeli do której został przypisany trigger
Zapytanie DELETE DELETE i WHERE DELETE FROM departments WHERE department_name='eka'; DELETE i LIMIT DELETE FROM departments ORDER BY department_id DESC LIMIT 10;
Zapytanie DELETE Optymalizacja usuwania całej tabeli, bez przeglądania wierszy: nie działają triggery ale za to usuwanie jest szybsze Problem z liczenie usuniętych wierszy rozwiązany w wersji 3.6.5
Zapytanie INSERT Tworzy nowy wiersz tabeli i wraz z wartościami : Unikalny klucz główny Wypełnione pola NOT NULL Schemat ogólny INSERT INTO table_name (column1, column2, column3,...) VALUES (value1, value2, value3,...)
Zapytanie INSERT INSERT bez INTO: MoŜliwe jest wykonanie zapytania bez nazw kolumn w INTO. Wtedy dane zostaną wprowadzone po kolei do kolumn. W VALUES pierwsza z lewej ląduje w pierwszej kolumnie INSERT INTO departments VALUES (322, London, 713245678);
Zapytanie INSERT INSERT i SELECT INSERT INTO employees (id, number, department) SELECT id, number, department FROM employees WHERE department_id = 222;
Zapytanie INSERT INSERT OR REPLACE: Dodaje lub zamienia wartości jeŝeli klucz główny się powtarza INSERT OR REPLACE INTO departments(department_id,city,number) VALUES (322, London, 713245678); INSERT w triggerze: Wykorzystywany jest do aktualizacji tabel. JeŜeli np. zostanie zwolniony pracownik (usunięty wiersz w tabeli) INSERT uŝyty w triggerze moŝe go przenieść do innej tabeli np. tabela zwolnień
Zapytanie UPDATE Wykonujemy je gdy jakieś rekordy są nieaktualne lub po prostu źle wpisane Schemat ogólny UPDATE table_name SET column1=value, column2=value2,... WHERE some_column=some_value
Zapytanie UPDATE JeŜeli w UPDATE brakuje WHERE wszystkie wiersze zostaną zmodyfikowane UPDATE w triggerach moŝe się odnosić jedynie do tabeli dla której trigger został stworzony W triggerach nie stosujemy LIMIT i ORDER BY LIMIT tak jak w DELETE
Zapytanie UPDATE Przykład: UPDATE departments SET department_name='studentki' WHERE department_name='studenci';
UNION UNION łączy wyniki wielu zapytań JOIN łączył kolumny tabel UNION łączy wiersze SELECT id, name FROM employees UNION SELECT department_id FROM departments;
Dobre praktyki Pisanie zapytań wielkimi literami (SELECT, INSERT) KaŜde zapytanie w nowej linijce (WHERE, SELECT, FROM)
Android - SQLite kursory Piotr Maćkowiak
Tworzenie Bazy public class DatabaseAdapter { } Następnie klasę naleŝy rozbudować o odpowiednie zmienne: private static final String DB_NAME = "database.db"; private static final String DB_TABLE = "anytable"; NaleŜy równieŝ dodać pole z wersją bazy private static final int DB_VERSION = 1; System wykorzystuje tą zmienną by sprawdzić, czy aplikacja posiada aktualną strukturę bazy danych.
Tworzenie Bazy Kolejnym etapem jest utworzenie pól odpowiadającym kolumnom naszej tabeli w bazie danych. public static final String KEY_ID = "_id" id"; public static final String ID_OPTIONS = "INTEGER PRIMARY KEY AUTOINCREMENT"; public static final String KEY_COUNTRY = "country"; "; public static final String COUNTRY_OPTIONS = "TEXT NOT NULL"; public static final String KEY_SHORTCUT = "shortcut"; public static final String SHORTCUT_OPTION = "TEXT NOT NULL"; tabela ma trzy kolumny _id, country i shortcut. Pole z łańcuchem znaków odpowiedzialnych za stworzenie tabeli. private static final String DB_CREATE = "create" table " + DB_TABLE + " (" + KEY_ID + " " + ID_OPTIONS + ", " + KEY_COUNTRY + " " + COUNTRY_OPTIONS + ", " + KEY_SHORTCUT + " " + SHORTCUT_OPTION + ");";
Tworzenie Bazy private SQLiteDatabase db; //- zmienna do przechowywania bazy danych private final Context context; //- kontekst aplikacji korzystającej z bazy private DatabaseHelper mydatabasehelper; //- helper do otwierania i aktualizacji bazy Ostatnie pole mydatabasehelper jest obiektem klasy dziedziczącej po klasie SQLiteHelper. SQLiteHelper jest klasą abstrakcyjną dostarczającą metody do tworzenia oraz aktualizacji bazy, jeszcze zanim zostanie ona otwarta.
Tworzenie Bazy private static class DatabaseHelper extends SQLiteOpenHelper { public DatabaseHelper(Context context, String name, CursorFactory factory, int version) {super(context, name, factory, version);} @Override public void oncreate(sqlitedatabase _db) { _db.execsql(db_create db.execsql(db_create); } @Override public void onupgrade(sqlitedatabase _db, int oldver, int newver) { _db.execsql("drop TABLE IF EXISTS " + DB_TABLE); oncreate(_db); Log.w("ListView DatabaseAdapter","Aktualizacja bazy z wersji " + oldver + " do " + newver + ". Wszystkie dane zostaną utracone."); } }
Tworzenie Bazy Na koniec, w klasie DatabaseAdapter a dopisujemy konstruktor oraz dwie metody: open() i close(): //Konstruktor public DatabaseAdapter(Context _context) { context = _context; mydatabasehelper = new DatabaseHelper(_context, DB_NAME, null, DB_VERSION); } //Otwieramy połączenie z bazą danych public DatabaseAdapter open() { db = mydatabasehelper.getwritabledatabase(); return this; } //Zamykamy połączenie z bazą danych public void close(){ db.close(); } Pozostaje tylko dodać dwie linijki do głównego activity: mydbadapter.open(); //TODO: Operacje na bazie mydbadapter.close();
Operacje na bazie danych Metody słuŝące do operacji na bazie danych: insert (String table, String nullcolumnhack, ContentValues values) update (String table, ContentValues values, String whereclause,, String[] whereargs) delete (String table, String whereclause,, String[] whereargs) ContentValues jest klasą Android SDK, która została przygotowana specjalnie by słuŝyć do dodawania nowych wierszy w naszej bazie.
Dodawanie Nowej Wartości public long insertcountry(country _country) { } //Tworzymy obiekt nowego "wiersza" ContentValues newcountryvalues = new ContentValues(); //Wypełniamy wszystkie pola wiersza newcountryvalues.put(key_country, _country.getcountryname()); newcountryvalues.put(key_shortcut, _country.getcountryshortcut()); //Wstawiamy wiersz do bazy return db.insert(db_table, null, newcountryvalues);
Aktualizacja danych w wierszu public boolean updatecountry (long _index, Country _country) { } //Warunek wstawiany do klauzuli WHERE String where = KEY_ID + "=" + _index; //Tak samo jak przy metodzie insert ContentValues updatecountryvalues = new ContentValues(); updatecountryvalues.put(key_country, _country.getcountryname()); updatecountryvalues.put(key_shortcut, _country.getcountryshortcut()); //Aktualizujemy dane wiersza zgodnego ze zmienną where return db.update (DB_TABLE, updatecountryvalues, where, null) > 0;
Usuwanie danych public boolean deletecountry (long _index) { String where = KEY_ID + "=" + _index; return db.delete (DB_TABLE, where, null) > 0; } public void deleteall () { db.delete (DB_TABLE, "1", null); }
Kursory Cursor jest klasą, której obiekty w systemie Android reprezentują wyniki zwracane przez zapytania do bazy danych. Posiada ona kilka metod, które bardzo ułatwiają nawigację po zwróconych wierszach. movetofirst() - przesuwa kursor na pierwszy wiersz zwróconego wyniku movetonext() - przesuwa kursor na następny wiersz wyniku, movetoprevious() - j.w. - na poprzedni, movetoposition() - przesuwa kursor na zadaną pozycję getposition() - zwraca aktualną pozycję obiektu Cursor
Kursory Android dostarcza równieŝ metody do zarządzania kursorem startmanagingcursor() - integruje czas Ŝycia kursora z czasem Ŝycia aktywności w której się znajduje. Dzięki temu kiedy Aktywność zostanie wstrzymana, automatycznie wywołana zostaje metoda deactivate(), a gdy wznowiona - requery(). stopmanagingcursor() - deintegruje czas Ŝycia kursora z czasem Ŝycia aktywności.
Kursor Przykład public Cursor fetchnote(long rowid) throws SQLException { } Cursor mcursor = mdb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowid, null, null, null, null, null); if (mcursor!= null) { mcursor.movetofirst(); } return mcursor;
Kursor Przykład private void updatecountrieslist() { countriescursor.requery(); countries.clear(); } if(countriescursor.movetofirst()) { do { String country = countriescursor.getstring(databaseadapter.country_column); String shortcut = countriescursor.getstring(databaseadapter.shortcut_column; Country newcountry = new Country(country, shortcut); countries.add(newcountry); } while (countriescursor.movetonext()); }
ListActivity Arkadiusz Szydełko
ListActivity Specjalna klasa stworzona do wyświetlania listy elementów UmoŜliwia oprogramowanie akcji związanych z elementami listy Lista elementów do tablicy pobierana jest z tablicy bądź kursora.
Oprogramowanie zdarzenia: Aby oprogramować zdarzenie wybrania elementu listy przez użytkownika należy nadpisać metodę onlistitemclick(). Przykład:
Tworzenie widoku: ListActivity zapewnia nam kilka standardowych widoków listy np.: simple_list_item_1 simple_list_item_2 two_line_list_item Zdefiniowane są w klasie android.r.layout http://blog.livedoor.jp/deeds_not_words/images/listactivity/listactivity01.jpg
Przesyłanie danych do widoku: Dane do domyślnego widoku moŝna wysyłać w OnCreate(), za pomocą metody setlistadapter(), przesyłającej dane z kursora do widoku. Przykład: this.setlistadapter(new ArrayAdapter<String>( this, android.r.layout.simple_list_item_1, Tablica_nazw) );
Tworząc własny widok przy pomocy ListView naleŝy zdefiniować odpowiednie id.
Tworzenie widoku: Innym sposobem na stworzenie własnego widoku jest określenie elementów i układu wiersza tworząc własny layout. Np. Stworzyć LinearLayout, a w nim za pomocą TextView określić układ elementów w wierszu.
Tworzenie widoku: Tworzymy własny layout, w którym określamy jak ma wyglądać wiersz:
Tworzenie widoku: Za pomocą klasy SimpleCursorAdapter przesyłamy dane do naszego widoku.
Przesyłanie danych: Aby przesłać połączyć dane z listą do dyspozycji są dwa standardowe listy adapterów: SimpleCursorAdapter dla wyników zapytań przechowywanych w kursorze. SimpleAdapter dla statycznych danych takich jak tablice bądź Maps s.
Android Adaptery Łukasz Pijet
Adapter w teorii Adapter (równieŝ Wrapper) wzorzec projektowy pozwalający na zmianę interfejsu obiektu. a w praktyce: Intefejsy Adapter oraz BaseAdapter we frameworku androida są klasami bazowymi dla adapterów, mających pośredniczyć pomiędzy widgetami (List,Spinner) a obiektami danych.
Dostępne klasy adapter Wśród juŝ zaimplementowanych klas moŝemy znaleźć: a) ArrayAdapter przetwarza dane zawarte w dowolnej liście ( obiekty implementujące interfejs List ) oraz tablice. b) (Simple)CursorAdapter przetwarza dane zawarte w obiekcie Cursor. c) SimpleAdapter przetwarza dane podobnie jak ArrayAdapter. Jeden wiersz danych odpowiada jednemu wierszowi na liście.
Proste Adaptery i ViewBinder Klasy SimpleAdapter i SimpleCursorAdapter posiadają wewnętrzny interfejs ViewBinder z metodą setviewvalue(); Jako argumenty przyjmuje widok, obiekt danych i nr wiersza. Metoda w prosty sposób pozwala na niestandardowe przypisywanie danych do widoku.
Metoda getview() Wywoływana jest dla kaŝdego elementu listy. Numer ostatniego elementu pobierany jest z metody getcount(). Funkcja zwraca obiekt typu View widok który odpowiada pojedynczemu wierszowi listy. Budowany jest na podstawie layotów zawartych w plikach XML aplikacji. PrzeciąŜając ją, moŝna dowolnie rozbudować listę np.: nadając wierszom inny wygląd, wstawiając wiele elementów do wiersza listy.
Metoda getview() - Przykład public View getview(int pozycja, View convertview, ViewGroup parent) { View wynik = null; LayoutInflater minflater; // Pobieramy standardową instancje obiektu LayoutInflater //(w ten sposób jest ona juŝ przygotowana) minflater = (LayoutInflater) getsystemservice(context.layout_inflater_service); if( position % 2 == 0 ) { // Za pomocą LayoutInflater a tworzymy obiekt View na podstawie plików XML // znajdujących się w katalogu res/layout wynik = minflater.inflate( R.layout.widok_1, null ); // Pobieramy obiekt przypisany do zadanego ID. W naszym przypadku jest to TextView. // Nadajemy mu odpowiedni tekst TextView tekst = (TextView) wynik.findviewbyid( R.id.tekst_1 ); tekst.settext( getitem( pozycja ) ); } else { wynik= minflater.inflate( R.layout.widok_2, null ); TextView tekst = (TextView) wynik.findviewbyid( R.id.tekst_2 ); tekst.settext( getitem( pozycja ) ); } // Zwracamy obiekt View pobrany z LayoutInflater return wynik; }
? Pytania?