Android webView加载数据时内存溢出问题及解决
作者:代号卧底
Android webView加载数据时内存溢出
今天使用webView加载数据时 如果数据太长就会崩溃,造成内存溢出,在网上查找了一下资料之后 终于把它解决了,谨在此记录
1.不要在XML里面写webView 可以使用一个占位布局
<FrameLayout android:id="@+id/layoutWebView" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone"/>
2.在代码中动态创建一个webView 把这个webView放到FrageLayout这个布局中
webView = new WebViewMod(getApplicationContext()); WebSettings settings = webView.getSettings(); settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); layoutWebView.addView(webView);
3.到这里基本就OK了,你可以直接在这个WebView里面加载数据了
WebViewMod 这个是我自定义的一个webView 用系统的WebView效果是一样的
4.在当前Activity销毁的时候 记得在onDestroy方法中销毁这个WebView
@Override protected void onDestroy() { webView.removeAllViews(); webView.destroy(); super.onDestroy(); }
大功告成!
Android内存问题 (内存溢出 内存泄漏 内存抖动)
内存溢出:指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory
Android系统为每个应用程序申请到的内存有限,一般为64M或者128M等,我们可以在清单文件中进行配置,android:largeheap = "true" 从而给APP申请更大的内存空间;
内存泄漏: 指程序在申请内存后,被某个对象一直持有,无法释放已申请的内存空间
一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
区别:单例模式在Android开发中会经常用到,但是如果使用不当就会导致内存泄露。因为单例的静态特性使得它的生命周期同应用的生命周期一样长,如果一个对象已经没有用处了,但是单例还持有它的引用,那么在整个应用程序的生命周期它都不能正常被回收,从而导致内存泄露
如何避免呢?全局的上下文Application Context就是应用程序的上下文,和单例的生命周期一样长,这样就避免了内存泄漏。单例模式对应应用程序的生命周期,所以我们在构造单例的时候尽量避免使用Activity的上下文,而是使用Application的上下文
静态变量导致内存泄露?静态变量存储在方法区,它的生命周期从类加载开始,到整个进程结束。
一旦静态变量初始化后,它所持有的引用只有等到进程结束才会释放。
如何解决呢?Info作为Activity的静态成员,并且持有Activity的引用,但是sInfo作为静态变量,生命周期肯定比Activity长。
所以当Activity退出后,sInfo仍然引用了Activity,Activity不能被回收,这就导致了内存泄露。
非静态内部类导致内存泄露?非静态内部类(包括匿名内部类)默认就会持有外部类的引用,当非静态内部类对象的生命周期比外部类对象的生命周期长时,就会导致内存泄露。
常见 (Handler,Thread,AsyncTask)
未取消注册或回调导致内存泄露?比如我们在Activity中注册广播,如果在Activity销毁后不取消注册,那么这个刚播会一直存在系统中,同上面所说的非静态内部类一样持有Activity引用,导致内存泄露。因此注册广播后在Activity销毁后一定要取消注册
集合中的对象未清理造成内存泄露?在循环中把引用o释放了,但是它被添加到了objectList中,所以objectList也持有对象的引用,此时该对象是无法被GC的。因此对象如果添加到集合中,还必须从中删除,最简单的方法防止集合类泄漏内存的方法
解决办法:置空集合对象即可
资源未关闭或释放导致内存泄露?在使用流或者等资源时要及时关闭。这些资源在进行读写操作时通常都使用了缓冲,如果及时不关闭,这些缓冲对象就会一直被占用而得不到释放,以致发生内存泄露。因此我们在不需要使用它们的时候就及时关闭,以便缓冲能及时得到释放,从而避免内存泄露
解决办法Webview下面的持有Activity引用,造成Webview内存无法释放,即使是调用了Webview.destory()}等方法都无法解决问题(Android5.1之后)。
最终的解决方案是:在销毁WebView之前需要先将WebView从父容器中移除,然后在销毁WebView。
内存抖动:是指在短时间内有大量的对象被创建或者被回收的现象,内存抖动出现原因主要是频繁(很重要)在循环里创建对象(导致大量对象在短时间内被创建,由于新对象是要占用内存空间的而且是很频繁
内存抖动结果:如果抖动很频繁,会导致垃圾回收机制频繁运行(短时间内产生大量对象,需要大量内存,而且还是频繁抖动,就可能会需要回收内存以用于产生对象,垃圾回收机制就自然会频繁运行了)。综上就是频繁内存抖动会导致垃圾回收频繁运行。
尽量避免在循环体内创建对象,应该把对象创建移到循环体外。
注意自定义View的onDraw()方法会被频繁调用,所以在这里面不应该频繁的创建对象。
当需要大量使用Bitmap的时候,试着把它们缓存在数组中实现复用。
对于能够复用的对象,同理可以使用对象池将它们缓存起来。
小结:JVM以Class为执行单元,Android虚拟机以Dex执行单元,编译流程JVM直接通过Javac即可加载。
Android 虚拟机需要先编译成dex,然后编译成apk。最后执行
Android Art虚拟机在安装的时候讲dex缓存本地机器码,安装比较慢,耗存储空间
Android Dalvik虚拟机在程序运行过程中进行翻译。节省空间,耗cpu时间。以空间换时间的典型
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。