android精妙面试题集三

1、绘制Activity和Fragment生命周期流程图,并以对比图形式展示。

Activity生命周期图:

https://img-blog.csdn.net/20130828141902812

Fragment生命周期图:

http://images2015.cnblogs.com/blog/945877/201611/945877-20161123093212096-2032834078.png    

两者对比图:

http://img.my.csdn.net/uploads/201301/22/1358841101_4818.png

2、如何避免OOM异常

OOM(out of Memory)即内存溢出异常,也就是说内存占有量超过了VM所分配的最大,导致应用程序异常终止。

通常OOM都发生在需要用到大量内存的情况下,因为Android的每一个应用都是一个Davlik虚拟机,该虚拟机的默认堆内存只有16M,远远无法跟我们的PC机比较,因此和容易导致OOM(Out Of Memory)异常的产生。导致这样的异常主要有以下原因:①、加载大图片或数量过多的图片,因为图片是超级耗内存的,②、操作数据库的时候Cursor忘记关闭,③、资源未释放,比如io流,file等,④、内存泄露。我们用用的OOM主要是加载图片导致的。因为后面的三种原因都是可以通过约束程序员的编码规范来进行预防,或者使用性能分析工具来检查。所以大致分为两类:

     ⑴,加载对象过大;

     ⑵,相应资源过多,没有来不及释放。

解决方案:

            ①在内存引用上做些处理,常用的有软引用、强化引用、弱引用

            ②在内存中加载图片时直接在内存中做处理,如:边界压缩.

            ③动态回收内存

            ④优化Dalvik虚拟机的堆内存分配

            ⑤自定义堆内存大小

3、ANR是什么?怎么避免和解决ANR?

ANR:Application Not Responding,五秒

在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。

  当对输入事件(如按键、触摸屏事件)的响应超过5秒会出现ANR

  意向接受器(intentReceiver)超过10秒钟仍未执行完毕会出现ANR。

  任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等,潜在的比较耗时的操作,如访问网络和数据库,或者是开销很大的计算如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。

4、请描述您在工作中所采用的Android异常处理机制(体现优点缺点)

如果在debug模式下开发的时候,是可以通过查看logcat日志来查看异常消息,从而进行处理。

如果我们在发布版本之后,用户在使用的时候会crash掉,我们需要写一个CrashHanler类结合log4j来记录日志,并且在发生crash时,将log文件发送到服务器。
这样程序就可以查看用户手机端的crash消息了,方便我们处理在debug模式开发时未发现的异常。

https://yq.aliyun.com/ziliao/26275

5、Handler,Loader和AsyncTask有什么区别,分别应用在哪些场景?

    Handler用于处理由looper分发的消息

   loader结合listview处理异步加载

     AsyncTask适合执行几秒内的网络任务

6、子线程发消息到主线程进行更新UI,有哪些方式?

方法一:用Activity对象的runOnUiThread方法更新 

在子线程中通过runOnUiThread()方法更新UI:

new Thread() {

        public void run() {

         //这儿是耗时操作,完成之后更新UI;

          runOnUiThread(new Runnable(){

                    @Override

                     public void run() {

                     //更新UI

                     imageView.setImageBitmap(bitmap);

}});}

}.start();

方法二:子线程调用Handler的sendMessage(message)发送事件。

①主线程中定义Handler:

Handler mHandler = new Handler() {

    @Override

      public void handleMessage(Message msg) {

             super.handleMessage(msg);

             switch (msg.what) {

                 case 0:

                 //完成主界面更新,拿到数据

                   String data = (String)msg.obj;

                    updateWeather();

                    textView.setText(data);

                     break;

                  default:

                     break;

}}};

②子线程发消息,通知Handler完成UI更新:

private void updateWeather() {

       new Thread(new Runnable(){

              @Override

              public void run() {

              //耗时操作,完成之后发送消息给Handler,完成UI更新;

                        mHandler.sendEmptyMessage(0);

                        //需要数据传递,用下面方法;

                        Message msg =new Message();

                        msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等;

                        mHandler.sendMessage(msg);

}}).start();

}

方法三:View.post(Runnable )

public void onClick( View v ) {  
        new Thread( new Runnable() {  
                public void run() {  
                       // 耗时操作  
​    ​    ​    ​    ​    ​      loadNetWork();  
​                          myText.( new Runnable() {  
                                  myText.setText( 来自网络的信息);  
                          });  
                 }  
        }).start();  
}

方法四:AsyncTask

//UI线程中执行  
new DownloadImageTask().execute( "www.91dota.com" );  
private class DownloadImageTask extends AsyncTask {  
    protected String doInBackground( String... url ) {  
         return loadDataFormNetwork( url[0] );//后台耗时操作  
    }  

    protected void onPostExecute( String result ) {  
          myText.setText( result ); //得到来自网络的信息刷新页面   

   }  
}

总结:

a.如果只是单纯的想要更新UI而不涉及到多线程的话,使用View.post()就可以了;

b.需要另开线程处理数据以免阻塞UI线程,像是IO操作或者是循环,可以使用Activity.runOnUiThread();

c.如果需要传递状态值等信息,像是蓝牙编程中的socket连接,就需要利用状态值来提示连接状态以及做相应的处理,就需要使用Handler + Thread的方式;

d.如果是后台任务,像是下载任务等,就需要使用AsyncTask。

https://www.cnblogs.com/wenjiang/p/3180324.html

7、如何理解Activity、View、Window三者之间的关系?

Activity包含了一个PhoneWindow,而PhoneWindow就是继承于Window的,Activity通过setContentView将View设置到了PhoneWindow上。View的事件监听是由WindowManagerService来接受消息,并回调Activity函数,比如onClickListener,noKeyDown等。

https://blog.csdn.net/zane402075316/article/details/69822438

8、Activity的几种LaunchMode及使用场景

基本上我们可以直接指定一个launchMode属性在AndroidManifest.xml 文件中

<activity android:name=".views.MainActivity"

android:screenOrientation="portrait"

android:launchMode="singleTop"/>

standard 模式介绍

默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。

场景:闹钟的使用 standard。用户可以启动此activity的多个实例,这些实例可以是任何任务的一部分,也可以是活动堆栈中的任何地方的一部分。

singleTop 模式介绍

如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。

场景:浏览书签页面使用singleTop(搜索功能)。虽然有可能是这一活动的多个实例,如果已经有一个在任务栈顶的活动将被重用和onnewintent()将被调用。这样,你只需要返回一次返回到浏览器,如果书签activity是开始多次。

singleTask 模式介绍

如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。

场景:browseractivity使用singleTask。只有一个浏览器的活动的时间,它不成为一部分的任务,把它试图打开网页。虽然它可能会返回到任何最近推出的它,当你回击它实际上是固定在其自己的任务活动栈的底部。它将分享它的任务与活动,它推出像书签.

singleInstance 模式介绍

在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。

场景:

alarmalert使用singleInstance。只有一个警报活动在一个时间,它总是自己的任务。它启动的任何东西(如果有的话)成为它自己的新任务的一部分这种模式很少被使用。一些真正的用例是一个用于启动或应用程序的活动,你是100%肯定只有一个活动。总之,我建议你不要使用这种模式,除非它是真的有必要。

https://blog.csdn.net/android_freshman/article/details/52948124

9、android中的几种动画

①Tween(补间)动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;

②Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。

10、RxJava有哪些优点?

异步、简洁(逻辑、代码读写)。内部支持多线程操作,强大的map和flatmap保证了依赖上一次接口数据进行二次处理时不会发生嵌套,将各个模块分离。

https://www.jianshu.com/p/06d506e6b728

11、你了解哪些设计模式,应用场景是什么?

http://mobile.51cto.com/android-535194.htm?mobile

12、 内存溢出和内存泄漏有什么区别?何时会内存泄漏?如何优化内存?

13、简述做过的项目,涉及到哪些技术点,遇到什么技术难点,解决方案

猜你喜欢

转载自blog.csdn.net/P876643136/article/details/81952636