2012-06-07 13 views
5

Wdrażam klienta REST w systemie Android. Widziałem przykład użycia Service do wykonania połączenia z serwerem i ResultReceiver, aby otrzymać powiadomienie o zakończeniu operacji. Wywołuję usługę z fragmentu i jeśli spróbuję obrócić ekran podczas działania usługi, metoda getActivity() w ResultReceiver zwraca wartość null, ponieważ prawdopodobnie ten fragment nie jest już w układzie.ResultReceiver nie przetrwał do rotacji ekranu

Sposób zwrotna we fragmencie:

@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); 
     } 

    } 
} 

W getActivity() powraca null. Czy to normalne? W jaki sposób mogę zezwolić na powiadomienia nawet przy obrocie ekranu? Lokalne transmisje?

Odpowiedz

1

Używam BroadcastReceiver zarejestrowany przy użyciu LocalBroadcastManager i czy działa prawidłowo. To nie było takie proste. Czy istnieje lepsze rozwiązanie?

-1

Funkcja getActivity() zwraca wartość null. Czy to normalne?

Aktywności Androida są odtwarzane po obróceniu urządzenia.

Po działalność odtworzył nie posiada stary context.that dlatego dostajesz getActivity() za nieważną

Jakie podejście mogłem użyć, aby umożliwić powiadomienie nawet na ekranie obrotu? Lokalne transmisje?

Jeśli nie chcesz, aby aktywność odtworzone na ekranie następujący rotation.mention w oczywisty

 <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> 

i ostatni Będziesz musiał zastąpić następujące aktywności.

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

Dzięki za odpowiedź. Właściwie wolałbym nie ustawiać manifestu screenOrientation, ponieważ układ jest inny w trybie poziomym, więc nie mogę tego ustawić. – Matroska

1

Myślę, że natknąłem się na ten sam problem i rozwiązałem go, sprawdzając NULL w metodzie onReceivedResult mojego ResultReceiver. Kod pisał tutaj prace na fragmencie Worker (fragment bez UI i setRetainInstance (true) w onCreate)

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

flagami notificationPending pomaga fragment przytrzymaj oczekujące powiadomienie, jeżeli działalność nie została znaleziona (działalność nie jest dostępny na fragment Detach).

Gdy fragment reattaches do aktywności i wykonać tę logikę

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

nadzieję, że to pomaga. Możesz poprosić o dalsze szczegóły, jeśli chcesz. Cheers

12

Nie,

android:configChanges="orientation" 

nie jest rozwiązaniem.

Aby korzystać ResultReceiver I:

  • zapisać go na zmiany orientacji:

    @Override 
    public void onSaveInstanceState(Bundle outState) { 
        outState.putParcelable(Consts.RECEIVER, mReceiver); 
        super.onSaveInstanceState(outState); 
    } 
    
  • zresetować odbiornik:

    @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); 
    } 
    

Oto moja klasa 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

Genialny! Widziałem wiele innych podobnych pytań (z wieloma upvotes) związanych z [ResultReceiver] (http://developer.android.com/reference/android/os/ResultReceiver.html) i każde z nich radziło sobie z tak częstym scenariuszem, jak aktywność rekreacja. – villoren

+0

Jak można uniknąć wyjątku ClassCastException w onCreateView() podczas wywoływania getParcelable()? Czy metoda getParcelable() nie zwróci instancji ResultReceiver (nie instancji twojej podklasy), ponieważ twoja podklasa nie implementuje Parcelable.CREATOR? – Alan

+0

@Alan Dzięki moim testom, po obróceniu urządzenia powyższa metoda działa. Jednak jeśli Android wyłączy aplikację w tle i uruchomisz ją ponownie, otrzymam wyjątek ClassCastException onCreateView(). Nie jestem pewien, dlaczego, ale to jest to, co znalazłem w moich testach ... – Micro

Powiązane problemy