In questa serie stiamo costruendo un client Twitter per la piattaforma Android utilizzando la libreria Twitter4J. Questo tutorial creerà un database SQLite per memorizzare la linea temporale dell'utente. Verranno inoltre mappati i dati dal database alle Visualizzazioni create l'ultima volta utilizzando un adattatore, in modo che l'utente possa vedere i loro aggiornamenti.
Nei primi due tutorial abbiamo impostato il progetto in Eclipse, registrato l'app con Twitter, importato il file JAR di Twitter4J e creato l'interfaccia utente. Abbiamo anche provveduto a far accedere gli utenti ai loro account Twitter e autorizzare l'app ad accedere ai loro tweet.
Questo tutorial creerà un database SQLite per memorizzare la linea temporale dell'utente. Verranno inoltre mappati i dati dal database alle Visualizzazioni create l'ultima volta utilizzando un adattatore, in modo che l'utente possa vedere i loro aggiornamenti.
Entriamo subito e crea il database della timeline usando SQLite. Crea una nuova classe nel tuo progetto selezionandola in Esplora pacchetti, scegliendo File, Nuovo quindi Class. Inserisci "NiceDataHelper" come nome della classe. Aprire il nuovo file di classe ed estendere la dichiarazione come segue:
public class NiceDataHelper estende SQLiteOpenHelper
Questa è una classe helper del database per il sistema SQLite. In questa classe creeremo e gestiremo il database per i tweet della timeline home.
Aggiungi le seguenti istruzioni di importazione all'inizio della classe:
importare android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; importare android.provider.BaseColumns; import android.util.Log;
Queste importazioni sono per l'elaborazione di base del database e la registrazione degli errori, oltre al contesto dell'applicazione per riferimento generale.
Il database conterrà una singola tabella per gli aggiornamenti dei tweet. Questa tabella includerà le seguenti colonne per ogni tweet: l'ID di stato di Twitter; il testo tweet; il nome dello schermo del tweeter; il momento in cui il tweet è stato inviato; l'URL dell'immagine del profilo del tweeter.
Inizia creando alcune costanti nella classe:
/ ** db version * / private static final int DATABASE_VERSION = 1; / ** nome database * / stringa finale statica privata DATABASE_NAME = "home.db"; / ** colonna ID * / stringa statica finale privata HOME_COL = BaseColumns._ID; / ** tweet text * / private static final String UPDATE_COL = "update_text"; / ** nome schermata twitter * / stringa finale statica privata USER_COL = "schermata utente"; / ** time tweeted * / private static final String TIME_COL = "update_time"; / ** immagine del profilo utente * / stringa statica finale privata USER_IMG = "user_img";
Queste variabili costanti includono il nome della versione del database, che dovresti modificare se desideri aggiornare il database negli sviluppi futuri della tua app. Le variabili includono anche il nome del database e i nomi delle colonne. La classe BaseColumns ci aiuta ad assegnare una colonna ID univoca usando il suffisso "_id".
Quindi crea la stringa di tabella SQLite create per la tabella home:
/ ** stringa di creazione del database * / stringa finale statica privata DATABASE_CREATE = "CREATE TABLE home (" + HOME_COL + "INTEGER NON NULL PRIMARY KEY," + UPDATE_COL + "TEXT," + USER_COL + "TEXT," + TIME_COL + "INTEGER , "+ USER_IMG +" TEXT); ";
Creare il metodo di costruzione per la classe helper del database:
/ ** * Metodo di costruzione * @ contesto di contesto * / NiceDataHelper (contesto di contesto) super (contesto, DATABASE_NAME, null, DATABASE_VERSION);
Il costruttore chiama semplicemente il metodo della superclasse. Quindi aggiungi il metodo "onCreate" in cui eseguiremo la creazione della tabella del database:
/ * * onCreate esegue la stringa di creazione del database * / @Override public void onCreate (SQLiteDatabase db) db.execSQL (DATABASE_CREATE);
Qui stiamo semplicemente eseguendo la creazione di database SQL String. Alla fine del metodo la tabella sarà stata creata.
Per completare la preparazione del nostro database, implementare il metodo "onUpgrade" nel caso in cui si decida di modificare il database in un momento futuro:
/ * * onUpgrade elimina la tabella home ed esegue la stringa di creazione * / @Override public void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion) db.execSQL ("DROP TABLE IF EXISTS home"); db.execSQL ( "vuoto"); onCreate (db);
Ciò consente di aggiornare il database modificando il numero di versione e la stringa di creazione o qualsiasi colonna.
Ora aggiungeremo un metodo finale alla nostra classe helper del database. Questo metodo restituirà i valori dagli ultimi aggiornamenti dello stato di Twitter recuperati e verrà chiamato dalla classe di servizio che creiamo nel prossimo tutorial. Aggiungi il contorno del metodo come segue:
/ ** * getValues recupera i record del database * - chiamato da TimelineUpdater in TimelineService * - questo è un metodo statico che può essere chiamato senza un'istanza della classe * * @param status * @return ContentValues result * / public static ContentValues getValues ( Status status) // prepara ContentValues per restituire ContentValues homeValues = new ContentValues (); // ottiene i valori // restituisce i valori return homeValues;
All'interno di questo metodo, convertiamo l'oggetto Status passato in un set di ContentValues. La classe Status fa parte della libreria Twitter4J, modella un singolo aggiornamento di stato o tweet. Quando il servizio dell'applicazione recupera la linea temporale dell'utente, passerà ciascuno degli aggiornamenti di stato in esso al metodo "getValues". Questo metodo recupererà le informazioni dal tweet che vogliamo archiviare nel database, ovvero ID, testo, nome utente, ora e URL dell'immagine del profilo. Il metodo inserirà ognuno di questi in un insieme di ContentValues che restituirà. Il Servizio tenterà quindi di scrivere i dati contenuti nel ContentValues nel database, aggiornandolo con i tweet recuperati di recente.
Implementeremo la maggior parte di questo processo quando creiamo il servizio nel prossimo tutorial. Per ora tutto ciò che dobbiamo fare è fornire il corpo del metodo "getValues". Prima della riga in cui vengono restituiti i valori, aggiungere quanto segue:
prova // ottenere ogni valore dalla tabella homeValues.put (HOME_COL, status.getId ()); homeValues.put (UPDATE_COL, status.getText ()); homeValues.put (USER_COL, status.getUser (). getScreenName ()); homeValues.put (TIME_COL, status.getCreatedAt (). getTime ()); homeValues.put (USER_IMG, status.getUser (). getProfileImageURL (). toString ()); catch (Exception te) Log.e ("NiceDataHelper", te.getMessage ());
Il processo può causare eccezioni, quindi i blocchi try e catch sono necessari. Si noti che il metodo tenta di recuperare ogni elemento dell'aggiornamento di stato che abbiamo progettato per l'archiviazione del database utilizzando i metodi Twitter4J. Avrai bisogno di un altro paio di importazioni aggiunte alla classe:
import twitter4j.Status; importare android.content.ContentValues;
Utilizzeremo una classe Adapter per mappare i dati dei tweet all'interfaccia utente Viste create nell'ultimo tutorial. Il ListView che abbiamo creato nel file di layout XML della timeline mostrerà i nuovi aggiornamenti tweet non appena saranno disponibili. Ogni aggiornamento dei tweet verrà visualizzato all'interno del layout XML di aggiornamento che abbiamo definito. Se guardi indietro a "res / layout / update.xml" vedrai che ci sono sezioni per la visualizzazione di tutti gli elementi di dati che stiamo memorizzando nel database, cioè l'immagine del profilo utente e il nome della schermata, il tweet e l'ora è stato tweettato.
La classe Adapter sta per mappare i dati di tweet di aggiornamento in arrivo a questi elementi Visualizza l'interfaccia utente. Piuttosto che doverlo implementare manualmente, la classe "SimpleCursorAdapter" ci consente di automatizzare parte del processo, mappando i dati a Views, consentendoci comunque di personalizzare questo processo di mappatura in base alle esigenze dell'app..
Crea una nuova classe nella tua app, nominandola "UpdateAdapter". Estendi la dichiarazione della classe come segue:
la classe pubblica UpdateAdapter estende SimpleCursorAdapter
Importa la classe genitore e la classe di registro come segue:
import android.widget.SimpleCursorAdapter; import android.util.Log;
Aggiungi variabili di istanza come segue:
/ ** chiave sviluppatore twitter * / stringa statica finale pubblica TWIT_KEY = "la tua chiave"; // alter / ** segreto sviluppatore di twitter * / stringa statica finale pubblica TWIT_SECRET = "il tuo segreto"; // alter / ** stringhe che rappresentano il database nomi di colonne da mappare a viste * / static final String [] da = "update_text", "user_screen", "update_time", "user_img"; / ** visualizza gli ID oggetto per il mapping dei valori del record del database su * / static final int [] su = R.id.updateText, R.id.userScreen, R.id.updateTime, R.id.userImg; private String LOG_TAG = "UpdateAdapter";
Cambia lo sviluppatore di chiavi Key and Secret in modo che rifletta il tuo, come hai usato nella principale classe di attività dell'app nell'ultimo tutorial. L'array "from" rappresenta il nome di ciascuna colonna della tabella del database mappata. La matrice "a" rappresenta gli ID delle viste a cui verranno mappati gli elementi "da". Gli ID erano tutti inclusi nei layout XML che abbiamo creato nell'ultimo tutorial.
Nella classe Adapter, aggiungi un metodo di costruzione come segue:
/ ** * costruttore imposta adattatore, passando 'da' dati e 'a' viste * @ contesto contesto * @param c * / pubblico UpdateAdapter (contesto contesto, cursore c) super (contesto, R.layout.update, c , da A);
Questo codice chiama il costruttore della superclasse, passando il contesto dell'applicazione, l'elemento View in cui i dati verranno visualizzati, il cursore per attraversare i dati e gli array "from" e "to" che abbiamo creato come variabili di istanza. Avrai bisogno delle seguenti istruzioni di importazione per questo codice:
importare android.content.Context; import android.database.Cursor;
Questo esegue la parte centrale del processo di mappatura, ovvero la visualizzazione dei dati all'interno delle Viste specificate. Tuttavia, vogliamo anche personalizzare il comportamento e l'aspetto degli elementi dell'interfaccia utente risultanti. Adatteremo la procedura di mappatura per recuperare l'immagine del profilo per ogni tweet e per formattare il tempo di aggiornamento. Nell'ultimo tutorial della serie estenderemo questo codice per impostare gli ascoltatori di clic per il pulsante retweet, il pulsante di risposta e il nome utente di Twitter per ciascun tweet.
Implementare il metodo "bindView" all'interno della classe Adapter utilizzando il seguente schema:
/ * * Associazione dei dati alle viste visibili * / @Override public void bindView (Visualizza riga, Contesto contesto, Cursore cursore) super.bindView (riga, contesto, cursore);
Qui stiamo semplicemente chiamando il metodo della superclasse. Il metodo "bindView" ci consente di specificare un'ulteriore elaborazione per quando i dati sono mappati alle Views. Per prima cosa proviamo a scaricare l'immagine del profilo per l'aggiornamento corrente tweet:
prova // ottieni profilo immagine URL profileURL = nuovo URL (cursor.getString (cursor.getColumnIndex ("user_img"))); // imposta l'immagine nella vista per il tweet attuale ImageView profPic = (ImageView) row.findViewById (R.id.userImg); profPic.setImageDrawable (Drawable.createFromStream ((InputStream) profileURL.getContent (), "")); catch (Exception te) Log.e (LOG_TAG, te.getMessage ());
Abbiamo bisogno di provare e intercettare i blocchi perché stiamo tentando di caricare una risorsa esterna. Il metodo ottiene prima l'URL dell'immagine del profilo come memorizzato nella colonna del database. Quindi il metodo ottiene un riferimento all'elemento View per visualizzare l'immagine in, utilizzando il relativo attributo ID, come impostato nel file di layout XML di aggiornamento. Infine il codice recupera l'immagine come InputStream, importandola come Drawable e impostandola come immagine all'interno di ImageView. Avrai bisogno delle seguenti importazioni:
importare java.io.InputStream; import java.net.URL; import android.graphics.drawable.Drawable; importa android.view.View; import android.widget.ImageView;
Ora modifichiamo la visualizzazione dell'ora di aggiornamento, poiché verrà memorizzata nel database come un numero. Per convertirlo in un tempo relativo leggibile dall'uomo, aggiungi il seguente codice dopo il blocco catch:
// ottiene il tempo di aggiornamento lungo createdAt = cursor.getLong (cursor.getColumnIndex ("update_time")); // ottiene la visualizzazione dell'ora di aggiornamento TextView textCreatedAt = (TextView) row.findViewById (R.id.updateTime); // regola il modo in cui viene visualizzata l'ora per renderlo leggibile da testo textCreatedAt.setText (DateUtils.getRelativeTimeSpanString (createdAt) + "");
Per prima cosa recuperiamo il valore della colonna a lungo, quindi otteniamo un riferimento all'elemento View per visualizzarlo all'interno dell'aggiornamento XML. Infine lo formiamo come una stringa in modo che l'utente possa vedere quando il tweet è stato inviato rispetto al tempo presente. Avrai bisogno delle seguenti dichiarazioni di importazione aggiuntive:
importare android.text.format.DateUtils; import android.widget.TextView;
Tornando alla principale classe di attività dell'app "TwitNiceActivity" implementiamo ora il metodo "setupTimeline". Nel prossimo tutorial aggiungeremo l'elaborazione del servizio al metodo, ma per ora gestiamo l'avvio del database e dell'adattatore. Prima di iniziare con il metodo, aggiungi le seguenti variabili di istanza all'inizio della tua classe:
/ ** vista principale per la timeline home * / private ListView homeTimeline; / ** helper del database per i dati di aggiornamento * / private NiceDataHelper timelineHelper; / ** aggiornamento database * / private SQLiteDatabase timelineDB; / ** cursore per la gestione dei dati * / private Cursor timelineCursor; / ** adattatore per la mappatura dei dati * / privato UpdateAdapter timelineAdapter;
Useremo queste variabili quando costruiamo la timeline. Aggiungi quanto segue per specificare la dimensione predefinita per la visualizzazione dell'immagine del profilo:
ProfileImage.ImageSize imageSize = ProfileImage.NORMAL;
Dovrai aggiungere le seguenti importazioni:
import twitter4j.ProfileImage; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.widget.ListView; import android.widget.LinearLayout;
Ora per impostare la sequenza temporale. Se hai creato il contorno del metodo "setupTimeline" per il test dell'ultima volta, puoi semplicemente aggiungere il corpo del metodo successivo. In caso contrario, crea il contorno del metodo ora:
/ ** * setupTimeline visualizza la linea temporale principale dell'utente Twitter * / private void setupTimeline () // metodo body
Potresti ricordare dall'ultima volta che questo metodo viene chiamato quando l'utente ha già autorizzato l'app a utilizzare il proprio account Twitter. All'interno del metodo istanziamo la classe Database Helper, recuperiamo un database leggibile, istanziamo la classe Adapter e la impostiamo per mappare i dati alle nostre Views. Inizia impostando il contenuto della timeline Visualizza:
setContentView (R.layout.timeline);
Alcuni dei metodi che utilizzeremo possono generare eccezioni, quindi aggiungi e prova i blocchi:
prova // get the timeline catch (Exception te) Log.e (LOG_TAG, "Impossibile recuperare la timeline:" + te.getMessage ());
Aggiungeremo i prossimi estratti di codice all'interno del blocco try. Qui stiamo per istanziare le variabili che abbiamo dichiarato all'inizio della classe. Innanzitutto ottenere un riferimento a ListView dal layout della timeline, in cui verranno visualizzate le visualizzazioni dell'aggiornamento:
// ottiene il riferimento alla vista elenco homeTimeline = (ListView) findViewById (R.id.homeList);
Quindi creare un'istanza della classe Database Helper e utilizzarla per recuperare un database leggibile:
// istanziare helper del database timelineHelper = new NiceDataHelper (this); // ottiene il database timelineDB = timelineHelper.getReadableDatabase ();
La prima riga qui crea un'istanza della classe Database Helper che abbiamo definito, mentre la seconda recupera effettivamente il database. Ora interrogiamo il database e acquisiamo un cursore per attraversarlo, passando questo cursore alla classe Adapter:
// interroga il database, i tweet più recenti first timelineCursor = timelineDB.query ("home", null, null, null, null, null, "update_time DESC"); // gestire gli aggiornamenti utilizzando un cursore startManagingCursor (timelineCursor); // instantiate adapter timelineAdapter = new UpdateAdapter (this, timelineCursor);
La query del database consiste semplicemente nel recuperare tutto dalla tabella, ordinando prima i tweet di aggiornamento più recenti. Passiamo il cursore al metodo di costruzione della classe Adapter che abbiamo creato.
In questo tutorial abbiamo creato il nostro database timeline tweet, definito un adapter per la visualizzazione dei dati all'interno della nostra interfaccia utente Views e utilizzato queste classi all'interno dell'attività principale della nostra app, per costruire la timeline visibile.
Nel prossimo tutorial configureremo un servizio e un ricevitore di trasmissione per recuperare continuamente nuovi aggiornamenti e visualizzarli all'interno della linea temporale dell'utente. Nel momento in cui esegui l'app non vedrai nessun aggiornamento, poiché non abbiamo ancora recuperato la sequenza temporale dell'utente. Come parte della classe Service, recupereremo la timeline utilizzando i metodi Twitter4J, chiamandoli a intervalli regolari per recuperare ripetutamente i tweet più recenti dagli account che l'utente segue. Quindi scriveremo i risultati nel database e li presenteremo nella visualizzazione della timeline.