Я использую Android Studio, и я разработал очень простое приложение.Приложение имеет 3 фрагмента и один BottomNavigationView
для навигации между фрагментами.Вот код, который я использую для навигации между фрагментами:
private Fragment chartFragment;
private Fragment tutorialFragment;
private Fragment optionFragment;
private FragmentManager fm;
private boolean isDisplaying;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("LifeCicle","MainActivity - Created");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
fm = getSupportFragmentManager();
if(savedInstanceState != null){
chartFragment = fm.getFragment(savedInstanceState,CHART_FRAGMENT__KEY);
tutorialFragment = fm.getFragment(savedInstanceState,TUTORIAL_FRAGMENT__KEY);
optionFragment = fm.getFragment(savedInstanceState,OPTION_FRAGMENT__KEY);
isDisplaying = savedInstanceState.getBoolean(IS_DISPLAYING_KEY);
}else{
tryCreateFragmentsInstances();
isDisplaying = false;
}
if(!isDisplaying){
showFragment(chartFragment);
}
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
if(tutorialFragment.isHidden()){
showFragment(tutorialFragment);
}
return true;
case R.id.navigation_dashboard:
if(chartFragment.isHidden()){
recreateChartFragment();
}
return true;
case R.id.navigation_notifications:
if(optionFragment.isHidden()){
showFragment(optionFragment);
}
return true;
}
return false;
}
};
@Override
protected void onSaveInstanceState(Bundle outState) {
Log.i("LifeCicle","MainActivity - Saving States");
super.onSaveInstanceState(outState);
if(chartFragment.isAdded()){
fm.putFragment(outState,CHART_FRAGMENT__KEY,chartFragment);
Log.i("LifeCicle","MainActivity - Chart fragment saved");
}if(tutorialFragment.isAdded()){
fm.putFragment(outState,TUTORIAL_FRAGMENT__KEY,tutorialFragment);
Log.i("LifeCicle","MainActivity - Turotial fragment saved");
}if(optionFragment.isAdded()){
fm.putFragment(outState,OPTION_FRAGMENT__KEY,optionFragment);
Log.i("LifeCicle","MainActivity - Option fragment saved");
}
outState.putBoolean(IS_DISPLAYING_KEY,isDisplaying);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.i("LifeCicle","MainActivity - Restoring States");
}
private void tryCreateFragmentsInstances(){
if(chartFragment == null){
chartFragment = ChartFragment.newInstance(gameLetterTime,gameLetterNum);
fm.beginTransaction().add(R.id.displayPanel,chartFragment).commit();
}if(tutorialFragment==null){
tutorialFragment = TutorialFragment.newInstance();
fm.beginTransaction().add(R.id.displayPanel,tutorialFragment).commit();
}if(optionFragment==null){
optionFragment = OptionFragment.newInstance();
fm.beginTransaction().add(R.id.displayPanel,optionFragment).commit();
}
hideAllFragments();
}
/**showFragment - Hide all fragments that are being displayed and show that one requested*/
private void showFragment(Fragment fragment){
hideAllFragments();
Log.i("LifeCicle","Displaying Fragment: "+fragment);
fm.beginTransaction()
.setCustomAnimations(android.R.anim.fade_in,android.R.anim.fade_out).
show(fragment).commit();
isDisplaying=true;
fm.popBackStack();
}
/**hideAllFragments - hide all fragments that exists in the project
* @see OptionFragment,ChartFragment,TutorialFragment*/
private void hideAllFragments(){
Log.i("LifeCicle","Hiding all fragments");
if(!chartFragment.isHidden()){
fm.beginTransaction().hide(chartFragment).commit();
}if(!optionFragment.isHidden()){
fm.beginTransaction().hide(optionFragment).commit();
}if(!tutorialFragment.isHidden()){
fm.beginTransaction().hide(tutorialFragment).commit();
}
}
private void recreateChartFragment(){
fm.beginTransaction().remove(chartFragment).commit();
chartFragment = ChartFragment.newInstance(gameLetterTime,gameLetterNum);
fm.beginTransaction().add(R.id.displayPanel,chartFragment).commit();
showFragment(chartFragment);
}
Фрагмент ChartFragment
, по особым причинам в моем приложении, мне нужно создавать его заново каждый раз, когда я хочу его отобразить.
После того, как я закончил приложение, я пошел в Profiler из студии Android, запустив приложение с моим реальным устройством.
Приложение запускается с использованием памяти 30 МБ, а 15 МБ описываются как графическая память,
Моя проблема в том, что каждый раз, когда я перемещаюсь между фрагментами, использование памяти увеличивается все больше и больше.Я ожидал, что использование памяти будет расти, но до некоторого момента.
Навигация вперед и назад между 3 фрагментами. Я мог бы увеличить объем используемой памяти до 80 МБ, а 44 МБ описать как графическую память.Ниже есть фотография моего профилировщика (все, что я делал во время этого теста, это переключался между фрагментами, нажимая на кнопки BottomNavigationView
):
Последнее событие сборщика мусора, которое явынужден проверить, уменьшит ли это использование памяти графической памятью, но это не сработало.
Это нормально для такого небольшого приложения?(внутри фрагментов просто тексты без изображений вообще!) Я пропускаю некоторую утечку памяти или делаю навигацию между фрагментами действительно плохим способом?
Я пытался уменьшить использование памяти в течение нескольких дней, но ничего не получалось.