Android面试大全(异常处理篇)

Android面试大全(四大组件篇)
Android面试大全(性能优化篇)
Android面试大全(异常处理篇)
Android面试大全(开源框架篇)
Android面试大全(网络篇)
Android面试大全(java篇)


开发中常见Exception

  • 空指针问题
    这种问题通过查看Log日志带有NullpointerException,定位到出错位置解决就好了,比如:控件或集合未初始化或者服务端数据格式问题取值前未做判断
  • IndexOutOfBoundsException 异常
    数组越界,解决办法:取值前先判断index与数组或集合的大小,避免循环删除集合数据(remove)等;
  • ResourceNotFoundException
    原因一:要查找的资源本地资源找不到(本地确实不存在|编译出错|未入导包)
    原因二:setText(4);当给TextView设置文字时直接设置整形数(textview设置整形数时会根据int索引去查找本地资源文件)
  • 权限问题
    这类问题通常log日志中会带有Permission关键字,同时系统会提示缺少具体哪种权限,解决就是在AndroidManifest.xml清单文件中声明一下
  • 说明
    Android四大组件都需要进行注册才能正常使用,其中Activity、Service、Content Provider内容提供者都需要在AndroidManifest清单文件中注册申明,BroadCastReceiver广播有两种动态注册方式:静态注册(即在AndroidManifest.xml文件中注册)或动态注册(通过java代码注册)
private final String action ="com.activity.send";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //注册广播,
        // 面试过程中有面试到动态注册广播时,需要几个参数,分别是什么
        IntentFilter filter = new IntentFilter();
        filter.addAction(action);
        /**
         * 两个参数 BroadCastreceiver实例,IntentFilter,通常使用的也是这种
         */
        registerReceiver(receiver,filter);
        /**
         * 四个参数:广播接收器实例,IntentFilter,广播权限,Handler
         */
//        registerReceiver(receiver,filter,"android.permission",Handler);
        Button button = new Button(this);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //发送广播
                sendBroadcast(new Intent(action));
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //销毁前需要取消广播注册
        unregisterReceiver(receiver);
    }
    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(action)){
                //TODO 接收到广播,做出相应处理
                //在此方法中不能创建线程,也不能做太过耗时的操作
                //广播接收器超过10s的操作会ANR(Application Not Response)

            }
        }
    };
  • 找不到activity类
    log日志类型ActivityNotFoundException,这种原因是自己创建一个类继承自activity,未在AndroidManifest.xml清单文件中注册,声明如下
    <activity android:name=".CustomActivity" ></activity>

  • 数组越界
    在操作集合时,索引(position超出范围)出错

网络请求 出错

  • java.lang.IllegalArgumentException: rawResponse must be successful response
  • 可检查下网络请求方式是否正确,如:post请求使用了get方式
  • url地址出错
  • 参数出错

ANR

Application Not Response,在手机上我们不时会看到程序无响应等字样,这就是在一定时间内为做完某项操作导致程序发生ANR异常

  • 程序主线程(UI线程)是不能做耗时操作的
  • Activity最长响应时间为5s
  • BroadCastReceiver最长响应时间为10s
  • Service最长响应时间为20s
    超时即会发生ANR异常,太过耗时的操作可以创建子线程去完成,我们也知道Service是运行在后台的服务,用户看不见,也能做一些耗时操作,长时间的耗时操作可考虑使用IntentService(extends Service),是Service的子类;
    ServiceBroadcastReceiver都运行在主线程中

OOM

OutOfMemory,Android的虚拟机是基于寄存器的Dalvik,最大堆大小一般是16M,有的机器为24M。OutOfMemory的错误,通常 是堆内存溢出。对一般手机应用,手机资源是相当有限的,堆内存的上限值只有16M(有的24M)Android的缺 省值是16M(某些机型是24M),而对于普通应用这是不能改的,当应用程序处理大资源的资源,如图片或视频等媒体资源时,数量一多,时间一长,16M的资源很容易耗尽,所以OOM很容易出现。

虽然Java有垃圾回收机制,但也存在内存泄露。如果我们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成了内存泄露。如果我们的java运行很久,而这种内存泄露不断的发生,最后就没内存可用了。当然java的,内存泄漏和C/C++是不一样的。如果java程序完全结束后,它所有的对象就都不可达了,系统就可以对他们进行垃圾回收,它的内存泄露仅仅限于它本身,而不会影响整个系统的。

C/C++的内存泄露就比较糟糕了,它的内存泄露是系统级,即使C/C++程序退出,它的泄露的内存也无法被系统回收,永远不可用 了,除非重启机器。

Android的一个应用程序的内存泄露对别的应用程序影响不大。为了能够使得Android应用程序安全且快速的运行,Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出的,也就是说每个应用程序都是在属于自己的进程中运行的。 Android为不同类型的进程分配了不同的内存使用上限,如果程序在运行过程中出现了内存泄漏的而造成应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill掉,这使得仅仅自己的进程被kill掉,而不会影响其他进程(如果是system_process等系统进程出问题的话,则会引起系统重启),这是,我们的应用程序就会崩溃,我们就会看到OOM。

引发OOM的原因

  • 资源文件未及时关闭:File(未关闭InputStream/OutputStream)、数据库Cursor未关闭
  • 构造adapter未缓存convertView
  • 未反注册引起(比如广播)
  • Bitmap未使用时未及时recycle()释放
  • Context引起的泄漏
  • static关键字的不当使用

解决办法

  • static关键字的使用
    static是Java中的一个关键字,当用它来修饰成员变量时,那么该变量就属于该类,而不是该类的实例。用static这个关键字修饰变量,使得该变量的生命周期大大延长,并且访问也极其方便,用类名就能直接访问,各个资源间 传值也极其方便,所以它经常被我们使用。但如果用它来引用一些资源耗费过多的实例(Context的情况最多),这时就要谨慎对待了。
    • ①:应该尽量避免static成员变量引用资源耗费过多的实例,比如Context。
    • ②:Context尽量使用Application Context,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。
    • ③:使用WeakReference代替强引用。比如可以使用WeakReference<Context> mContextRef;
  • Bitmap引起的内存泄漏
    • 及时销毁(调用recycle并不确定该bitmap会立即被回收,但给虚拟机说了“改图片是可以销毁的了”,如有需要可手动通过代码置空NULL)
    • 设置采样率
      我在性能优化篇有说到过采样率,将图片进行缩放
private ImageView preview;  
    BitmapFactory.Options options = new BitmapFactory.Options();  
    options.inSampleSize = 2;//宽高都为原来的1/2,即图片为原来的1/4
    Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri), null, options);  
    preview.setImageBitmap(bitmap);  
  • 使用软引用保存图片的引用(SoftRefrence)
  • cursor未关闭
    Cursor是Android查询数据后得到的一个管理数据集合的类,正常情况下,如果查询得到的数据量较小时不会有内存问题,而且虚拟机能够保证Cusor最终会被释放掉。
    然而如果Cursor的数据量特别大时,应该保证Cursor占用的内存被及时的释放掉,而不是等待GC来处理。并且 Android明显是倾向于编程者手动的将Cursor close掉,因为在源代码中我们发现,如果等到垃圾回收器来回收时,会给用户以错误提示。
    所以我们使用Cursor的方式一般如下:
Cursor cursor = null;  
  try {  
    cursor = ctx.getContentResolver().query(uri,null, null,null,null);  
    if(cursor != null) {  
        cursor.moveToFirst();  
        //do something  
    }  
  } catch (Exception e) {  
    e.printStackTrace();    
  } finally {  
    if (cursor != null) {  
       cursor.close();  
    }  
}   

有一种情况下,我们不能直接将Cursor关闭掉,这就是在CursorAdapter中应用的情况,但是注意,CursorAdapter在Acivity结束时并没有自动的将Cursor关闭掉,因此,你需要在onDestroy函数中,手动关闭cursor。

  • inputstream/outputstream
    这个我们在操作完毕时关闭就好了
  • 未反注册
    以广播为例 registerReceiver(receiver,filter);unregisterReceiver(receiver);是成对出现的;未调用反注册时程序不会crash掉,在log日志中也会出现错误信息的
  • 未缓存converview(少量数据时影响不大)

状态异常

IllegalStateException
  • 发生情形:
    ①:fragment中使用recycleview
    adapter中加载layout布局时错误使用方法(亲测)
    LayoutInflater.from(mContext).inflate(R.layout.item_summary, parent);
  • 使用以下方法得以解决
    LayoutInflater.from(mContext).inflate(R.layout.item_summary, parent, false);

正在持续更新中……

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,799评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,699评论 2 59
  • Android 内存管理的目的 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题。简单粗...
    晨光光阅读 1,290评论 1 4
  • 阳光明媚的一天,阳光透过厚重的树林,稀疏地照落到树下的草地上,两只小鼹鼠在草地上玩耍,时而我挠挠你,时而你逗逗我。...
    小贤爱写作阅读 542评论 2 1
  • 我是小草,你可以把我安进尘土;你也是小草,别人也可以把你扔进泥土烂掉;我们都是小草,我们都害怕农夫。他们的锄头是原...
    粲月阅读 176评论 0 0