Android面试一天一题(4 Day)

作者: goeasyway | 来源:发表于2016-05-19 19:55 被阅读8431次

我一般面试技术分两方面了解面试者,一是测重问面试者细节的地方,看对方是否真如简历上所说对XX“精通”、“熟悉”、“有一定的见解”,有实践经验的积累。别一种是侧重考察对方对问题(可以是未知问题)的理解和解决问题的思路。

面试题: 如何判断Activity是否在运行?

如下这场景我相信很多人都遇到过,这段话也是从某个帖子截取出来的:

从Activity A 启动一个线程去进行网络上传操作,在A中设立一个回调函数,当上传操作完成以后,在A的这个回调函数中会弹出一个对话框,用来显示回调信息。可是当上传的过程还在进行的时候,我按下back键,A的activity 被销毁了,可是那个上传的线程还在进行,当那个线程结束后,本来应该在A中弹出一个对话框,可是由于A已经不存在了,系统就会报错提示,“将对话框显示在不存在的页面上”,然后程序就挂掉了。

我看到过很多人用Handler来充当上面所提到的“回调函数”,即工作线程完成工作后,通过主线程的Handler处理UI更新,如弹出提示Dialog。可能有些人没有弄明白,Activity都被系统销毁了,工作线程怎么还能调它的变量呢?其实所谓的Activity销毁只是不再受系统的AMS控制,但Activity这个对象的实例还是存在于内存中的,具体什么时候真正把这个对象实例也销毁(回收)了,就要看内存回收机制了,哪怕是这个实例没有可达的引用了也不一定会马上回收。

针对这种用Handler更新UI的情况,我们需要在操作UI前判断一下此Activity是否已被销毁。很多人可能都用过isFinishing来判断,用多了就会发现好象不太准,为什么呢,看一下它的源代码:

    /**
     * Check to see whether this activity is in the process of finishing,
     * either because you called {@link #finish} on it or someone else
     * has requested that it finished.  This is often used in
     * {@link #onPause} to determine whether the activity is simply pausing or
     * completely finishing.
     *
     * @return If the activity is finishing, returns true; else returns false.
     *
     * @see #finish
     */
    public boolean isFinishing() {
        return mFinished;
    }

    /**
     * Returns true if the final {@link #onDestroy()} call has been made
     * on the Activity, so this instance is now dead.
     */
    public boolean isDestroyed() {
        return mDestroyed;
    }

而mFinished是在finish()中被赋值的,也就是说只有通过调用finish()结束的Activity,mFinished的值才会被置为true。所以有时候Activity的生命周期没有按我们预想的来走时(如内存紧张时),会出现判断出错的情况。

Android源码可以使用这个网站查询:androidxref

看看Google工程师是怎么判断的(来源于Android源码中的Call应用,AsyncTask中的onPostExecute片段):

    @Override
    protected void onPostExecute(Void result) {
        final Activity activity = progressDialog.getOwnerActivity();

        if (activity == null || activity.isDestroyed() || activity.isFinishing()) {
            return;
        }

        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

多了一个isDestroyed()的判断。

小结

如果对方没听说过isFinishing函数,那可以让他从自己的角度看如何解决这个问题,正好可以看看他的逻辑思维是否清晰合理。工作中往往会遇到,一些求职者由于之前是做其他方面刚转Android开发,对Android的了解还不够,但有很强理解和学习能力,通过引导发现他可以快速的得到合理的解决方案的话,我一般都很乐意要这样的人。

相关文章

  • Android面试一天一题-goeasyway

    以下文章作者:goeasyway Android面试一天一题(1 Day) Android面试一天一题(2 Day...

  • MS(1):Android之架构篇

    一、架构相关 1、MVC,MVP,MVVM MS思考:Android面试一天一题(Day 33:Android开发...

  • 面试题

    最全的BAT大厂面试题整理答案Android面试一天一题(Day 37:一套高级工程师的面试题)Android面试...

  • MS(2):Android之基础知识篇

    二、组件 1、Activity----------1 MS思考:Android面试一天一题(3 Day):Acti...

  • MS(7):非技术问题篇

    一、GM问非技术问题汇总 MS思考:Android面试一天一题(Day 34:常去的Android相关站点) 说下...

  • MS(3):Android之机制原理篇

    五、重点机制原理 1、Handler机制 MS思考:Android面试一天一题(8 Day):Handler相关分...

  • MS(5):android之进阶篇

    七、自定义View MS思考:Android面试一天一题(Day 30:老外的自定义View面试题)MS思考:老外...

  • android Service 一些思考

    看了Android面试一天一题(1 Day),对Service 的一些总结与思考 作者原文章链接: http://...

  • MS(6):Java篇

    MS思考:Android面试一天一题(7 Day):Java相关 1.Switch能否用string做参数? 在J...

  • 读goeasyway文章有感

    今天在地铁上读goeasyway的文章《Android面试一天一题(Day 39:写博客很重要吗?)》,很有感触,...

网友评论

  • 9b4f2400ea72:来源于Android源码中的Call应用,AsyncTask中的onPostExecute片段
    这个Call应用在哪找呀。。。 我之间看os包下的AsyncTask,onPostExecute方法是空的
    那个网站可以讲讲怎么用么:crying_cat_face:
    瓶子里的王国:谢谢大神,以前我都是full search,然后在结果中一个一个找我想要的,竟没想过还可以条件查询,还是自己不够细心,以后做什么事都得认真考虑,多动脑
    goeasyway:关于“androidxref.com”的使用:Full Search和google的搜索框一样,搜到所有包含搜索关键词的内容;Definition 可以收到函数(或方法)的声明和定义部分;File Path: 可以按文件名来搜索相关的文件;
  • b175c9e44bf5:isDestoryed 这个方法,低版本是不支持的,
  • 望北8261:上传东西的时候就不应该让用户继续操作,如果要操作那可以用IntentService,结果用Notification显示。
    比如新浪微博的评论就是用通知显示结果
  • _番茄沙司:Loader是个很不错的选择,他接受Activity和fragment生命周期的管理。不必考虑是否还存活
  • Jafir:表示从32篇开始往前看,觉得,作者确实是一位经验丰富且思路独特的笔者。但是呢,我看了这么多篇,关于文章,我不多说,很不错。但是,我们在写这样的文章的同时,是否应该也抱着对自己写出的文章和看文章的人的负责的态度呢?如果我们写了文章,有人看,有人评,有人有疑问,那么我们是不是应该抱着负责的态度,在开新篇文章之前先来解决这些问题呢?
    Jafir:@goeasyway 谢谢,加油
    goeasyway:@Jafir 谢谢你的关注,我努力吧。如果有什么问题的话,我没注意到可以私信我,谢谢。另,我还有其他工作和事情,或者说本人水平也有限,不好保证每一个读者的问题都照顾到,希望你谅解。
  • 8cd249b8ddf2:给楼主找个茬吧,轻拍~
    首先这个栗子感觉不太贴切,栗子里面这种情况应该是考核“dialog在没有activity的时候能不能弹出,为什么?”
    而“判断activity是否在运行”,我碰到过一个比较实在的栗子,是我做IM的时候遇到的。
    栗子如下:IM类的app需要一直跑一个service在后台,当收到消息推送的时候,就在通知栏弹出通知,然后用户点击通知栏,跳到对应的聊天界面。
    然而在这里,就需要判断那个聊天的activity是否正在运行了,如果在运行,直接cancel那个通知就OK,如果不在运行,就需要启动那个activity。
    当然这个问题也考核了对于启动模式的知识。
    我当时的做法是通过自己维护一个自己的activity栈,启动一个activity就入栈,当需要判断activity存活情况的时候,就需要遍历一下栈,找到activity实例,再使用官方的那个方法,判断一下isDestroy, isFinish这种
    Allen_tong:我想问下 维护的activity栈 一直往里面添加会导致内存泄露不? 你是如何解决的
    uuid1234:思路挺好,学习了:+1:
    goeasyway:@Beary :+1:
  • dean550:我通常的做法是 用全局变量定义好app的几个状态,如 后台 前台 被强杀。。。
  • f43bd2ab367b:我想知道如果加上trycatch程序就不会崩溃,这种处理会不会对手机有影响
  • 天青色等煙雨_而我在等妳:Handler更新UI的情况,我们需要在操作UI前判断一下此Activity是否已被销毁。我也遇到过一次,我当时是在onDestroy()里加个标识,好像不太好使。
  • duanduan2088:来源于Android源码中的Call应用,请问Call应用源码在哪,找不到
    259c1c37b7cc:@android段段 if (activity == null || activity.isDestroyed() || activity.isFinishing()) {
    return;
    }
    duanduan2088:@goeasyway 谢谢!有一点疑惑,本文的题目是如何判断Activity是否在运行,可感觉本文主要是在讲如何防止因Activity被销毁而导致程序崩溃,并没有说判断Activity是否在运行的方法啊.
    goeasyway:@android段段 抱歉,我忘了,Call的工程叫做Dialer,可以用这个地址查看:http://androidxref.com/6.0.1_r10/xref/packages/apps/Dialer/src/com/android/dialer/calllog/ClearCallLogDialog.java
  • HuDP:一进来思路是自己在onDestroy finish方法里面加一个标识... 原来系统有了 :stuck_out_tongue_winking_eye:
  • steven_chan:我一般在ondestroy 会吧所有的异步请求cancle掉 这样回掉就不再执行了
    one_cup:@天青色等煙雨_而我在等妳 你可以自己在方法里面打LOG,或者百度就知道了
    天青色等煙雨_而我在等妳:@one_cup finish, onDestroy, 被回收,这三者的关系究竟是怎样的呢?
    one_cup:@steven_chan 但是会遇到一些情况在Activity退出的情况下,需要在后台继续执行任务啊,还有就是就算在onDestroy中把异步请求都取消掉,但是有可能这个onDestroy这个方法并不会执行啊,所以还真是得都判断一下,finish执行了可能onDestroy还没执行。onDestroy执行了可能finish没执行。不对可以留言交流 :smile:

本文标题:Android面试一天一题(4 Day)

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