2013-08-13 25 views
5

Od pewnego czasu borykam się z moją strukturą aplikacji. I naprawdę wygląda na to, że ta struktura sprawia mi wiele bólu w rozwoju innych funkcji. Zanim przejdę dalej, chciałbym zasięgnąć porady i zobaczyć, czy robię coś złego tutaj.Przepływ aplikacji z AccountManager

Celem mojej aplikacji jest połączenie z serwerem, używam mechanizmu AccountManager do utworzenia konta na urządzeniu i przechowywania tokena, który ma służyć do żądania danych z serwera. Podczas tworzenia konta wszystko jest w porządku. (Działa także od ustawień urządzenia -> dodaj konto)

To idzie tak:

główną działalność jest działalnością, która, gdy uruchomisz aplikację, sprawdź czy masz konto. Jeśli masz konto, otrzymuję token w zmiennej statycznej, więc każdy fragment w MainActivity może uzyskać do niego dostęp. (Przypuszczalnie działa, ale nie) Inaczej, tworzę intencję z LoginActivity, aby utworzyć konto na urządzeniu. Problem polega na tym, że moje fragmenty nie mogą uzyskać tego tokena, ponieważ podczas odtwarzania tokena w wątku za pomocą obiektu AccountManager.getAuthToken() fragmenty są tworzone przed odzyskaniem tego tokenu. I dlatego nie mogę żądać danych z mojego serwera.

Które doprowadziło mnie do myślenia, że ​​moja struktura aplikacji może nie być tak dobra. Tak więc myślałem: "A co jeśli tak zrobię?" :

  • Użytkownik uruchamia aplikację
  • główną działalność, które działają jak sprawdzić na konto i żeton, czy istnieje konto na urządzeniu, ale nie generują żadnego rodzaju widok jak w aktualnej wersji startowej.
  • główną działalność albo przekierować do LoginActivity lub ContentActivity (nazwijmy to w ten sposób, działanie, które miało korzystać z tokena, aby wypełnić dane w moich ListViews)

ten sposób pozwala mi myśleć, że główną działalność będzie mieć token do przejść, ale nie jestem pewien, czy jest idealny pod względem UX. (Musisz poczekać na token przed uzyskaniem dostępu do zawartości). Jestem otwarty na każdą sugestię w tym momencie, ponieważ naprawdę utknąłem.

Dzięki!

Aktualizacja 1:

To raczej logowania/rejestracji aplikacji logiki niż obsługa AccountManager. Udało mi się sprawić, by działały, ale ja po prostu mam problem z konstrukcją logiki aplikacji "najlepsza praktyka", więc nie napotykam na wiele innych problemów z tego powodu (ponieważ tak naprawdę nie mam czasu). Potrzebuję tylko diagramu lub czegoś, co pokaże mi przykład "najlepszej praktyki", aby moja aplikacja działała w sposób opisany powyżej. Wystąpił również problem, ponieważ po uruchomieniu MainActivity sprawdza konto, a jeśli nie, uruchamia funkcję LoginActivity, ale jeśli cofnę, mogę zobaczyć MainActivity (unfilled).

Odpowiedz

4

Więcej z ogólną praktyką jest to, co używasz:

General Practice

Struktura ta jest całkowicie do zaakceptowania i jest to normalny przepływ server-Dependent aplikacji. Wolę model, w którym rejestrowanie jest tylko opcją z pewną treścią, która nie wymaga logowania. Za każdym razem, gdy uruchamiana jest akcja wymagająca logowania, użytkownikowi wyświetlany jest login. Jednak twój model powinien działać dobrze.

widzę, że wasze problemy są

  1. I also ran into a problem because when I start the MainActivity it checks for an account and if not it launches LoginActivity but if I press back, i can see MainActivity (unfilled).

    Ten problem może być rozwiązany za pomocą niewidzialnej Dispatch działalność, która wysyła główną działalność lub LoginActivity na podstawie stanu aktualnego użytkownika. Jak na diagramie, po Twojej decyzji jest tylko aktywność wysyłkowa. Twój LoginActivity jest odpowiedzialny za ponowne uruchomienie DispatchActivity, które zostanie ponownie zdefiniowane w następnym kroku. Ogólnie rzecz biorąc, nie zastępuj onBackPressed z LoginActivity, aby uruchomić Dispatch, wystarczy uruchomić Dispatch w przypadku pomyślnego zalogowania.

    Jeśli jednak zdecydujesz się pokazać trochę treści w swojej aktywności, nawet jeśli użytkownik nie jest zalogowany, możesz użyć odświeżenia zawartości głównego atrybutu po żądaniu logowania za pomocą onActivityResult.

  2. The problem is that my fragments can't get this token because, as i'm recovering the token in a thread using AccountManager.getAuthToken(), the fragments are created before this token is recovered.

    Ten problem jest normalne. Jeśli twoje działania/fragmenty zostały już utworzone podczas przetwarzania żądania logowania, musisz być w stanie je poinformować. Zasadniczo, jeśli twoje fragmenty nie pokazują "nieuwierzytelnionych" treści, nie powinieneś stawić czoła temu problemowi, ponieważ nie powinieneś nawet tworzyć tych fragmentów, dopóki się nie zalogujesz.

    Jednak, jeśli zdecydowałeś się pokazać zawartość w twoich działaniach/fragmentach, nawet jeśli użytkownik nie jest zalogowany, musisz poinformować te działające komponenty o zmianie statusu. Jednym ze sposobów jest wdrożenie usługi onResume w swoich działaniach, która sprawdza, czy użytkownik jest zalogowany i czy wprowadza odpowiednie zmiany. Innym sposobem jest użycie Local transmisję poinformować prowadzenie działalności/fragmenty że stan uległa zmianie:

    BroadcastReceiver mReciever = new BroadcastReceiver() { 
        public void onReceive(Context context, Intent intent) { 
          //do whatever you want //check state 
        } 
    }; 
    
    public void onCreate(Bundle state) { 
        //bla bla 
        //bla bla 
        LocalBroadcastManager.getInstance(mContext).registerReceiver(mReciever, new IntentFilter("your_package_name.LOGIN_STATE_CHANGED")); 
    } 
    

    Gdy zmienia się stan, wyślij nadanie:

    Intent intent = new Intent("your_package_name.LOGIN_STATE_CHANGED"); 
    LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent); 
    

Of Oczywiście może się to zdarzyć w konkretnym przypadku. Na przykład, jeśli sprawdzisz Touch App on Google Play, zauważysz, że utworzyłem ekran wysyłkowy, który jest widoczny niezależnie od stanu logowania użytkownika, a następnie poprosił użytkownika o zalogowanie się, jeśli wejdzie w działanie, które wymaga zalogowania. W takim przypadku każda aktywność wymagająca logowania powinna odpowiednio zaimplementować właściwość onActivityResult i zaktualizować ui, jeśli użytkownik zaloguje się lub zakończy, jeśli użytkownik tego nie zrobił. Z drugiej strony, psst app on Google Play używa ekranu powitalnego, aby zdecydować, czy przejść do ekranu logowania, czy ekranu głównego, w zależności od stanu użytkownika.

+0

miał spojrzeć na aplikację Last.fm, który jest w pełni open source i robi tego rodzaju wysyłek bezpośrednio do „login” aktywność. Sprawdza on wiele rzeczy (np. Działanie intencji), ponieważ ta czynność jest używana, gdy użytkownik pochodzi z ustawienia "dodaj konto", gdy użytkownik konfiguruje widżet aplikacji lub gdy tylko uruchamia aplikację. Czy uważasz, że to może być dobry sposób, aby to zrobić? (tutaj jest link kodu aktywności https://github.com/c99koder/lastfm-android/blob/master/app/src/fm/last/android/LastFm.java) Chcę również uniknąć SplashScreen, ponieważ Myślę, że to jest złe dla UX – CinetiK

+0

To jest dobre. tak. Jeśli ktoś nalega, za wszystko można wykorzystać jedną czynność. –

+0

Wielkie dzięki, naprawdę mi pomogłeś! Udało mi się sprawić, że teraz działa. – CinetiK

0

przykładowy kod ..

public class DispatchActivity extends ActionBarActivity { 


    SharedPreferences prefs = null; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 


     prefs = getSharedPreferences("me.sanath.megh", MODE_PRIVATE); 
     boolean islogin = prefs.getBoolean("islogin",false); 
     if(islogin) 
     { 
      Intent i = new Intent(this,homepageActivity.class); 
      startActivity(i); 
      finish(); 
     }else{ 

      Intent i = new Intent(this,LoginActivity.class); 
      startActivityForResult(i,1); 
     } 
    } 

    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 

     if (requestCode == 1) { 
      boolean islogin = prefs.getBoolean("islogin",false); 
      if(islogin) 
      { 
       Intent i = new Intent(this,homepageActivity.class); 
       startActivity(i); 
       finish(); 
      }else{ 

       Intent i = new Intent(this,LoginActivity.class); 
       startActivityForResult(i,1); 

      } 
     } 
    } 
}