如何防止android

时间:2017-09-25 15:58:02

标签: android memory-management memory-leaks

在通过Android Studio Memory monitor调查我的应用内存使用情况时,我意识到可能存在一些内存泄漏,主要是由于(在我看来,如果错误请纠正我)逐渐增加Memory allocated大小,从大约30MB增加到50MB,70MB,达到近90MB。

内存分配的增加是由于浏览标签(fragments)和Activities,返回初始活动等等造成的。

查找Memory leaks的最简单(或简单易行)方法可能是(this link describes the process)在.hprof之后检查并分析内存dumping a java memory heap文件在Android Studio中。使用这种方法,我正确地确定了一个内存泄漏,因为我声明了一个static context变量(并不以此为荣)。

不幸的是,在检查右侧标签LeakedActivites时,我发现CatalogActivity仍然存在,因此mContext仍然存在上下文内存泄漏。

enter image description here

这次我无法识别内存泄漏,因为我还没有声明任何mContext变量。 (显然,因为它的深度为6,它指的是该活动的全局背景)

如何识别仍然发生的内存泄漏?我在第一段描述的行为是否正常?(随着时间的推移逐渐增加内存分配)

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

注意:当我使用LG G6(4GB RAM)调试应用程序时,内存分配会逐渐增加。使用模拟设备Nexus 5时,行为仍然会发生,但会逐渐减少(内存分配从2MB开始,达到5MB左右的峰值)。

1 个答案:

答案 0 :(得分:1)

我遇到了类似的问题,每次创建新片段时分配的内存都没有在destroy上被丢弃。

问题出现在drawables ArrayList<Drawable>列表中,设置为onDestroyView中数组的所有元素,问题解决了。

我认为你应该尝试在GridView中使用对位图的引用设置为null变量。

希望它会有所帮助...