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

安卓常见异常处理

作者: 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