0

Ich habe 2 Aktivitäten: - LoginActivity: es wird die Anmeldeinformationen später - MainActivity: die Haupt-App, alle Funktionen werden auf Fragmenten zur Verfügung gestellt werden.So verwenden Sie Backstack richtig auf Aktivitäten und Fragmente

Ich möchte den Backstack richtig verwenden, aber ich kann nicht.

Was ich will (aber nicht erreichen kann): App startet mit Login-Bildschirm. Ich logge mich ein (jetzt drücke die Start-Taste), danach erscheint der Hauptbildschirm und das erste Fragment wird geladen. Jetzt, wenn ich die Zurück-Taste drücke, schließt sich die App, und so sollte es funktionieren, es darf nicht mit einem einfachen Zurück-Knopfdruck zum Anmeldebildschirm zurückkehren.

Aber jetzt, wenn ich abmelden (und der Login-Bildschirm erscheint), und ich drücke die Zurück-Taste, bringt mich die App zurück zum Hauptbildschirm, was wirklich nicht in Ordnung ist. Wenn ich mich abmelde, sollte die Zurück-Schaltfläche vom Anmeldebildschirm aus die App schließen.

Und ein anderes Problem, in Bezug auf Backstack und Fragmente: Ich habe 3 Fragmente: erste, zweite und dritte. Wenn ich sie nacheinander öffne (innerhalb der Hauptaktivität natürlich), und ich drücke die Zurück-Taste, möchte ich, dass sie mich zurück zum zuvor geöffneten Fragment bringt, oder wenn es keine vorherige gibt, schließe die App. Jetzt macht es es, öffnet das vorherige Fragment, aber gleichzeitig schließt es die komplette App. (Ich kann sehen, dass sie direkt hintereinander passieren)

Was fehlt? Was sollte geändert werden, um dieses (normale) Verhalten zu erreichen?

Danke!

Mein Code:

MainActivity:

public class MainActivity extends AppCompatActivity 
    implements NavigationView.OnNavigationItemSelectedListener { 

public static final String SP_DATA = "SP_DATA"; 
public static final String FB_LOGIN_STATUS = "FB_LOGIN_STATUS"; 
public static final String FLRT = "FLRT"; 

public SharedPreferences sharedPreferences; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE); 
    boolean bAlreadyLoggedIn = sharedPreferences.getBoolean(FB_LOGIN_STATUS, false); 

    if (bAlreadyLoggedIn) { 
     Log.d(FLRT, "Already logged in"); 
    } 
    else { 
     Log.d(FLRT, "Not logged in"); 

     Intent intent = new Intent(MainActivity.this, LoginActivity.class); 
     startActivity(intent); 
    } 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

    showFragment(new FirstFragment(),"FirstFragment"); 

    Button btnLogout = (Button) findViewById(R.id.btnLogout); 

    btnLogout.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

      logout(); 

      showActivity(MainActivity.this, LoginActivity.class); 
     } 
    }); 

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
    fab.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 
        .setAction("Action", null).show(); 
     } 
    }); 

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
      this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
    drawer.setDrawerListener(toggle); 
    toggle.syncState(); 

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 
    navigationView.setNavigationItemSelectedListener(this); 
} 

private void showActivity(Context context_fromActivity, Class<?> class_toActivty){ 
    Intent intent = new Intent(context_fromActivity, class_toActivty); 
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
    startActivity(intent); 
} 

private void logout() { 
    Log.d(FLRT, "Logging out..."); 

    sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE); 
    SharedPreferences.Editor editor = sharedPreferences.edit(); 
    editor.putBoolean(FB_LOGIN_STATUS, false); 
    editor.commit(); 
} 

@Override 
public void onBackPressed() { 
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
    if (drawer.isDrawerOpen(GravityCompat.START)) { 
     drawer.closeDrawer(GravityCompat.START); 
    } else { 
     super.onBackPressed(); 
    } 

    if (getFragmentManager().getBackStackEntryCount() > 0){ 
     getFragmentManager().popBackStack(); 
    } else { 
     super.onBackPressed(); 
    } 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle action bar item clicks here. The action bar will 
    // automatically handle clicks on the Home/Up button, so long 
    // as you specify a parent activity in AndroidManifest.xml. 
    int id = item.getItemId(); 

    //noinspection SimplifiableIfStatement 
    if (id == R.id.action_settings) { 
     return true; 
    } 

    return super.onOptionsItemSelected(item); 
} 

@SuppressWarnings("StatementWithEmptyBody") 
@Override 
public boolean onNavigationItemSelected(MenuItem item) { 
    // Handle navigation view item clicks here. 
    int id = item.getItemId(); 

    if (id == R.id.nav_first_layout) { 
     showFragment(new FirstFragment(), "FirstFragment"); 
    } 
    else if (id == R.id.nav_second_layout) { 
     showFragment(new SecondFragment(), "SecondFragment"); 
    } 
    else if (id == R.id.nav_third_layout) { 
     showFragment(new ThirdFragment(), "ThirdFragment"); 
    } 
    else if (id == R.id.nav_share) { 

    } 
    else if (id == R.id.nav_send) { 

    } 

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
    drawer.closeDrawer(GravityCompat.START); 
    return true; 
} 

private void showFragment(Fragment fragment, String sFragmentTAG) { 
    FragmentManager fragmentManager = getFragmentManager(); 
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 

    if (fragmentManager.findFragmentByTag(sFragmentTAG) != null) { 
     Log.d(FLRT, "Fragment found, using existing one: " + sFragmentTAG); 
     fragment = fragmentManager.findFragmentByTag(sFragmentTAG); 
    } 
     fragmentTransaction.replace(R.id.fragmentContainer, fragment, sFragmentTAG); 
     fragmentTransaction.addToBackStack(null); 
     fragmentTransaction.commit(); 

} 
} 

LoginActivity:

public class LoginActivity extends AppCompatActivity { 

public static final String SP_DATA = "SP_DATA"; 
public static final String FB_LOGIN_STATUS = "FB_LOGIN_STATUS"; 
public static final String FLRT = "FLRT"; 

public SharedPreferences sharedPreferences; 

private Button btn_start; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_login); 

    btn_start = (Button) findViewById(R.id.btn_start); 

    btn_start.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 

      login(); 

      showActivity(LoginActivity.this, MainActivity.class);; 
     } 
    }); 
} 

private void showActivity(Context context_fromActivity, Class<?> class_toActivty){ 
    Intent intent = new Intent(context_fromActivity, class_toActivty); 
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
    startActivity(intent); 
} 

private void login() { 
    Log.d(FLRT, "Logging in..."); 

    sharedPreferences = getSharedPreferences(SP_DATA, MODE_PRIVATE); 
    SharedPreferences.Editor editor = sharedPreferences.edit(); 
    editor.putBoolean(FB_LOGIN_STATUS, true); 
    editor.commit(); 
} 
} 

Antwort

1

Über zwischen Activities wechseln.

Eine wichtige Sache.
In showActivity()finish()Activityverwenden, wenn Sie zu einem anderen gehen. Wenn es nicht hilft - siehe unten.

Versuchen Sie auch FLAG_ACTIVITY_NEW_TASK mit Ihrem aktuellen Flag zu verwenden, weil FLAG_ACTIVITY_CLEAR_TOP nur Aktivitäten in Aufgabe oberhalb der aktuellen Aktivität, aber nicht darunter schließt.
So wäre es dies: intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Eine weitere Option ist die Verwendung: FLAG_ACTIVITY_CLEAR_TASK nur - neue Aktivität wird in es die Aufgabe und sich als root löschen.

Wenn beide nicht helfen - verwenden Sie android:launchMode = "singleInstance" im Manifest für jede Actitivy.


über Fragments - Ich sehe einen kleinen Fehler in Ihrem Code: Er ruft super.onBackPressed(); vor Fragment von BackStack
knallen würde ich so ändern:

@Override 
public void onBackPressed() { 
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
    if (drawer.isDrawerOpen(GravityCompat.START)) { 
     drawer.closeDrawer(GravityCompat.START); 
    } else if (getFragmentManager().getBackStackEntryCount() > 0){ 
     getFragmentManager().popBackStack(); 
    } else { 
     super.onBackPressed(); 
    } 
} 

!! Auch sollten Sie diese Zeile testen: getFragmentManager().getBackStackEntryCount() > 0 mit 0 und 1 in Zustand (weil in der aktuellen Implementierung in meinem Projekt FragmentContainer als erste, Null-Wert in einem BackStack berücksichtigt). Testen Sie einfach 0 und 1, um zu sehen, welche funktioniert.

Danke.


PS. Noch ein paar Tipps.

Sie können FragmentManager fragmentManager in Ihrem Activity deklarieren, um es einmalig in onCreate() zu erstellen. Es wäre besser, als es jedes Mal zu bekommen.

Betrachten Sie dies ändern:

if (id == R.id.nav_first_layout) { 
     showFragment(new FirstFragment(), "FirstFragment"); 
    } 
    else if (id == R.id.nav_second_layout) { 
     showFragment(new SecondFragment(), "SecondFragment"); 
    } 
    else if (id == R.id.nav_third_layout) { 
     showFragment(new ThirdFragment(), "ThirdFragment"); 
    } 
    else if (id == R.id.nav_share) { 

    } 
    else if (id == R.id.nav_send) { 

    } 

An:

switch (item.getItemId()) { 
    case R.id.nav_first_layout: 
     showFragment(new FirstFragment(), "FirstFragment"); 
     break; 
    case ... 
} 

und so weiter. Der Code wäre hübscher :)

+0

Danke! Der Fragmentteil Ihrer Antwort war die perfekte Lösung - und sogar mein Code wurde hübscher! :) Das Setzen von "getFragmentManager(). GetBackStackEntryCount()> 0" auf "getFragmentManager(). GetBackStackEntryCount()> 1" hat mir auch Kopfzerbrechen bereitet, da jetzt das erste Fragment dort bleibt und nicht nur der Empy-Container sichtbar ist . Für den Aktivitätsteil, was mir geholfen hat, ist der "android: noHistory =" true "" Code in der Manifest-Datei, der funktionierte, der andere nicht wirklich. Danke für Ihre Hilfe! – lpasztor

+0

Ich habe ein anderes Problem konfrontiert: Wenn ich die Home-Taste drücke oder zu einer anderen App wechsle und danach die App wiederherstelle, sind die Zustände der Fragmente verloren. Könnten Sie bitte Ihre Antwort mit diesem Teil bearbeiten? Vielen Dank! – lpasztor

+0

Oder ist die einzige Möglichkeit, die Zustände aller Elemente jedes Fragments zu speichern und wiederherzustellen? – lpasztor

Verwandte Themen