0

У меня 2 активных деятелей: - LoginActivity: он будет обрабатывать материалы для входа позже - MainActivity: главное приложение, все функции будут предоставлены на фрагментах.Как правильно использовать задний стоп на действиях И фрагменты

Я хочу правильно использовать задний стек, но я не могу.

Что я хочу (но не могу) достичь: Приложение начинается с экрана входа в систему. Я вхожу в систему (прямо сейчас нажмите кнопку «Пуск»), после чего появляется главный экран и загружается первый фрагмент. Теперь, если я нажимаю кнопку «Назад», приложение закрывается, и так оно и должно работать, оно не должно возвращаться на экран входа с простым нажатием кнопки «Назад».

Но теперь, если я выхожу на выход (и появляется экран входа в систему), и я нажимаю кнопку «Назад», приложение возвращает меня на главный экран, что действительно не так. Если я выйду из системы, на экране входа в систему нажмите кнопку «Назад», чтобы закрыть приложение.

И еще одна проблема, касающаяся также отскока и фрагментов: У меня есть 3 фрагмента: первый, второй и третий. Если я открою их друг за другом (в основном, конечно, конечно), и я нажимаю кнопку «Назад», я хочу, чтобы она вернула меня к ранее открытому фрагменту, или если нет предыдущего, закройте приложение. Теперь он делает это, открывает предыдущий фрагмент, но в то же время он закрывает полное приложение. (Я вижу, что они происходят сразу друг за другом)

Что не хватает? Что нужно изменить для достижения этого (нормального) поведения?

Спасибо!

Мой код:

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

ответ

1

О переключении между Activities.

Одна важная вещь.
showActivity() использовать finish(), чтобы убить текущий Activity при переходе на другой. Если это не поможет - см. Ниже.

Попробуйте использовать также FLAG_ACTIVITY_NEW_TASK с вашим текущим флагом, потому что FLAG_ACTIVITY_CLEAR_TOP будет закрыт только Действия в задаче выше текущей деятельности, но не ниже.
Итак, было бы так: intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Другой вариант: FLAG_ACTIVITY_CLEAR_TASK only - new Activity очистит задание и станет его root.

Если оба не помогут - используйте android:launchMode = "singleInstance" в манифесте для каждого Actitivy.


О Fragments - Я вижу маленькую ошибку в коде: он вызывает super.onBackPressed(); перед появлением Fragment из BackStack
Я хотел бы изменить так:

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

!! Также вы должны проверить эту строку: getFragmentManager().getBackStackEntryCount() > 0 с 0 и 1 в состоянии (потому что в текущей реализации в моем проекте FragmentContainer рассматривает как первое, нулевое значение в BackStack). Просто проверьте 0 и 1, чтобы посмотреть, какие работы.

Спасибо.


PS. Еще несколько советов.

Вы можете объявить FragmentManager fragmentManager в своем Activity, чтобы создать его один раз в onCreate(). Было бы лучше, чем получить его каждый раз.

Рассмотрим это изменить:

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

    } 

To:

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

и так далее. Код был бы более симпатичным :)

+0

Спасибо! Часть фрагмента вашего ответа была идеальным решением - и даже мой код стал красивее! :) Настройка «getFragmentManager(). GetBackStackEntryCount()> 0» на «getFragmentManager(). GetBackStackEntryCount()> 1» также спас мне головную боль, потому что теперь остается первый фрагмент, и будет отображаться не только контейнер empy , Для части деятельности, которая помогла мне, это «андроид: noHistory =« true »« код в файле манифеста, который сработал, а другой - нет. Спасибо за помощь! – lpasztor

+0

У меня возникла другая проблема: если я нажму кнопку «домой» или переключись на другое приложение, и после этого восстановите приложение, состояния фрагментов будут потеряны. Не могли бы вы отредактировать свой ответ с помощью этой части? Спасибо! – lpasztor

+0

Или это единственный способ сохранить состояния каждого элемента каждого фрагмента и восстановить их? – lpasztor