Projet Android (LI260) Cours 4 Nicolas Baskiotis Universite´ Pierre et Marie Curie (UPMC) Laboratoire d’Informatique de Paris 6 (LIP6) S2 - 2013/2014 ´ Resum e´ sur le multi-thread • Service : facile • operations ´ courtes • bloque le thread principal ´ ⇒ doit lancer dans de nouveaux threads les operations longues • Thread : difficile • gen ´ erique ´ • pour toute operation ´ ´ a` executer dans un autre thread • IntentService : facile • execut ´ e´ dans un thread parallele ` • une seule execution ´ a` la fois, sans interaction avec les autres threads • communication a ` l’aide de message (pour la fin par exemple) • ASyncTask : facile • pour des operations ´ ´ moyenne (quelques secondes) de duree • execut ´ e´ dans un thread parallele ` • communication limitee ´ avec l’UI (progression) • doit etre ˆ cre´ e´ par le thread principal Plan ´ Operations de stockage Options : • Pref ´ erences ´ ´ primitives, leg ´ eres, ` ´ : donnees par cle-valeur • Donnees ´ privees ´ : stockage interne ou externe, non partagee, ´ ´ ´ ´ detruites quand l’application est desinstall ee • Donnees ´ partagees ´ : photos, images, sons en stockage externe • Base de donnees ´ : SQLite, accessible uniquement a` l’interieur ´ de l’application • Reseau ´ : stockage en ligne ´ erences ´ Pref ´ Caracteristiques : • seulement type primitif (int, double, boolean, . . . ) • persistant (meme ˆ ´ si l’application est tuee) • dans un seul fichier (Preferences) • ou dans plusieurs fichiers (SharedPreferences) Utilisation • lecture : (SharedPreferences getSharedPreferences(NOM,0)) .getInt(‘‘myvar’’,defaut), • ecriture ´ : un objet Editor (getSharedPreferences(NOM,0).edit() .putInt(‘‘myvar’’,val) Exemple p u b l i c c l a s s PreferenceDemo0 extends A c t i v i t y implements O n C l i c k L i s t e n e r { Boolean fancyPrefChosen = f a l s e ; f i n a l S t r i n g MYPREFS = ” MyPreferences 001 ” ; SharedPreferences mySharedPreferences ; SharedPreferences . E d i t o r myEditor ; @Override p u b l i c v o i d onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; ... mySharedPreferences = getSharedPreferences (MYPREFS, 0 ) ; myEditor = mySharedPreferences . e d i t ( ) ; i f ( mySharedPreferences ! = n u l l && mySharedPreferences . c o n t a i n s ( ” backColor ” ) ) { applySavedPreferences ( ) ; } else { Toast . makeText ( g e t A p p l i c a t i o n C o n t e x t ( ) , ” No P r e f e r e n c e s found ” , 1 ) . show ( ) ; } } p u b l i c v o i d o n C l i c k ( View v ) { myEditor . c l e a r ( ) ; myEditor . p u t I n t ( ” backColor ” , C o l o r . BLACK ) ; / / b l a c k background myEditor . p u t I n t ( ” t e x t S i z e ” , 1 2 ) ; myEditor . p u t S t r i n g ( ” t e x t S t y l e ” , ” b o l d ” ) ; / / f a n c y b o l d myEditor . p u t I n t ( ” l a y o u t C o l o r ” , C o l o r .GREEN ) ; / / f a n c y green myEditor . commit ( ) ; } p r o t e c t e d v o i d onPause ( ) { myEditor . p u t S t r i n g ( ” D a t e L a s t E x e c u t i o n ” , new Date ( ) . t o L o c a l e S t r i n g ( ) ) ; myEditor . commit ( ) ; super . onPause ( ) ; } p u b l i c v o i d applySavedPreferences ( ) { i n t backColor = mySharedPreferences . g e t I n t ( ” backColor ” , C o l o r . BLACK ) ; i n t t e x t S i z e = mySharedPreferences . g e t I n t ( ” t e x t S i z e ” , 1 2 ) ; S t r i n g t e x t S t y l e = mySharedPreferences . g e t S t r i n g ( ” t e x t S t y l e ” , ” normal ” ) ; i n t l a y o u t C o l o r = mySharedPreferences . g e t I n t ( ” l a y o u t C o l o r ” , C o l o r .DKGRAY ) ; S t r i n g msg = ” c o l o r ” + backColor + ”\n ” + ” s i z e ” + t e x t S i z e + ”\n ” + ” s t y l e ” + t e x t S t y l e ; Toast . makeText ( g e t A p p l i c a t i o n C o n t e x t ( ) , msg , 1 ) . show ( ) ; } ´ Base de donnees SQLite • leger ´ • pour de petites bases, sans operations ´ intensives • beaucoup de sucre syntaxique pour aider a` la programmation • soit acces ` direct avec toute la gestion des exceptions • soit par l’intermediaire ´ ´ de l’heritage En pratique, pour chaque table : • classe SQLiteOpenHelper : gestion de la creation ´ et de la ` ´ mise-a-jour (schema) d’une table de la bd • une classe modele ` : decrit ´ l’objet que l’on stocke dans la table • DAO : data access object, classe encapsulant les requetes ˆ pour ´ la manipulation des donnees ´ Operations usuelles en pratique • .execSQL() : execute ´ une action SQL • classe Cursor : curseur sur le resultat ´ ˆ : de requete • isFirst(), isLast(), moveToFirst(), moveToNext(), moveToLast() • getString(int i), getInt(int i), getColumnName(), getColumnCount() • classe ContentValues : stocke des paires champs/valeurs .put(key,val) • modification : • public long insert(String table, String nullColumnHack, ContentValues values) • public int update( String table, ContentValues values, String whereClause, String[] whereArgs) • public int delete( String table, String whereClause, String[] whereArgs) Exemple : db.update( "tbl", (new ContentValues()).put(‘‘name’’,‘‘Moi’’), "recID > ? and recID < ?", {‘‘2’’, ‘‘7’’} )} ` Exemple : le modele p u b l i c c l a s s Comment { p r i v a t e long i d ; p r i v a t e S t r i n g comment ; p u b l i c long getId ( ) { return id ; } p u b l i c void s e t I d ( long i d ) { this . id = id ; } p u b l i c S t r i n g getComment ( ) { r e t u r n comment ; } p u b l i c v o i d setComment ( S t r i n g comment ) { t h i s . comment = comment ; } / / W i l l be used by t h e A r r a y A d a p t e r i n t h e L i s t V i e w @Override public String toString () { r e t u r n comment ; } } ´ Exemple : creation p u b l i c c l a s s MySQLiteHelper extends SQLiteOpenHelper { p u b l i c s t a t i c f i n a l S t r i n g TABLE COMMENTS = ” comments ” ; p u b l i c s t a t i c f i n a l S t r i n g COLUMN ID = ” i d ” ; p u b l i c s t a t i c f i n a l S t r i n g COLUMN COMMENT = ” comment ” ; p r i v a t e s t a t i c f i n a l S t r i n g DATABASE NAME = ” commments . db ” ; p r i v a t e s t a t i c f i n a l i n t DATABASE VERSION = 1 ; / / Database c r e a t i o n s q l s t a t e m e n t p r i v a t e s t a t i c f i n a l S t r i n g DATABASE CREATE = ” c r e a t e t a b l e ” + TABLE COMMENTS + ” ( ” + COLUMN ID + ” i n t e g e r p r i m a r y key autoincrement , ” + COLUMN COMMENT + ” t e x t not n u l l ) ; ” ; p u b l i c MySQLiteHelper ( Context c o n t e x t ) { super ( c o n t e x t , DATABASE NAME, n u l l , DATABASE VERSION ) ; } @Override p u b l i c v o i d onCreate ( SQLiteDatabase database ) { database . execSQL (DATABASE CREATE ) ; } @Override p u b l i c v o i d onUpgrade ( SQLiteDatabase db , i n t o l d V e r s i o n , i n t newVersion ) { Log . w( MySQLiteHelper . c l a s s . getName ( ) , ” Upgrading database from v e r s i o n ” + o l d V e r s i o n + ” t o ” + newVersion + ” , which w i l l d e s t r o y a l l o l d data ” ) ; db . execSQL ( ”DROP TABLE I F EXISTS ” + TABLE COMMENTS ) ; onCreate ( db ) ; } } Exemple : DAO p u b l i c c l a s s CommentsDataSource { p r i v a t e SQLiteDatabase database ; p r i v a t e MySQLiteHelper dbHelper ; p r i v a t e S t r i n g [ ] allColumns = { MySQLiteHelper . COLUMN ID , MySQLiteHelper .COLUMN COMMENT }; p u b l i c CommentsDataSource ( Context c o n t e x t ) {dbHelper = new MySQLiteHelper ( c o n t e x t ) ; } p u b l i c v o i d open ( ) throws SQLException {database = dbHelper . g e t W r i t a b l e D a t a b a s e ( ) ; } p u b l i c v o i d c l o s e ( ) {dbHelper . c l o s e ( ) ; } p u b l i c Comment createComment ( S t r i n g comment ) { ContentValues v a l u e s = new ContentValues ( ) ; v a l u e s . p u t ( MySQLiteHelper .COLUMN COMMENT, comment ) ; l o n g i n s e r t I d = database . i n s e r t ( MySQLiteHelper . TABLE COMMENTS, n u l l , v a l u e s ) ; Cursor c u r s o r = database . query ( MySQLiteHelper . TABLE COMMENTS, allColumns , MySQLiteHelper . COLUMN ID + ” = ” + i n s e r t I d , n u l l , n u l l , n u l l , n u l l ) ; c u r s o r . moveToFirst ( ) ; Comment newComment = cursorToComment ( c u r s o r ) ; cursor . close ( ) ; r e t u r n newComment ; } Exemple : DAO p u b l i c v o i d deleteComment ( Comment comment ) { l o n g i d = comment . g e t I d ( ) ; System . o u t . p r i n t l n ( ” Comment d e l e t e d w i t h i d : ” + i d ) ; database . d e l e t e ( MySQLiteHelper . TABLE COMMENTS, MySQLiteHelper . COLUMN ID + ” = ” + i d , n u l l ) ; } p u b l i c L i s t<Comment> getAllComments ( ) { L i s t<Comment> comments = new A r r a y L i s t<Comment>(); Cursor c u r s o r = database . query ( MySQLiteHelper . TABLE COMMENTS, allColumns , n u l l , n u l l , n u l l , n u l l , n u l l ) ; c u r s o r . moveToFirst ( ) ; while ( ! cursor . i s A f t e r L a s t ( ) ) { Comment comment = cursorToComment ( c u r s o r ) ; comments . add ( comment ) ; c u r s o r . moveToNext ( ) ; } cursor . close ( ) ; r e t u r n comments ; } p r i v a t e Comment cursorToComment ( Cursor c u r s o r ) { Comment comment = new Comment ( ) ; comment . s e t I d ( c u r s o r . getLong ( 0 ) ) ; comment . setComment ( c u r s o r . g e t S t r i n g ( 1 ) ) ; r e t u r n comment ; } } Exemple : classe principale p u b l i c c l a s s T e s t D a t a b a s e A c t i v i t y extends L i s t A c t i v i t y { p r i v a t e CommentsDataSource datasource ; p u b l i c v o i d onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; setContentView (R . l a y o u t . main ) ; datasource = new CommentsDataSource ( t h i s ) ; datasource . open ( ) ; L i s t<Comment> v a l u e s = datasource . getAllComments ( ) ; ArrayAdapter<Comment> a d a p t e r = new ArrayAdapter<Comment>(t h i s , android .R. l a y o u t . s i m p l e l i s t i t e m 1 , values ) ; s e t L i s t A d a p t e r ( adapter ) ; } p u b l i c v o i d o n C l i c k ( View view ) { ArrayAdapter<Comment> a d a p t e r = ( ArrayAdapter<Comment>) g e t L i s t A d a p t e r ( ) ; Comment comment = n u l l ; s w i t c h ( view . g e t I d ( ) ) { case R . i d . add : S t r i n g [ ] comments = new S t r i n g [ ] { ” Cool ” , ” Very n i c e ” , ” Hate i t ” }; i n t n e x t I n t = new Random ( ) . n e x t I n t ( 3 ) ; comment = datasource . createComment ( comments [ n e x t I n t ] ) ; a d a p t e r . add ( comment ) ; break ; case R . i d . d e l e t e : i f ( g e t L i s t A d a p t e r ( ) . getCount ( ) > 0 ) { comment = ( Comment ) g e t L i s t A d a p t e r ( ) . g e t I t e m ( 0 ) ; datasource . deleteComment ( comment ) ; a d a p t e r . remove ( comment ) ; } break ; } a d a p t e r . notifyDataSetChanged ( ) ; } p r o t e c t e d v o i d onResume ( ) { datasource . open ( ) ; super . onResume ( ) ; } p r o t e c t e d v o i d onPause ( ) { datasource . c l o s e ( ) ; super . onPause ( ) ; Plan MVC : Model-View-Control ´ Objectif : separer • les donnees ´ (model) • l’interface graphique (view) • la manipulation (control) ´ Operations sur les vues • properties : couleur, police, taille • listeners : methodes ´ ´ a` l’ecoute des actions sur la vue • focus • visibilite´ Exemples Exemples ´ gen ´ eriques ´ Mots-cles • orientation : vertical, horizontal • fill model : match parent, wrap contents • weight : 0,1,2,. . . • gravity, layout gravity : top, bottom, center • padding, margin • layout alignParent{Top,Bottom,Left,Right}, layout center{InParent,centerVertical,centerHorizontal} • layout {above,below,toLeftOf,toRightOf} • layout span List Widgets ArrayAdapter • Heritage ´ de BaseAdapter • accepte un tableau d’objet • utilise la methode ´ toString() de l’objet • utilise un TextView pour afficher chaque objet • personnalisation pour afficher des objets plus complexes S t r i n g [ ] i t e m s = { ” Data−0” , ” Data−1” , ” Data−2” , ” Data−3” , ” Data−4” , ” Data−5” , ” Data−6” , ” Data−7” };} ArrayAdapter<S t r i n g> a d a p t e r = new ArrayAdapter<S t r i n g >(t h i s , a n d r o i d .R . l a y o u t . s i m p l e l i s t i t e m 1 , items ) ; Exemple 1 XML Layout <L i n e a r L a y o u t xmlns : a n d r o i d = ” h t t p : / / schemas . a n d r o i d . com / apk / r e s / a n d r o i d ” xmlns : t o o l s = ” h t t p : / / schemas . a n d r o i d . com / t o o l s ” a n d r o i d : l a y o u t w i d t h = ” match parent ” a n d r o i d : l a y o u t h e i g h t = ” match parent ” android : o r i e n t a t i o n = ” v e r t i c a l ” > <TextView a n d r o i d : i d = ”@+ i d / txtMsg ” a n d r o i d : l a y o u t w i d t h = ” match parent ” android : l a y o u t h e i g h t = ” wrap content ” a n d r o i d : background= ” # f f f f f f 0 0 ” a n d r o i d : t e x t = ” Using L i s t V i e w s . . . ” a n d r o i d : t e x t S i z e = ” 16sp ” /> <L i s t V i e w a n d r o i d : i d = ”@+ i d / m y l i s t ” a n d r o i d : l a y o u t w i d t h = ” match parent ” a n d r o i d : l a y o u t h e i g h t = ” match parent ” > </L i s t V i e w> </L i n e a r L a y o u t> Exemple 1 p u b l i c c l a s s ListViewDemo2 extends A c t i v i t y { S t r i n g [ ] i t e m s = { ” Data−0” , ” Data−1” , ” Data−2” , ” Data−3” , ” Data−4” , ” Data−5” , ” Data−6” , ” Data−7” }; L i s t V i e w myListView ; TextView txtMsg ; @Override p u b l i c v o i d onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; setContentView (R . l a y o u t . a c t i v i t y m a i n ) ; myListView = ( L i s t V i e w ) f i n d V i e w B y I d (R . i d . m y l i s t ) ; ArrayAdapter<S t r i n g> aa = new ArrayAdapter<S t r i n g >(t h i s , android .R. l a y o u t . s i m p l e l i s t i t e m 1 , items ) ; myListView . s e t A d a p t e r ( aa ) ; txtMsg = ( TextView ) f i n d V i e w B y I d (R . i d . txtMsg ) ; } myListView . s e t O n I t e m C l i c k L i s t e n e r ( new O n I t e m C l i c k L i s t e n e r ( ) { @Override p u b l i c v o i d o n I t e m C l i c k ( AdapterView<?> av , View v , i n t p o s i t i o n , long i d ) { String text = ” Position : ” + position + ”\nData : ” + i t e m s [ p o s i t i o n ] ; txtMsg . s e t T e x t ( t e x t ) ; } }); } Exemple 2 Activity XML <?xml v e r s i o n = ” 1 . 0 ” encoding= ” UTF−8”?> <L i n e a r L a y o u t xmlns : a n d r o i d = ” h t t p : / / schemas . a n d r o i d . com / apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t w i d t h = ” match parent ” android : l a y o u t h e i g h t = ” wrap content ” a n d r o i d : background= ” # f f f f f f f f ” android : o r i e n t a t i o n = ” v e r t i c a l ” a n d r o i d : padding= ” 2dp ” > <TextView a n d r o i d : i d = ”@+ i d / txtMsg ” a n d r o i d : l a y o u t w i d t h = ” match parent ” android : l a y o u t h e i g h t = ” wrap content ” a n d r o i d : background= ” # f f 0 0 f f 0 0 ” a n d r o i d : t e x t = ” s c r o l l and c l i c k t o s e l e c t . . . ” a n d r o i d : textAppearance = ” ? a n d r o i d : a t t r / textAppearanceLarge ” /> <H o r i z o n t a l S c r o l l V i e w a n d r o i d : l a y o u t w i d t h = ” match parent ” android : l a y o u t h e i g h t = ” wrap content ” a n d r o i d : background= ” #44aaaaaa ” > <L i n e a r L a y o u t a n d r o i d : i d = ”@+ i d / viewgroup ” android : l a y o u t w i d t h = ” wrap content ” android : l a y o u t h e i g h t = ” wrap content ” android : o r i e n t a t i o n = ” h o r i z o n t a l ” a n d r o i d : padding= ” 10 d i p ” > </L i n e a r L a y o u t> </H o r i z o n t a l S c r o l l V i e w> <ImageView a n d r o i d : i d = ”@+ i d / imageSelected ” android : l a y o u t w i d t h = ” wrap content ” android : l a y o u t h e i g h t = ” wrap content ” a n d r o i d : l a y o u t w e i g h t = ” 2 ” /> </L i n e a r L a y o u t> Exemple 2 Icon Frame XML <?xml v e r s i o n = ” 1 . 0 ” encoding= ” UTF−8”?> <L i n e a r L a y o u t xmlns : a n d r o i d = ” h t t p : / / schemas . a n d r o i d . com / apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t w i d t h = ” match parent ” android : l a y o u t h e i g h t = ” wrap content ” android : o r i e n t a t i o n = ” v e r t i c a l ” > <ImageView a n d r o i d : i d = ”@+ i d / i c o n ” a n d r o i d : l a y o u t w i d t h = ” 80dp ” a n d r o i d : l a y o u t h e i g h t = ” 80dp ” a n d r o i d : p a d d i n g L e f t = ” 2dp ” a n d r o i d : p a d d i n g R i g h t = ” 2dp ” a n d r o i d : paddingTop= ” 2dp ” a n d r o i d : s r c = ” @drawable / i c l a u n c h e r ” /> <TextView a n d r o i d : i d = ”@+ i d / c a p t i o n ” a n d r o i d : l a y o u t w i d t h = ” match parent ” android : l a y o u t h e i g h t = ” wrap content ” a n d r o i d : background= ” #55 f f f f 0 0 ” a n d r o i d : t e x t S i z e = ” 20sp ” /> </L i n e a r L a y o u t> Exemple 2 p u b l i c c l a s s M a i n A c t i v i t y extends A c t i v i t y { TextView txtMsg ; ViewGroup s c r o l l V i e w g r o u p ; ImageView i c o n ; TextView c a p t i o n ; S t r i n g [ ] i t e m s = { ” Data−1” , . . } I n t e g e r [ ] t h u m b n a i l s = { R . drawable . p i c 0 1 s m a l l , . . . } I n t e g e r [ ] largeImages = { R . drawable . p i c 0 1 l a r g e , . . . } ImageView imageSelected ; p r o t e c t e d v o i d onCreate ( Bundle s a v e d I n s t a n c e S t a t e ) { super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; setContentView (R . l a y o u t . a c t i v i t y m a i n ) ; txtMsg = ( TextView ) f i n d V i e w B y I d (R . i d . txtMsg ) ; imageSelected = ( ImageView ) f i n d V i e w B y I d (R. i d . imageSelected ) ; s c r o l l V i e w g r o u p = ( ViewGroup ) f i n d V i e w B y I d (R . i d . viewgroup ) ; f o r ( i n t i = 0 ; i < i t e m s . l e n g t h ; i ++) { f i n a l View singleFrame = g e t L a y o u t I n f l a t e r ( ) . i n f l a t e ( R. l a y o u t . frame icon caption , n u l l ) ; singleFrame . s e t I d ( i ) ; TextView c a p t i o n = ( TextView ) singleFrame . f i n d V i e w B y I d (R. i d . c a p t i o n ) ; ImageView i c o n = ( ImageView ) singleFrame . f i n d V i e w B y I d (R . i d . i c o n ) ; i c o n . setImageResource ( t h u m b n a i l s [ i ] ) ; caption . setText ( items [ i ] ) ; s c r o l l V i e w g r o u p . addView ( singleFrame ) ; singleFrame . s e t O n C l i c k L i s t e n e r ( new View . O n C l i c k L i s t e n e r ( ) { p u b l i c v o i d o n C l i c k ( View v ) { S t r i n g t e x t = ” S e l e c t e d p o s i t i o n : ” + singleFrame . g e t I d ( ) ; txtMsg . s e t T e x t ( t e x t ) ; showLargeImage ( singleFrame . g e t I d ( ) ) ; } }); } } p r o t e c t e d v o i d showLargeImage ( i n t f r a m e I d ) { Drawable selectedLargeImage = getResources ( ) . getDrawable ( largeImages [ f r a m e I d ] ) ; imageSelected . setBackground ( selectedLargeImage ) ; } }
© Copyright 2024 Paperzz