2013-08-13 4 views
5

Ich habe mit meiner App-Struktur für eine Weile gekämpft. Und es scheint wirklich so zu sein, dass diese Struktur mir bei der Entwicklung anderer Features viel Schmerz bereitet. Bevor ich weiter gehe, möchte ich einen Ratschlag haben und sehen, ob ich hier etwas falsch mache.App-Flow mit AccountManager

Zweck meiner App ist die Verbindung mit einem Server, ich benutze den AccountManager-Mechanismus, um ein Konto auf dem Gerät zu erstellen und ein Token zu speichern, das verwendet werden soll, um Daten vom Server anzufordern. Bei der Erstellung des Accounts ist alles in Ordnung. (Es funktioniert auch in den Geräteeinstellungen -> fügen Sie ein Konto)

Es so geht:

MainActivity die Aktivität ist, die, wenn Sie die App starten, prüfen Sie, ob Sie ein Konto haben. Wenn Sie ein Konto haben, bekomme ich das Token in einer statischen Variable, so dass jedes Fragment in der MainActivity darauf zugreifen kann. (Soll funktionieren, tut es aber nicht) Ansonsten erstelle ich mit LoginActivity eine Absicht, um ein Konto auf dem Gerät zu erstellen. Das Problem ist, dass meine Fragmente dieses Token nicht bekommen können, da, während ich das Token in einem Thread mithilfe von AccountManager.getAuthToken() wiederherstelle, die Fragmente erstellt werden, bevor dieses Token wiederhergestellt wird. Daher kann ich keine Daten von meinem Server anfordern.

Was mich dazu gebracht hat zu denken, dass meine App-Struktur nicht so gut sein könnte. Also dachte ich: "Was ist wenn ich es mag?" :

  • Der Benutzer startet die App
  • MainActivity wirken wie eine Bootstrap, die für Rechnung überprüfen und Token erhalten, wenn ein Konto auf dem Gerät gibt es aber keine Art von Ansicht wie die aktuelle Version erzeugen. entweder
  • MainActivity zu LoginActivity oder ContentActivity umleiten (nennen wir es auf diese Weise, eine Tätigkeit, die mein Token angenommen hat, zu verwenden, um Daten in meinem Listviews aufzufüllen)

Auf diese Weise mich denken lässt, dass MainActivity das Token haben wird Pass aber ich bin mir nicht sicher, es ist ideal in Bezug auf UX. (Ich muss auf Token warten, bevor ich auf einen Inhalt zugreife). Ich bin offen für jeden Vorschlag an diesem Punkt, da ich wirklich feststecke.

Danke!

Update 1:

Es ist eher ein Login/Logik-Anwendung Registrierung als Accountmanager Handhabung. Ich habe es geschafft, sie zum Laufen zu bringen, aber ich habe wirklich Probleme mit der App-Logik-Struktur "Best Practice", so dass ich nicht auf viele andere Probleme stoße (weil ich nicht wirklich Zeit habe). Alles, was ich brauche, ist ein Diagramm oder etwas, das mir ein "Best Practice" -Beispiel zeigt, damit meine App so funktioniert, wie ich oben erklärt habe. Ich stieß auch auf ein Problem, weil, wenn ich die MainActivity starte, es nach einem Konto sucht, und wenn nicht, startet es LoginActivity, aber wenn ich zurückdrücke, kann ich MainActivity (ungefüllt) sehen.

Antwort

4

Mehr eine allgemeine Praxis ist, was Sie verwenden:

General Practice

Diese Struktur völlig akzeptabel ist, und ist ein normaler Fluss von Server-abhängige Anwendungen. Ich bevorzuge das Modell, bei dem die Protokollierung nur eine Option mit einigen Inhalten ist, für die keine Anmeldung erforderlich ist. Wenn eine Aktion ausgelöst wird, die eine Anmeldung erfordert, wird dem Benutzer die Anmeldung angezeigt. Ihr Modell sollte jedoch gut funktionieren.

Ich sehe, dass Ihre Probleme

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

    Dieses Problem sind, kann mit einer unsichtbaren Dispatch-Aktivität gelöst werden, die die MainActivity oder die LoginActivity starten basierend auf dem Status des aktuellen Benutzers. Wie im Diagramm, nur finish() die Dispatch-Aktivität nach Ihrer Entscheidung. Ihre LoginActivity ist dafür verantwortlich, die DispatchActivity neu zu starten, die im nächsten Schritt neu definiert wird. Im Allgemeinen sollten Sie OnBackPressed von LoginActivity nicht überschreiben, um den Dispatch zu starten. Starten Sie den Dispatch im Falle einer erfolgreichen Anmeldung.

    Wenn Sie sich jedoch entschieden haben, Inhalte in Ihrer Aktivität anzuzeigen, selbst wenn der Benutzer nicht angemeldet ist, können Sie den Inhalt der MainActivity mithilfe der onActivityResult nach einer Anmeldeanforderung aktualisieren.

  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.

    Dieses Problem ist normal. Wenn Ihre Aktivitäten/Fragmente bereits bei der Verarbeitung einer Anmeldeanforderung erstellt wurden, müssen Sie diese Informationen bereitstellen können. Wenn Ihre Fragmente keinen "nicht authentifizierten" Inhalt zeigen, sollten Sie dieses Problem grundsätzlich nicht haben, da Sie diese Fragmente erst erstellen sollten, wenn Sie angemeldet sind.

    Aber auch wenn Sie sich entschieden haben, einige zu zeigen Inhalt in Ihren Aktivitäten/Fragmenten auch wenn der Benutzer nicht eingeloggt ist, müssen Sie diese laufenden Komponenten über die Statusänderung informieren. Eine Möglichkeit besteht darin, in Ihren Aktivitäten ein onResume zu implementieren, das überprüft, ob der Benutzer angemeldet ist und die entsprechenden Änderungen vornimmt. Eine weitere Möglichkeit ist es, eine lokale Broadcast verwenden Aktivitäten zu informieren Laufen/Fragmente, die den Zustand geändert hat:

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

    Jedes Mal, wenn sich der Zustand ändert, eine Broadcast senden:

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

Of Natürlich kann dies fallspezifisch sein. Wenn Sie beispielsweise die Touch App on Google Play überprüfen, werden Sie feststellen, dass ich einen Versandbildschirm erstellt habe, der unabhängig vom Anmeldestatus des Benutzers sichtbar ist, und den Benutzer dann zur Anmeldung auffordert, wenn er eine Aktivität eingibt, die eine Anmeldung erfordert. In diesem Fall sollte jede Aktivität, die eine Anmeldung erfordert, ihr onActivityResult entsprechend implementieren und die Benutzerschnittstelle aktualisieren, wenn der Benutzer sich angemeldet hat, oder beenden, wenn der Benutzer dies nicht getan hat. Auf der anderen Seite verwendet die psst app on Google Play einen Begrüßungsbildschirm, um zu entscheiden, ob der Anmeldebildschirm oder der Hauptbildschirm angezeigt werden soll, abhängig vom Status des Benutzers.

+0

hatte einen Blick auf dem Last.fm-App, die vollständig Open Source ist und er tut diese Art von Sendungen direkt in die „Login“ Aktivität. Er überprüft tatsächlich eine Menge Dinge (wie Vorsatz), weil diese Aktivität verwendet wird, wenn der Benutzer von der Einstellung "Konto hinzufügen" kommt, wenn der Benutzer das App-Widget konfiguriert oder wenn er die App gerade startet. Denkst du, dass das auch ein guter Weg sein könnte? (hier ist der Link des Aktivitätscodes https://github.com/c99koder/lastfm-android/blob/master/app/src/fm/last/android/LastFm.java) Ich möchte auch SplashScreen vermeiden, weil ich denke, es ist schlecht für die UX – CinetiK

+0

Es ist gut. Ja. Wenn man darauf besteht, kann eine einzige Aktivität für alles verwendet werden. –

+0

Vielen Dank, du hast mir wirklich dabei geholfen! Ich habe es geschafft, es jetzt zum Laufen zu bringen. – CinetiK

0

Beispielcode ..

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

      } 
     } 
    } 
}