Android 常规面试题整理(内含参考答案)

Android 四大组件是什么?

参考答案

Activity【活动】:用于表现功能。
Service【服务】:后台运行服务,不提供界面呈现。
BroadcastReceiver【广播接收器】:用来接收广播。
Content Provider【内容提供商】:支持在多个应用中存储和读取数据,相当于数据库。

Android 四个组件的生命周期?

参考答案
Activity生命周期图及 Fragment生命周期图

Service的生命周期:首先Service有两种启动方式,而在这两种启动方式下,它的生命周期不同。

通过startService()方法启动的服务

  初始化结束后系统会调用 void onStart(Intent intent) 方法,用于处理传递给startService()的Intent对象。如音乐服务会打开Intent 来探明将要播放哪首音乐,并开始播放。注意:多次调用startService()方法会多次触发onStart()方法。

通过bindService ()方法启动的服务

  初始化结束后系统会调用 IBinder onBind(Intent intent) 方法,用来绑定传递给bindService 的Intent 的对象。注意:多次调用bindService()时,如果该服务已启动则不会再触发此方法。

Activity的四种启动模式对比?

参考答案
Standard:标准的启动模式,如果需要启动一个activity就会创建该activity的实例。也是activity的默认启动模式。 SingeTop:如果启动的activity已经位于栈顶,那么就不会重新创建一个新的activity实例。而是复用位于栈顶的activity实例对象。如果不位于栈顶仍旧会重新创建activity的实例对象。 SingleTask:设置了singleTask启动模式的activity在启动时,如果位于activity栈中,就会复用该activity,这样的话,在该实例之上的所有activity都依次进行出栈操作,即执行对应的onDestroy()方法,直到当前要启动的activity位于栈顶。一般应用在网页的图集,一键退出当前的应用程序。 singleInstance:如果使用singleInstance启动模式的activity在启动的时候会复用已经存在的activity实例。不管这个activity的实例是位于哪一个应用当中,都会共享已经启动的activity的实例对象。使用了singlestance的启动模式的activity会单独的开启一个共享栈,这个栈中只存在当前的activity实例对象。

Activity在有Dialog时按Home键的生命周期?

参考答案
当我们的Activity上弹出Dialog对话框时,程序的生命周期依然是onCreate() —> onStart() —> onResume(),在弹出Dialog的时候并没有onPause()和onStop()方法。而在此时我们按下Home键,才会继续执行onPause()和onStop()方法。这说明对话框并没有使Activity进入后台,而是在点击了Home键后Activity才进入后台工作。

原因就是,其实Dialog是Activity的一个组件,此时Activity并不是不可见,而是被Dialog组件覆盖了其他的组件,此时我们无法对其他组件进行操作而已。

两个Activity 之间跳转时必然会执行的是哪几个方法?

参考答案
首先定义两个Activity,分别为A和B。

当我们在A中激活B时,A调用onPause()方法,此时B出现在屏幕时,B调用onCreate()、onStart()、onResume()。

这个时候B【B不是一个透明的窗体或对话框的形式】已经覆盖了A的窗体,A会调用onStop()方法。

前台切换到后台,然后再回到前台,Activity生命周期回调方法。弹出Dialog,生命值周期回调方法?

参考答案
首先定义两个Activity,分别为A和B。

完整顺序为:A调用onCreate()方法 —> onStart()方法 —> onResume()方法。当A启动B时,A调用onPause()方法,然后调用新的Activity B,此时调用onCreate()方法 —> onStart()方法 —> onResume()方法将新Activity激活。之后A再调用onStop()方法。当A再次回到前台时,B调用onPause()方法,A调用onRestart()方法 —> onStart()方法 —> onResume()方法,最后调用B的onStop()方法 —> onDestory()方法。

弹出Dialog时,调用onCreate()方法 —> onStart()方法 —> onResume()方法。

fragment各种情况下的生命周期?

参考答案
由于Fragment的生命周期与Activity的生命周期有着牵扯,所以把两者的图放到一起作为对比理解。

接下来就不同情况下的Fragment生命周期做一简单介绍:

Fragment在Activity中replace 新替换的Activity:onAttach() —> onCreate() —> onCreatView() —> onViewCreated —> onActivityCreated() —> onStart —>onResume()

被替换的Activity:onPause() —> onStop()--->onDestoryView()--->onDestory()--->onDetach()`

Fragment在Activity中replace,并addToBackStack 新替换的Fragment(没有在BackStack中):onAttach > onCreate > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

新替换的Fragment(已经在BackStack中):onCreateView > onViewCreated > onActivityCreated > onStart > onResume

被替换的Fragment:onPause > onStop > onDestroyView

Fragment在ViewPager中切换 我们称切换前的的Fragment称为PreviousFragment,简称PF;切换后的Fragment称为NextFragment,简称NF;其他Fragment称为OtherFragment,简称OF。

(在ViewPager中setUserVisibleHint能反映出Fragment是否被切换到后台或前台,所以在这里也当作生命周期)

如果相关的Fragment没有被加载过: NF: setUserVisibleHint(false)【用户不可见】 > onAttach > onCreate > setUserVisibleHint(true)【用户可见】 > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF跟NF相邻: setUserVisibleHint(false) > onAttach > onCreate > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

如果相关的Fragment已经被加载过: NF跟PF相邻 :setUserVisibleHint(true)

NF跟PF不相邻:setUserVisibleHint(true) > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

PF跟NF相邻 :setUserVisibleHint(false)

PF跟NF不相邻:setUserVisibleHint(false) > onPause > onStop > onDestroyView

OF跟PF相邻:onPause > onStop > onDestroyView

OF跟NF相邻:onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF夹在PF和NF中间:不调用任何生命周期方法

NF跟PF相邻 :setUserVisibleHint(true)

NF跟PF不相邻:setUserVisibleHint(true) > onCreateView > onViewCreated > onActivityCreated > onStart > onResume

PF跟NF相邻 :setUserVisibleHint(false)

PF跟NF不相邻:setUserVisibleHint(false) > onPause > onStop > onDestroyView

OF跟PF相邻:onPause > onStop > onDestroyView

OF跟NF相邻:onCreateView > onViewCreated > onActivityCreated > onStart > onResume

OF夹在PF和NF中间:不调用任何生命周期方法

如果重写了FragmentPagerAdapter的DestroyItem方法,并且相关的Fragment已经加载过: 相互切换时只会调用setUserVisibleHint

Fragment进入了运行状态: Fragment在进入运行状态时,以下四个生命周期会随它所属的Activity一起被调用:

onPause() —> onStop() —> onStart() —> onResume()

关于Fragment的onActivityResult方法: 使用Fragment的startActivity方法时,FragmentActivity的onActivityResult方法会回调相应的Fragment的onActivityResult方法,所以在重写FragmentActivity的onActivityResult方法时,注意调用super.onActivityResult。

如何实现Fragment的滑动?

参考答案
将Fragment与viewpager绑定,通过viewpager中的touch事件,会进行move事件的滑动处理。

Fragment布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_red_light">
<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="Fragment One" />
    </LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_red_light">
    <TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="Fragment Two" />
    </LinearLayout>

Fragment代码:

public class FragmentOne extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
           return inflater.inflate(R.layout.fragment_one, container, false);
}

}
public class FragmentTwo extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
   return inflater.inflate(R.layout.fragment_Two, container, false);
}
}

viewpager布局:

xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.spreadtrumshitaoli.fragmentscroll.MainActivity">
<android.support.v4.view.ViewPager
    android:id="@+id/view_pager"
    android:layout_height="match_parent"
    android:layout_width="match_parent"/>
</android.support.constraint.ConstraintLayout>

MainActivity代码:

public class MainActivity extends AppCompatActivity {
private FragmentOne fragmentOne;
private FragmentTwo fragmentTwo;
 
private ViewPager viewPager;
 
private ArrayList<Fragment> mFragmentList = new ArrayList <Fragment>();
private FragmentPagerAdapter fragmentPagerAdapter;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    init();
 
}
 
private void init() {
 
    viewPager = (ViewPager) findViewById(R.id.view_pager);
    fragmentOne = new FragmentOne();
    fragmentTwo = new FragmentTwo();
 
    mFragmentList.add(fragmentOne);
    mFragmentList.add(fragmentTwo);
    
    //将adapter和fragment绑定在一起。
        fragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int i) {
                return mFragmentList != null ? mFragmentList.get(i) : null;
            }
            @Override
        public int getCount() {
            return mFragmentList != null ? mFragmentList.size() : 0;
        }
    };
    viewPager.setAdapter(fragmentPagerAdapter);
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i1) {
 
        }
 
        @Override
        public void onPageSelected(int i) {
            //TODO:
        }
 
        @Override
        public void onPageScrollStateChanged(int i) {
 
        }
    });
 
}
   } 

在这段代码中,我们

首先fragment以及viewpager都实例化;

再将fragment添加到泛型arraylist里;

最后将带有fragment的arraylist和adapter绑定。

Android中的动画有哪些?

参考答案
逐帧动画(Frame Animation) 加载一系列Drawable资源来创建动画,简单来说就是播放一系列的图片来实现动画效果,可以自定义每张图片的持续时间

补间动画(Tween Animation) Tween可以对View对象实现一系列动画效果,比如平移,缩放,旋转,透明度等。但是它并不会改变View属性的值,只是改变了View的绘制的位置,比如,一个按钮在动画过后,不在原来的位置,但是触发点击事件的仍然是原来的坐标。

属性动画(Property Animation) 动画的对象除了传统的View对象,还可以是Object对象,动画结束后,Object对象的属性值被实实在在的改变了

设备横竖屏切换的时候,生面周期的变化(这个偶尔会问)

参考答案
不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

RecyclerView和ListView的区别(这个是必问的)

参考答案
RecyclerView可以完成ListView,GridView的效果,还可以完成瀑布流的效果。同时还可以设置列表的滚动方向(垂直或者水平); RecyclerView中view的复用不需要开发者自己写代码,系统已经帮封装完成了。 RecyclerView可以进行局部刷新。 RecyclerView提供了API来实现item的动画效果。

在性能上: 如果需要频繁的刷新数据,需要添加动画,则RecyclerView有较大的优势。 如果只是作为列表展示,则两者区别并不是很大。

Android异步消息处理机制(这个也会经常问到)

参考答案
异步消息处理机制主要是用来解决子线程更新UI的问题

主要有四个部分:
①. Message (消息) 在线程之间传递,可在内部携带少量信息,用于不同线程之间交换数据 可以使用what、arg1、arg2字段携带整型数据 obj字段携带Object对象
②. Handler (处理者) 主要用于发送和处理消息,sendMessage()用来发送消息,最终会回到handleMessage()进行处理
③. MessageQueue (消息队列) 主要存放所有通过Handler发送的消息,它们会一直存在于队列中等待被处理 每个线程只有一个MessageQueue
④. Looper (循环器) 调用loop()方法后,会不断从MessageQueue 取出待处理的消息,然后传递到handleMessage进行处理

图片加载框架有哪些?他们之间的区别是什么?(这个也是必问的)

ImageLoader 优点
① 支持下载进度监听;
② 可以在 View 滚动中暂停图片加载;
③ 默认实现多种内存缓存算法这几个图片缓存都可以配置缓存算法,不过 ImageLoader 默认实现了较多缓存算法,如 Size 最大先删除、使用最少先删除、最近最少使用、先进先删除、时间最长先删除等;
④ 支持本地缓存文件名规则定义; 缺点: 缺点在于不支持GIF图片加载, 缓存机制没有和http的缓存很好的结合, 完全是自己的一套缓存机制

Picasso 优点
① 自带统计监控功能,支持图片缓存使用的监控,包括缓存命中率、已使用内存大小、节省的流量等。
② 支持优先级处理
③ 支持延迟到图片尺寸计算完成加载
④ 支持飞行模式、并发线程数根据网络类型而变,手机切换到飞行模式或网络类型变换时会自动调整线程池最大并发数。
⑤ “无”本地缓存。Picasso 自己没有实现本地缓存,而由okhttp 去实现,这样的好处是可以通过请求 Response Header 中的 Cache-Control 及 Expired 控制图片的过期时间。 缺点: 于不支持GIF,默认使用ARGB_8888格式缓存图片,缓存体积大。

Glide 优点
①图片缓存->媒体缓存 ,支持 Gif、WebP、缩略图。甚至是 Video。
②支持优先级处理
③与 Activity/Fragment 生命周期一致,支持 trimMemory
④支持 okhttp、Volley。Glide 默认通过 UrlConnection 获取数据,可以配合 okhttp 或是 Volley 使用。实际 ImageLoader、Picasso 也都支持 okhttp、Volley。
⑤内存友好,内存缓存更小图片,图片默认使用默认 RGB565 而不是 ARGB888 缺点: 清晰度差,但可以设置

Fresco 优点:

①图片存储在安卓系统的匿名共享内存, 而不是虚拟机的堆内存中,所以不会因为图片加载而导致oom, 同时也减少垃圾回收器频繁调用回收Bitmap导致的界面卡顿,性能更高.
②渐进式加载JPEG图片, 支持图片从模糊到清晰加载
③图片可以以任意的中心点显示在ImageView, 而不仅仅是图片的中心.
④JPEG图片改变大小也是在native进行的, 不是在虚拟机的堆内存, 同样减少OOM
⑤很好的支持GIF图片的显示 缺点: 框架较大, 影响Apk体积,使用较繁琐

ANR是什么?怎样避免和解决ANR

参考答案
Application Not Responding,即应用无响应

出现的原因有三种:
a)KeyDispatchTimeout(5 seconds)主要类型按键或触摸事件在特定时间内无响应
b)BroadcastTimeout(10 seconds)BoradcastReceiver在特定的时间内无法处理
c)ServiceTimeout(20 seconds)小概率类型Service在特定的时间内无法处理完成

避免ANR最核心的一点就是在主线程减少耗时操作。通常需要从那个以下几个方案下手:
a)使用子线程处理耗时IO操作
b)降低子线程优先级,使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认Thread的优先级和主线程相同
c)使用Handler处理子线程结果,而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程
d)Activity的onCreate和onResume回调中尽量避免耗时的代码
e)BroadcastReceiver中onReceiver代码也要尽量减少耗时操作,建议使用intentService处理。intentService是一个异步的,会自动停止的服务,很好解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题

最后

因文章篇幅长度限制,无法完整展现 Android 面试常见知识点,为了能帮助到大家参考进行学习,小编已将Android 面试知识点进行的整理PDF 文档形式,并上传之CSDN的开发平台 GitHub地址:https://github.com/733gh/Android-T3 给大家进行参考学习。

猜你喜欢

转载自blog.csdn.net/u012165769/article/details/115145285