thread导致的内存泄漏实例——为什么使用静态内部类避免内存泄漏

背景:有个数据库处理类,包含一个thread负责对数据库进行写入(耗时操作)。该thread在某个fragment中会被重新初始化并开始。

 

        private void updateBookShelf() {
            Globals.getInstance().setBookShelves(bookShelves);
            if (Globals.getInstance().thread != null && Globals.getInstance().thread.isAlive()) {
                Globals.getInstance().thread.interrupt();
            }
            Globals.getInstance().thread = new Thread(() -> {
                List<BookShelf> bookShelfList = Globals.getInstance().getBookShelves();
                clearAllBookShelf();
                for (int i = 0; i < bookShelfList.size(); i++) {
                    BookShelf bookShelf = bookShelfList.get(i);
                    if (bookShelf.getType().compareTo(BookShelf.TYPE_FOLDER) == 0) {
                        for (int j = 0; j < ((BookShelf_FolderBean) bookShelf).getChildCount();
                            j++) {
                            BookShelf
                                .createWithOutCheck(((BookShelf_FolderBean) bookShelf).getChild(j));
                        }
                    }
                    BookShelf.createWithOutCheck(bookShelf);
                }
            });
            Globals.getInstance().thread.start();
        }


        private void clearAllBookShelf() {
            BookShelf.deleteForAll();
        }

本身这里没有把thread写成静态内部类,只是new了一个Thread,然后重写了run方法,但是根据LeakCanary的报告这里出现了内存泄漏

 

分析:

这是个长期存在的thread,发生内存泄漏的话应该thread持有了该fragment的对象。可是重新阅读代码发现并没有显示的持有该fragment的某个对象。经过漫长的排查....发现其中的某行代码clearAllBookShelf();是问题所在,thread中使用了类的成员方法,成员方法是需要fragment对象调用的,因此持有了fragment实例。尽管clearAllBookShelf();方法中并没有持有实例。

 

解决办法:

可以见到clearAllBookShelf();方法中BookShelf.deleteForAll();是一个其他类中的静态方法。将thread中对clearAllBookShelf();的调用直接替换成BookShelf.deleteForAll();。

 

见到这里突然对静态内部类避免内存泄漏有了深一点的理解,拿这个例子来说,虽然不使用静态内部类可以解决内存泄漏。但是我们使用静态内部类的话就可以直接避免这个问题了,静态内部类中不会允许我们调用外部类的成员方法,就也不会如此“秘密”地持有fragment的实例了,恰巧这个例子中还是一个thread生命周期比fragment更久的情况,导致fragment无法被回收,引发了内存泄漏了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值