PDA

View Full Version : [android] Chiarimento sugli INTENT


abbobba
12-08-2015, 09:28
Salve

stavo provando a utilizzare nel manifest la modalità:
android:launchMode="singleInstance"
a quanto ho letto in rete ogni volta che si arriva a questo punto:
Intent myIntent = newIntent(activityB.this,activityC.class);
myIntent.putExtra("firstKeyName","FirstKeyValue");
myIntent.putExtra("secondKeyName","SecondKeyValue");
startActivity(myIntent);
invece di crearmi una nuova instanza dell'activityC creata, verifiche se nello stack è già presente un'istanza e eventualmente l'avvia. Quindi se si verifica ciò al posto di iniziare dal metodo onCreate() inizia da:
protected void onNewIntent (Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
Log.i(TAG, "onNewIntent");
processExtraData();
}


ora al di la del fatto che tutto funziona, la cosa che non riesco a capire è cosa fa esattemente onNewIntent(Intent intent) in particolare il parametro intent a chi si riferisce? e setIntent(intent) cosa fa?

Daniels118
12-08-2015, 11:04
In quest'ottica la funzione degli intent viene sminuita, in realtà essi hanno uno scopo più elevato, ovvero quello di fornire un meccanismo di comunicazione interprocesso. "onNewIntent" è l'event handler del ricevente che viene invocato a fronte di una richiesta da parte di un'altra activity, o di un'altra applicazione, o del sistema operativo. Il parametro intent descrive l'azione richiesta dal chiamante; la chiamata a setIntent serve per aggiornare l'intent dell'activity in cui ti trovi, è necessaria solo se il comportamento dell'activity deve essere influenzato dall'intent che l'ha chiamata (nel tuo caso è superflua). Se ti interessa sapere cosa contiene l'intent nel tuo caso, puoi mettere un breakpoint ed analizzare la variabile.
Qui trovi la descrizione ufficiale (http://developer.android.com/reference/android/app/Activity.html#onNewIntent(android.content.Intent)).

abbobba
13-08-2015, 10:21
In quest'ottica la funzione degli intent viene sminuita, in realtà essi hanno uno scopo più elevato, ovvero quello di fornire un meccanismo di comunicazione interprocesso. "onNewIntent" è l'event handler del ricevente che viene invocato a fronte di una richiesta da parte di un'altra activity, o di un'altra applicazione, o del sistema operativo. Il parametro intent descrive l'azione richiesta dal chiamante; la chiamata a setIntent serve per aggiornare l'intent dell'activity in cui ti trovi, è necessaria solo se il comportamento dell'activity deve essere influenzato dall'intent che l'ha chiamata (nel tuo caso è superflua). Se ti interessa sapere cosa contiene l'intent nel tuo caso, puoi mettere un breakpoint ed analizzare la variabile.
Qui trovi la descrizione ufficiale (http://developer.android.com/reference/android/app/Activity.html#onNewIntent(android.content.Intent)).

grazie!

Un'ultima cosa mi potresti fare degli esempi di casi d'usi in cui è preferibile usare startActivityForResult() rispetto al startActivity()

Daniels118
13-08-2015, 10:44
startActivityForResult viene utilizzato quando si vuole ottenere una risposta dall'activity richiamata. Supponiamo ad esempio che tu voglia realizzare un'applicazione che necessita di scattare delle foto, ma non vuoi "reinventare la ruota" scrivendo tutte le funzioni necessarie per gestire la fotocamera (white balance, zoom, flash mode, ecc..), piuttosto preferisci appoggiarti all'applicazione di sistema già predisposta a tale scopo. Per fare ciò occorre avviare l'applicazione (activity) della fotocamera, comunicandole che si desidera ricevere una foto (intent).
Nella tua activity avrai una cosa del genere (ho omesso il controllo degli errori per brevità):
void scattaFoto() {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 13);
}

public void onActivityResult(int requestID, int res, Intent data) {
super.onActivityResult(requestID, res, data);
if (requestID == 13) {
Bitmap picture = (Bitmap) data.getExtras().get("data");
// Fai qualcosa con l'immagine ottenuta
}
}
Siccome onActivityResult può gestire il risultato di diverse activity (o più istanze dello stesso tipo di activity) occorre identificare qual'è l'activity che l'ha invocata utilizzando l'id della richiesta, ovvero un numero intero arbitrario ed univoco (nell'esempio ho utilizzato la costante 13, ma è meglio adottare una strategia più robusta).

Riporto dalla doc ufficiale un passo molto significativo:
this method should only be used with Intent protocols that are defined to return a result. In other protocols (such as ACTION_MAIN or ACTION_VIEW), you may not get the result when you expect. For example, if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result

abbobba
13-08-2015, 12:13
capisco, ultima domanda e non ti disturbo più :rolleyes:
se ho per esempio un' activityA che riceve i dati sia dall'activityB sia dall'activityC come faccio a scegliere un determinato comportamento in base all'activity chiamante. Cioè mi spiego meglio l'activityB mi passa i dati B e l'activityC mi passa i dati C, come faccio nell'activityA a capire chi l'ha chiamata ed estrarre i dati corrispondenti.
questo (http://stackoverflow.com/questions/4967799/how-to-know-the-calling-activity-in-android) modo può andare bene o esiste altro?

grazie

Daniels118
13-08-2015, 13:34
L'activity non deve sapere chi la sta chiamando, deve solo rispondere al comportamento richiesto (vedi paragrafo successivo). Puoi specificare il comportamento come extra all'interno dell'intent e recuperarlo dal metodo onNewIntent.
Fai attenzione alla launch mode, in determinate condizioni è possibile che la stessa istanza dell'activity riceva più intent, in questi casi è necessario implementare una politica di gestione.

In ogni caso l'activity dovrebbe rispondere ad un unico tipo di richiesta (comportamento), e tali richieste dovrebbero differenziarsi solo in base a delle opzioni. Tipi di richieste diverse dovrebbero essere gestite da activity diverse; per esempio, l'activity "ScattaFoto" dovrebbe avere in input sempre e solo i parametri necessari per scattare una foto, mentre eventuali opzioni per aprire la galleria delle foto scattate dovrebbe aspettarsele un'activity "Galleria".

Se le opzioni che vuoi passare all'activity sono variabili (pur facendo riferimento alla stessa azione) hai varie alternative, a titolo esemplificativo e non esaustivo riporto le seguenti:
1) passare un extra fisso che descrive il tipo di opzioni presenti;
2) passare un oggetto di una determinata classe che possiede tutte le opzioni con i valori di default, sovrascrivendo solo quelle che vuoi personalizzare.
3) passare un oggetto di classe variabile, ed utilizzare l'istruzione instanceof per determinare a quale classe appartiene.

abbobba
13-08-2015, 13:40
grazie mille :D