美文网首页
关于android的内存泄露

关于android的内存泄露

作者: 如果丶世界漆黑 | 来源:发表于2017-04-03 18:04 被阅读0次

    内存泄漏:进程中某些对象已经没有使用价值了,但是它们却可以直接或间接地引用到,导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,从而导致内存泄漏了。
    内存溢出(OOM):程序在申请内存时,没有足够的内存空间供其使用;内存泄漏是导致内存溢出的主要原因之一;
    内存泄露的原因主要就是该关闭的资源对象没有即使释放;

    1.单例造成的内存泄露
    单例的特点是其生命周期与application保持一致
    大概大多数的单例都是像这么写的吧
    <code>
    public class MyTest {
    public static MyTest mTest;
    private Context mContext;
    private MyTest (Context context) {
    mContext = context;
    }
    public static synchronized Test getInstance(Context context) {
    if (mTest == null) {
    mTest = new MyTest(context);
    }
    return mTest;
    }
    }
    </code>
    ①如果传入的是 Activity 的 Context,当这个 Context 所对应的 Activity 退出时,由于该 Context 的引用被单例对象所持有,其生命周期等于整个应用程序的生命周期,所以当前 Activity 退出时它的内存并不会被回收,从而导致了内存泄露;
    ②当我们传入的是Application的Context的时候,单例的生命周期就和Application的一样长,因为Application的生命周期是贯穿整个程序的,所以MyTest类持有它的引用,也不会造成内存泄露问题。
    所以当我们能用Application Context代替的,尽量用Application Context。
    2.Bitmap使用不当
    Bitmap是一个极容易消耗内存的对象,用完之后要及时回收;
    当我们展示图片区域很小的时候,需要对图片进行压缩及降低像素或者加载缩略图等;
    运用Glide加载图片的时候,ImageView的scaleType设置不当会导致OOM,当设置为我们fitXY时,Glide不会进行缩放,会以全分辨率加载,所以尽量不要设置为fitXY。
    3.Handler造成的内存泄漏
    非static的handler会持有activity的引用,而如果handler没有处理完成工作的时候,我们调用finish,则activity不能释放,这个时候就会出现内存泄漏。
    平常我用handler是这样使用的:
    <code>
    public class MainActivity extends AppCompatActivity {
    ...
    private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
    }
    };
    }
    </code>
    但是这样会造成内存泄漏,在Java中在内部创建对象之后会隐式的持有外部对象,也就是说new Handler()之后Handler对象对Activity就有了一个持有,那么此时finish掉Activity的话是没办法回收的。这就造成了内存泄漏。
    正确使用handler的姿势应该是这样的:
    <code>
    static class MyHandler extends Handler {
    private final WeakReference<Test> mActivity;
    TestHandler(Test activity) {
    mActivity = new WeakReference<>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
    final Test activity = mActivity.get();
    if (activity == null || activity.isFinishing()) {
    removeCallbacksAndMessages(null);
    return;
    }
    }
    }
    </code>
    4.匿名内部类造成的内存泄露
    <code>
    public class TestActivity extends Activity {
    ...
    MyRunnable re1 = new MyRunable();
    Runnable re2 = new Runnable() {
    @Override
    public void run() {
    ...
    }
    };
    }
    </code>
    其中re2是匿名内部类,ref2的实现对象里面有个引用,这个引用指向TestActivity ,当前的TestActivity 实例会被re2持有,如果将这个引用再传入一个异步线程,此线程和此Acitivity生命周期不一致的时候,就造成了Activity的泄露。
    5.资源性对象未关闭
    File,Cursor,Stream,File,Cursor,Stream,BraodcastReceiver,ContentObserver,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
    6.Webview造成的内存泄露
    在重复打开有WebView的页面时,你会发现,应用的内存会不断升高,销毁了之后也不会降下来,这样就出现了内存泄漏了;
    使用Webview之后要activity的onDestroy方法中调用webView.removeAllViews()和webView.destroy();new WebView的时候需要传入ApplicationContext,如果传入Activity的Context的话,对内存的引用会一直被保持着;
    7.静态变量造成的内存泄露
    在 Activity 类中定义一个 static 变量,并将其指向一个运行中的 Activity 实例。如果在 Activity 的生命周期结束之前,没有清除这个引用,那它就会泄漏。由于 Activity 的类对象是静态的,一旦加载,就会在 APP 运行时一直常驻内存,如果类对象不卸载,其静态成员就不会被垃圾回收,应该尽量避免static成员变量引用资源耗费过多的实例;
    Android的内存优化的建议:
    1 对不用的对象显示置NULL;
    2.使用更加轻量的数据结构;
    3内存对象的重复利用,一些数据进行缓存;
    4 注册监听及时注销;
    5 优化布局,减少嵌套层次;
    6 Listview的优化ContentView获取缓存的view,使用ViewHolder模。建议用recyclerview代替listview;
    7 复用系统自带的资源,如颜色,图片,简单的布局,样式,接口,动画等;

    • ━━━━━━神兽出没━━━━━━
    • ┏┓   ┏┓
    • ┏┛┻━━━┛┻┓
    • ┃       ┃
    • ┃   ━   ┃
    • ┃ ┳┛ ┗┳ ┃
    • ┃       ┃
    • ┃   ┻   ┃
    • ┃       ┃
    • ┗━┓   ┏━┛
    • ┃   ┃
    • ┃   ┃
    • ┃   ┗━━━┓
    • ┃       ┣┓
    • ┃       ┏┛
    • ┗┓┓┏━┳┓┏┛
    • ┃┫┫ ┃┫┫
    • ┗┻┛ ┗┻┛
      *━━━━━━━━━━━━━━━━

    相关文章

      网友评论

          本文标题:关于android的内存泄露

          本文链接:https://www.haomeiwen.com/subject/ofcnottx.html