Ho ragione nel ritenere che non è possibile inviare trasmissioni "adesive" utilizzando LocalBroadcastManager? Se è così questo sembra molto miope in particolare se un app utilizza frammenti che possono essere scambiati dentro e fuori durante il ciclo di vita dell'applicazione e si basa su dati di trasmissione ..Utilizzo di LocalBroadcastManager per trasmissione "persistente"
risposta
È corretto pensare che non riesco a inviare 'appiccicoso 'trasmissioni utilizzando LocalBroadcastManager?
Sì, hai ragione.
Se è così questo sembra molto miope in particolare se un app utilizza frammenti che possono essere scambiati dentro e fuori durante il ciclo di vita dell'applicazione e si basa su dati di trasmissione ..
Si sono invitati a prendere la codice sorgente a LocalBroadcastManager
e crea le tue estensioni appiccicose, se lo desideri. Personalmente, utilizzerei altri mezzi per archiviare tali dati (frammenti di modello, singoletti o archivi di dati persistenti, a seconda dello scenario).
Ho alcuni frammenti sullo schermo e voglio che, a seconda del frammento "principale" che viene caricato, un piccolo frammento in basso ne modifichi il numero. Volevo farlo inviando una trasmissione su onResume del frammento principale. Ma il frammento che avrebbe dovuto mostrare il numero non è stato caricato in quel punto. Come posso fare questo? .... –
@QuadroQ: chiedi al frammento di estrarre i dati da qualche parte. Oppure, passa a un bus eventi che offre questo tipo di pattern (EventBus di greenrobot offre eventi appiccicosi, Square's offre '@ Producer'). – CommonsWare
Grazie! Stavo pensando a Otto! –
Come ha detto @CommonsWare, ho cercato di implementare appiccicoso con i codici sorgente di LocalBroadcastManager. Verifica: https://gist.github.com/lidemin/5cd4080ebbc74154a0e7
Non so se sia il modo migliore per farlo. Funziona bene fino ad ora. Personalmente preferisco usare Otto.
public class StickyLocalBroadcastManager {
private static class ReceiverRecord {
final IntentFilter filter;
final BroadcastReceiver receiver;
boolean broadcasting;
ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
filter = _filter;
receiver = _receiver;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(128);
builder.append("Receiver{");
builder.append(receiver);
builder.append(" filter=");
builder.append(filter);
builder.append("}");
return builder.toString();
}
}
private static class BroadcastRecord {
final Intent intent;
final ArrayList<ReceiverRecord> receivers;
BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {
intent = _intent;
receivers = _receivers;
}
}
private static final String TAG = "LocalBroadcastManager";
private static final boolean DEBUG = false;
private final Context mAppContext;
private final HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers
= new HashMap<BroadcastReceiver, ArrayList<IntentFilter>>();
private final HashMap<String, ArrayList<ReceiverRecord>> mActions
= new HashMap<String, ArrayList<ReceiverRecord>>();
private final ArrayList<BroadcastRecord> mPendingBroadcasts
= new ArrayList<BroadcastRecord>();
private final ArrayList<Intent> mStickyBroadcasts
= new ArrayList<Intent>();
static final int MSG_EXEC_PENDING_BROADCASTS = 1;
private final Handler mHandler;
private static final Object mLock = new Object();
private static StickyLocalBroadcastManager mInstance;
public static StickyLocalBroadcastManager getInstance(Context context) {
synchronized (mLock) {
if (mInstance == null) {
mInstance = new StickyLocalBroadcastManager(context.getApplicationContext());
}
return mInstance;
}
}
private StickyLocalBroadcastManager(Context context) {
mAppContext = context;
mHandler = new Handler(context.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EXEC_PENDING_BROADCASTS:
executePendingBroadcasts();
break;
default:
super.handleMessage(msg);
}
}
};
}
/**
* Register a receive for any local broadcasts that match the given IntentFilter.
*
* @param receiver The BroadcastReceiver to handle the broadcast.
* @param filter Selects the Intent broadcasts to be received.
* @see #unregisterReceiver
*/
public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
synchronized (mReceivers) {
ReceiverRecord entry = new ReceiverRecord(filter, receiver);
ArrayList<IntentFilter> filters = mReceivers.get(receiver);
if (filters == null) {
filters = new ArrayList<IntentFilter>(1);
mReceivers.put(receiver, filters);
}
filters.add(filter);
for (int i = 0; i < filter.countActions(); i++) {
String action = filter.getAction(i);
ArrayList<ReceiverRecord> entries = mActions.get(action);
if (entries == null) {
entries = new ArrayList<ReceiverRecord>(1);
mActions.put(action, entries);
}
entries.add(entry);
}
//check sticky broadcasts
for (Intent intent : mStickyBroadcasts) {
if (mActions.containsKey(intent.getAction())) {
sendBroadcast(intent, false);
}
}
}
}
/**
* Unregister a previously registered BroadcastReceiver. <em>All</em>
* filters that have been registered for this BroadcastReceiver will be
* removed.
*
* @param receiver The BroadcastReceiver to unregister.
* @see #registerReceiver
*/
public void unregisterReceiver(BroadcastReceiver receiver) {
synchronized (mReceivers) {
ArrayList<IntentFilter> filters = mReceivers.remove(receiver);
if (filters == null) {
return;
}
for (int i = 0; i < filters.size(); i++) {
IntentFilter filter = filters.get(i);
for (int j = 0; j < filter.countActions(); j++) {
String action = filter.getAction(j);
ArrayList<ReceiverRecord> receivers = mActions.get(action);
if (receivers != null) {
for (int k = 0; k < receivers.size(); k++) {
if (receivers.get(k).receiver == receiver) {
receivers.remove(k);
k--;
}
}
if (receivers.size() <= 0) {
mActions.remove(action);
}
}
}
}
}
}
/**
* remove the sticky broadcasts .
* @param action is the action need to be removed.
*/
public void removeStickyBroadcast(String action) {
if (action == null || action.length() <= 0) {
return;
}
synchronized (mStickyBroadcasts) {
Iterator<Intent> intentIterator = mStickyBroadcasts.iterator();
while (intentIterator.hasNext()) {
Intent intent = intentIterator.next();
if (action.equalsIgnoreCase(intent.getAction())) {
intentIterator.remove();
}
}
}
}
/**
* remove all the sticky broadcasts.
*/
public void removeAllStickyBroadcasts(){
synchronized (mStickyBroadcasts){
mStickyBroadcasts.clear();
}
}
/**
* send broadcast with specified action.
* @param action is the action .
* @return
*/
public boolean sendBroadcast(String action){
Intent intent = new Intent(action);
return sendBroadcast(intent);
}
/**
* send broadcast with specified action.
* @param action is the action .
* @return
*/
public boolean sendBroadcast(String action, boolean isSticky){
Intent intent = new Intent(action);
return sendBroadcast(intent, isSticky);
}
/**
* Broadcast the given intent to all interested BroadcastReceivers. This
* call is asynchronous; it returns immediately, and you will continue
* executing while the receivers are run.
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
* @see #registerReceiver
*/
public boolean sendBroadcast(Intent intent) {
return sendBroadcast(intent, false);
}
/**
* Broadcast the given intent to all interested BroadcastReceivers. This
* call is asynchronous; it returns immediately, and you will continue
* executing while the receivers are run.
*
* @param intent The Intent to broadcast; all receivers matching this
* Intent will receive the broadcast.
* @param isSticky The flag of this intent is need to be sticky or not.
* @see #registerReceiver
*/
public boolean sendBroadcast(Intent intent, boolean isSticky) {
if (isSticky) {
mStickyBroadcasts.add(intent);
}
synchronized (mReceivers) {
final String action = intent.getAction();
final String type = intent.resolveTypeIfNeeded(
mAppContext.getContentResolver());
final Uri data = intent.getData();
final String scheme = intent.getScheme();
final Set<String> categories = intent.getCategories();
final boolean debug = DEBUG ||
((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
if (debug) Log.v(
TAG, "Resolving type " + type + " scheme " + scheme
+ " of intent " + intent);
ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());
if (entries != null) {
if (debug) Log.v(TAG, "Action list: " + entries);
ArrayList<ReceiverRecord> receivers = null;
for (int i = 0; i < entries.size(); i++) {
ReceiverRecord receiver = entries.get(i);
if (debug) Log.v(TAG, "Matching against filter " + receiver.filter);
if (receiver.broadcasting) {
if (debug) {
Log.v(TAG, " Filter's target already added");
}
continue;
}
int match = receiver.filter.match(action, type, scheme, data,
categories, "LocalBroadcastManager");
if (match >= 0) {
if (debug) Log.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match));
if (receivers == null) {
receivers = new ArrayList<ReceiverRecord>();
}
receivers.add(receiver);
receiver.broadcasting = true;
} else {
if (debug) {
String reason;
switch (match) {
case IntentFilter.NO_MATCH_ACTION:
reason = "action";
break;
case IntentFilter.NO_MATCH_CATEGORY:
reason = "category";
break;
case IntentFilter.NO_MATCH_DATA:
reason = "data";
break;
case IntentFilter.NO_MATCH_TYPE:
reason = "type";
break;
default:
reason = "unknown reason";
break;
}
Log.v(TAG, " Filter did not match: " + reason);
}
}
}
if (receivers != null) {
for (int i = 0; i < receivers.size(); i++) {
receivers.get(i).broadcasting = false;
}
mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
}
return true;
}
}
}
return false;
}
/**
* Like {@link #sendBroadcast(Intent, boolean)}, but if there are any receivers for
* the Intent this function will block and immediately dispatch them before
* returning.
*/
public void sendBroadcastSync(Intent intent) {
if (sendBroadcast(intent, false)) {
executePendingBroadcasts();
}
}
private void executePendingBroadcasts() {
while (true) {
BroadcastRecord[] brs = null;
synchronized (mReceivers) {
final int N = mPendingBroadcasts.size();
if (N <= 0) {
return;
}
brs = new BroadcastRecord[N];
mPendingBroadcasts.toArray(brs);
mPendingBroadcasts.clear();
}
for (int i = 0; i < brs.length; i++) {
BroadcastRecord br = brs[i];
for (int j = 0; j < br.receivers.size(); j++) {
br.receivers.get(j).receiver.onReceive(mAppContext, br.intent);
}
}
}
}
}
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. –
@Markus Grazie per il vostro consiglio. La prima volta dopo la risposta su Stackoverflow. – Damon
- 1. NullPointerException quando si utilizza LocalBroadcastManager
- 2. Equivalente di LocalBroadcastManager senza libreria di supporto Android
- 3. LocalBroadcastManager vs utilizzando le callback
- 4. Posso usare AlarmManager con LocalBroadcastManager su Android?
- 5. È possibile verificare se una trasmissione è stata inviata in modalità persistente? Può essere abortito/rimosso?
- 6. Memoria persistente per Apache Mesos
- 7. BroadcatReceiver dichiarato nel manifest.xml non ricevere intenti LocalBroadcastManager
- 8. Invia trasmissione per notifica click
- 9. Ricevitore di trasmissione per l'inserimento nei contatti
- 10. Persistente vs non persistente - Quale dovrei usare?
- 11. Strategia di archiviazione persistente iOS
- 12. Prestazioni di trasmissione multicast
- 13. Interfacce COM di trasmissione
- 14. Debug di trasmissione SOAP
- 15. Servizio persistente
- 16. Trasmissione Bluetooth
- 17. Trasmissione a enumerazione nullable
- 18. Esempio di persistente con operatore specifico backend
- 19. Come interrompere la notifica di trasmissione? (per una trasmissione non ordinata)
- 20. Cache query persistente Entity Framework
- 21. Capire lo Scapy "Indirizzo Mac per raggiungere la destinazione non trovata. Utilizzo della trasmissione". warning
- 22. Hash persistente per i programmi Ruby?
- 23. Trasmissione del risultato di TableOperation.Retrieve
- 24. Cronologia persistente di Windows PowerShell
- 25. IFrame persistente nell'estensione di Chrome
- 26. Tipo di tipi personalizzati di trasmissione per tipi di base
- 27. Memoizzazione persistente in Python
- 28. Parametri di trasmissione con HttpURLConnection
- 29. Nessuna trasmissione per tf.matmul in TensorFlow
- 30. Ricerca di coda persistente, distribuita, di lavoro per erlang
Le trasmissioni appiccicose sono ora deprecate in ogni caso. – Malcolm