2012-06-07 16 views
5

Sto implementando un client REST in Android. Ho visto un esempio di utilizzo di un Service per eseguire la connessione al server e lo ResultReceiver da notificare del completamento dell'operazione. Sto chiamando il servizio da un frammento e, se provo a ruotare lo schermo mentre il servizio è in esecuzione, il metodo getActivity() in ResultReceiver restituisce null perché probabilmente quel frammento non è più nel layout.ResultReceiver non sopravvive alla rotazione dello schermo

Il metodo di callback nel frammento:

@Override 
public void onReceiveResult(int resultCode, Bundle resultData) { 
    Response response = (Response) resultData 
      .getSerializable(RestService.RESULT); 
    if (resultCode == RestService.SUCCESS 
      && response != null) { 
     if (getActivity() != null) { 
      recommendationResponse = response; 
      getLoaderManager().restartLoader(0, new Bundle(), 
        Fragment.this); 
     } 

    } 
} 

I getActivity() restituisce null. È normale? Quale approccio potrei utilizzare per consentire la notifica anche sulla rotazione dello schermo? Trasmissione locale?

risposta

1

Sto usando un BroadcastReceiver registrati utilizzando LocalBroadcastManager e sta funzionando correttamente. Non era così semplice. Esiste una soluzione migliore?

-1

getActivity() restituisce null. È normale?

Le attività Android vengono ricreate dopo la rotazione del dispositivo.

Dopo l'attività è ricreato esso non tiene vecchio context.that perché vostro ottenere getActivity() nullo

Quale approccio potrei usare per consentire la notifica anche sullo schermo rotazione? Trasmissione locale?

Se non volete l'attività per ricreato sullo schermo rotation.mention segue in palese

 <activity 
      android:name=".MyActivity" 
      android:configChanges="orientation" <<<<<<<<< 
      android:label="@string/app_name" 
      android:screenOrientation="portrait" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

E durare Si dovrà sostituire in seguito in attività.

@Override 
    public void onConfigurationChanged(Configuration newConfig) 
    { 
     // TODO Auto-generated method stub 
     super.onConfigurationChanged(newConfig); 
    } 
+2

Grazie per la risposta. In realtà preferirei non impostare screenOrientation su manifest perché il layout è diverso in modalità landscape, quindi non posso impostarlo. – Matroska

1

Penso di essermi imbattuto nello stesso problema e di averlo risolto verificando NULL nel metodo onReceivedResult del mio ResultReceiver. Il codice postato qui lavora su un frammento operaio (frammento senza interfaccia utente e setRetainInstance (vero) in onCreate)

protected void onReceiveResult(int resultCode, Bundle resultData) { 
      //Verify activity 
      if(getActivity() != null){ 
       //Handle result 
      }else{ 
       notificationPending = true;     
      } 
     } 

Le bandiere notificationPending aiuta il frammento di tenere la notifica in sospeso se non è stata trovata l'attività (attività non è accessibile frammento Detach).

Quando il frammento riattacca all'attività Eseguo questa logica

public void onAttach(Activity activity){ 
    super.onAttach(activity); 
     if(notificationPending){ 
      //Handle notification 
      notificationPending = false; 
     } 
} 

Speranza che aiuta. Puoi chiedere ulteriori dettagli se ti va. Acclamazioni

12

No,

android:configChanges="orientation" 

non è una soluzione.

Per utilizzare ResultReceiver I:

  • salvatelo sul cambiamento di orientamento:

    @Override 
    public void onSaveInstanceState(Bundle outState) { 
        outState.putParcelable(Consts.RECEIVER, mReceiver); 
        super.onSaveInstanceState(outState); 
    } 
    
  • reimpostare il ricevitore:

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) { 
    
        if (savedInstanceState != null) { 
         mReceiver = savedInstanceState.getParcelable(Consts.RECEIVER); 
        } 
        else { 
         mReceiver = new MyResultReceiver(new Handler()); 
        } 
        mReceiver.setReceiver(this); 
    } 
    

Ecco la mia classe ResultReceiver:

import android.os.Bundle; 
import android.os.Handler; 
import android.os.ResultReceiver; 

public class MyResultReceiver extends ResultReceiver { 
    private Receiver mReceiver; 

    public MyResultReceiver(Handler handler) { 
     super(handler); 
    } 

    public void setReceiver(Receiver receiver) { 
     mReceiver = receiver; 
    } 

    public interface Receiver { 
     public void onReceiveResult(int command, Bundle resultData); 
    } 

    @Override 
    protected void onReceiveResult(int command, Bundle resultData) { 
     if (mReceiver != null) { 
      mReceiver.onReceiveResult(command, resultData); 
     } 
    } 
} 
+0

Brillante! Ho visto molte altre domande simili (con molti upvotes) relativi a [ResultReceiver] (http://developer.android.com/reference/android/os/ResultReceiver.html), e ognuno di essi ha affrontato con successo uno scenario così frequente come attività ricreazione. – villoren

+0

Come si evita una classe ClassCastException in onCreateView() quando si chiama getParcelable()? Does not getParcelable() restituisce un'istanza ResultReceiver (non un'istanza della sottoclasse) in quanto la sottoclasse non implementa Parcelable.CREATOR? – Alan

+0

@Alan Con il mio test, quando si ruota il dispositivo, il metodo sopra funziona. Tuttavia, se Android chiude l'app in background e lo riavvii, ottengo ClassCastException in onCreateView(). Non sono sicuro del perché, ma questo è quello che ho trovato dai miei test ... – Micro

Problemi correlati