En étudiant l'utilisation de la mémoire de mon application via Android Memory monitor
de Studio Studio, je me suis rendu compte qu'il pouvait y avoir des fuites de mémoire principalement dues à l'augmentation progressive de la mémoire. Memory allocated
taille qui est passée d'environ 30 Mo à 50 Mo, 70 Mo et atteignant près de 90 Mo.Comment éviter les fuites de mémoire liées au contexte dans android
Ces augmentations de l'allocation de mémoire sont causées par le passage des onglets (fragments
) et Activities
, en revenant aux activités initiales, etc.
La méthode la plus straight-forward (ou facile, je pourrais dire) de localiser Memory leaks
pourrait être (comme this link describes the process) la vérification et l'analyse d'un fichier de mémoire .hprof
après dumping a java memory heap
dans Android Studio. Avec cette méthode, j'ai correctement identifié une fuite de mémoire comme je déclarais une variable static context
(pas fier de lui).
Malheureusement, tout en vérifiant le bon onglet LeakedActivites
je remarquai que CatalogActivity
est toujours présent là, donc il y a encore une fuite de mémoire de contexte se produit en ce qui concerne mContext
.
Cette fois, je suis incapable d'identifier la fuite de mémoire, comme je l'ai pas déclaré une variable mContext
. (évidemment comme il a une profondeur de 6, il se réfère à un contexte global pour cette activité)
Comment puis-je identifier la fuite de mémoire qui se produit encore? Le comportement que j'ai décrit dans le premier paragraphe est-il normal? (augmentation progressive de l'allocation de mémoire à travers le temps)
de CatalogActivity:
public class CatalogActivity extends AppCompatActivity {
private ViewPager mViewPager;
private SectionsPageAdapter mSectionsPageAdapter;
private FirebaseAuth mFirebaseAuth;
private Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.slidein, R.anim.slideout);
setContentView(R.layout.activity_catalog);
context = this;
mFirebaseAuth = FirebaseAuth.getInstance();
mSectionsPageAdapter = new SectionsPageAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
setupViewPager(mViewPager);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
int tabIcon1 = R.drawable.ic_collections_24dp;
int tabIcon2 = R.drawable.ic_book_black_24dp;
int tabIcon3 = R.drawable.ic_chat__24dp;
if (tabLayout.getTabAt(0) != null) {
tabLayout.getTabAt(0).setIcon(tabIcon1);
}
if (tabLayout.getTabAt(1) != null) {
tabLayout.getTabAt(1).setIcon(tabIcon2);
tabLayout.getTabAt(1).getIcon().setAlpha(128);
}
if (tabLayout.getTabAt(2) != null) {
tabLayout.getTabAt(2).setIcon(tabIcon3);
tabLayout.getTabAt(2).getIcon().setAlpha(128);
}
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int tabIconColor = ContextCompat.getColor(context, R.color.colorAccent);
if (tab.getIcon() != null) {
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
tab.getIcon().setAlpha(255);
}
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
int tabIconColor = ContextCompat.getColor(context, R.color.grey);
if (tab.getIcon() != null) {
tab.getIcon().setColorFilter(tabIconColor, PorterDuff.Mode.SRC_IN);
tab.getIcon().setAlpha(128);
}
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
ViewServer.get(this).addWindow(this);
}
private void setupViewPager(ViewPager viewPager) {
SectionsPageAdapter adapter = new SectionsPageAdapter(getSupportFragmentManager());
adapter.addFragment(new CatalogFragment());
adapter.addFragment(new MyBooksfragment());
adapter.addFragment(new MyChatsFragment());
viewPager.setAdapter(adapter);
}
public void switchContent(Fragment fragment) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragment).commit();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.chat_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.sign_out_menu) {
LoginManager.getInstance().logOut();
mFirebaseAuth.signOut();
loadLogInView();
}
return super.onOptionsItemSelected(item);
}
private void loadLogInView() {
Intent intent = new Intent(this, LogInActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
Note: L'augmentation progressive de l'allocation de mémoire se produit lorsque je déboguer l'application avec LG G6 (4 Go de RAM). Lors de l'utilisation d'un périphérique émulé Nexus 5, le comportement persiste mais est considérablement réduit (l'allocation de mémoire commence à 2 Mo et atteint un pic autour de 5 Mo).
Je suis sûr qu'il y a beaucoup de bitmaps. c'est peut-être drôle - mais les bitmaps font une grande fuite de mémoire. – Peter
s'il vous plaît ne nous obligent pas à aller à d'autres endroits pour regarder votre code –
@Peter Mon application a environ 4 'GridViews' chaque entièrement rempli de bitmaps. Par conséquent, vous avez deviné correctement. Mais comment puis-je arrêter les fuites de mémoire provoquées par beaucoup de bitmaps dans 'GridView'? J'ai cherché beaucoup de messages et je n'ai pas trouvé une bonne solution. –