Android内存溢出与优化(三)——使用完后要close、recycle、unregister、null

来源:互联网 发布:mysql 主键作用 编辑:程序博客网 时间:2024/06/13 21:35

总篇地址:Android内存溢出与优化(零)——开题篇 


       相信大家看到close、recycle、unregister、null,大概已经猜到要说什么了,没错,这一篇都是大家熟知的部分。不过,既然是说内存溢出与优化,这些东西确实又是不可忽略的,懂得的朋友可以跳过,新手朋友请多注意!这些多是系统给出的对象占用,需要主动释放,如果不释放,这些对象将一直占用内存,造成内存泄露!下面的例子,就直接上代码了,相信大家都懂。


*****个人经验狭隘,难免有所疏漏,若有问题,恳请斧正!*****


1.数据库的操作,使用完后要close()

下面是一个数据库查询的代码例子:

    /**     * 查询号码是否存在     *     * @param number 手机号码     * @return     */    public boolean find(String number) {        SQLiteDatabase database = mHelper.getWritableDatabase();        Cursor cursor = database.query("blackNumber", new String[]{"number", "mode"},                "number=?", new String[]{number}, null, null, null);        boolean exist = false;        if (cursor.moveToFirst()) {            exist = true;        }        cursor.close();//cursor用完后要关闭,释放资源        database.close();//database用完后要关闭,释放资源        return exist;    }


2.I/O流及其相关的操作,使用完后要close()  

下面是一个缓存文件读取的代码例子:

    /**     * 读取缓存     */    private String getCache(int index) {        File cacheDir = UIUtils.getContext().getCacheDir();//本应用的缓存文件夹        File cacheFile = new File(cacheDir, getKey() + "?index=" + index + getParams());//生成缓存文件        if (cacheFile.exists()) {   //判断缓存是否存在            //判断缓存是否超过有效期            BufferedReader reader = null;            try {                reader = new BufferedReader(new FileReader(cacheFile));                long deadline = Long.parseLong(reader.readLine());//读取第一行                if (System.currentTimeMillis() < deadline) {    //缓存有效                    StringBuffer sb = new StringBuffer();                    String line;                    while ((line = reader.readLine()) != null) {    //line不包含有效期,因为前面已经读取过第一行了                        sb.append(line);                    }                    return sb.toString();                }            } catch (Exception e) {                e.printStackTrace();            } finally {                IOUtils.close(reader);//关闭reader            }        }        return null;    }
上面的关闭操作,使用了一个工具IOUtils,主要是简化try catch代码,方便阅读,该工具类如下:

/** * IO流关闭工具类 */public class IOUtils {/** * 关闭流         */public static boolean close(Closeable io) {if (io != null) {try {io.close();} catch (IOException e) {LogUtils.e(e);}}return true;}}


3.TypeArray使用完后要recycle()  

 制作自定义控件时,我们会用到TypeArray,用完请记得recycle(),例子如下:

TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.RoundProgressWithProgress);int Radius = (int) ta.getDimension(R.styleable.RoundProgressWithProgress_radius, mRadius);//获取自定义属性ta.recycle();//用完后,释放资源

4.Bitmap在确定不再被使用后,最好recycle()  

Bitmap在开发中是经常用到的,图片占用资源相当大,大量的占用就容易造成内存问题。每当我们确定一

张图片再被使用后,可以主动将其释放recycle(),而不是等待垃圾回收机来释放。具体操作如下:

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);//中间做一些相关操作bitmap.recycle();//确定Bitmap不再使用了,recycle()

5.Receiver的注销与null

在开发中,我们可能会启动一个服务去监听广播,例如监听锁屏广播,这时可以这样做,代码如下:

/** * 锁屏监听 * * @author ALion */public class MyService extends Service{    private InnerScreenOffReceiver mReceiver;    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public void onCreate() {        super.onCreate();        //注册广播,监听屏幕关闭        mReceiver = new InnerScreenOffReceiver();        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);        registerReceiver(mReceiver, filter);    }    @Override    public void onDestroy() {        super.onDestroy();        //注销广播        unregisterReceiver(mReceiver);        mReceiver = null;    }    class InnerScreenOffReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context context, Intent intent) {            //监听到锁屏后,要做的操作        }    }}

在代码中,可以看到在Service的onDestroy()方法中需要unregisterReceiver(mReceiver),并且

mReceiver = null。


在这里讲的东西,都是常见的需要注意的细节,总体的原理都是一个“需要主动释放资源”,所以都是举出代码,
未做详细的说明。在开发中,只要记得做后续的释放操作既可,不然会长期占用内存,并且不会被垃圾回收器回收,

导致内存泄露,最终大量累积导致内存溢出。


1 0