美文网首页
安卓常见异常处理

安卓常见异常处理

作者: watayouxiang | 来源:发表于2017-05-13 22:16 被阅读59次

    内存泄漏 的 造成原因 及 解决方案

    1. 对象内存过大

      • 保存占大量内存的对象,如Bitmap, XML文件
    2. 资源没及时释放

      • context, Cursor, IO的引用没有及时释放
    3. static关键字问题

      • static 是java的关键字,当修饰该关键字的成员变量就不再属于对象,而是属于类变量,生命周期延长,如果用static来修饰引用资源过多的实例,如context的时候就容易出现内存泄漏
      • 解决办法
        1. 避免static 成员变量引用耗费资源的实例,如context
        2. context尽量使用ApplicationContext, 因为Application的Context的生命周期较长,引用不会出现内存泄漏问题
        3. 使用WeakReference代替强引用:WeakReference<Context> mContextRef;
    4. 线程导致内存溢出

       public class MyActivity extends Activity {
           @Override
           public void onCreate(Bundle savedInstanceState) {
               super.onCreate(savedInstanceState);
               setContentView(R.layout.main);
      
               new MyThread().start();
           }
      
           private class MyThread extends Thread{
               @Override
               public void run() {
                   super.run();
                   //do somthing while(true)
               }
           }
       }
      

    假设MyThread是一个耗时操作,当切换横竖屏的时候,会重新调用Activity的生命周期方法,销毁旧的Activity。但是由于MyThread中保存了Activity的引用,所以老的Activity并不会被销毁,从而出现了内存泄漏

    AsyncTask问题更加严重,AsyncTask 内部的实现机制是运用了ThreadPoolExcutor,该类产生的Thread 对象的生命周期是不确定的,是应用程序无法控制的,因此如果AsyncTask 作为Activity 的内部类,就更容易出现内存泄露的问题。

    解决办法:

    1. 将线程的内部类,改为静态内部类(因为非静态内部类拥有外部类对象的强引用,而静态类则不拥有)。
    2. 在线程内部采用弱引用保存Context 引用

    内存溢出 的 造成原因 及 解决方案

    1. 图片过大导致OOM

      • Android 中用bitmap 时很容易内存溢出,比如报如下错误:Java.lang.OutOfMemoryError : bitmap size
        exceeds VM budget。
      • 解决办法:
        1. 边界压缩 (等比例缩小图片) 图片: 只保存图片尺寸大小,不加载图片到内存:Options options = new BitmapFactory.Options(); 等比例缩小图片(缩小比例需要计算): opts.inSampleSize = 2;
        2. 软引用: SoftReference<Bitmap> bitmap = new SoftReference<Bitmap>(Bitmap);
        3. 及时回收:bitmap.get().recycle();
    2. 界面切换导致OOM

      • 横竖屏切换N 次后OOM 了
      • 解决办法:
        1. 页面布局的背景图改成到activity的onCreate中设置。在activity的destroy方法中进行释放drawable.setCallback(null);
        2. 在页面切换时尽可能少地重复调用数据库,反复使用某些对象等
        3. 在onPause()、onStop()、onDestroy()方法中适当的释放资源
    3. 数据库的Cursor没有及时关闭

    4. 构造Adapter 时,没有使用缓存的convertView

    Android 中如何捕获没法打印的app崩溃异常

    自定义一个Application,继承Application 实现UncaughtExceptionHandler

    覆写UncaughtExceptionHandler 的onCreate 和uncaughtException 方法

    @Override
    public void onCreate() {
        super.onCreate();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }
    
    @Override
    public void uncaughtException(final Thread thread, final Throwable ex) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                System.out.println(Thread.currentThread());
                Toast.makeText(getApplicationContext(), "thread="+thread.getId()+"ex="+ex.toString(), 1).show();
                Looper.loop();
                // 保存异常信息到手机sd卡中,上传服务器  
            }
        }).start();
            
        SystemClock.sleep(3000);
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    相关文章

      网友评论

          本文标题:安卓常见异常处理

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