Android面试系列之Android基础知识

这两天就要换工作了,为了拿到offer,是时候来一波面试准备了!希望自己能找到心仪的工作。也希望这篇博客能帮助到大家。

本篇博客是相对基础的知识,虽然是基础,但是很重要,你能保证你都记住了么?

Activity相关

Activity是四大组件之一,应该是我们开发中接触最多的组件了吧。那么问题来了!


什么是Activity?
Activity是Android中的一个组件,提供了一个界面用于和用户交互,使用户可以在界面上进行点击、滑动等操作。


Activity的四种状态
running / paused / stopped / killed

running: 表明Activity处于活动(完全可见)状态,用户可以与屏幕进行交互,此时,Activity处于栈顶。
paused: 表明Activity处于失去焦点的状态(例如:被非全屏的的Activity覆盖),此时用户无法与该Activity进行交互。
stopped: 表明activity处于不可见的状态(例如:被另一个Activity完全覆盖)。
killed: 表明Activity被系统回收了,


Activity生命周期

首先来一张经典的图:
Android面试系列之Android基础知识_第1张图片

正常情况下Activity生命周期大致可以分为四个场景:

1.Activity启动–>onCreate()–>onStart()–onResume();
onCreate是Activity被创建的时候调用,是生命周期的第一个方法,我们新建的Activity几乎都会重写这个方法,在这里我们可以做一些初始化操作等
onStart表明Activity正在启动,此时处于用户可见状态,但是并不能与用户交互
onResume表明Activity已经处于前台状态,可以与用户交互了。此时Activity就处于Running状态了

2.点击Home键–>onPause()–>onStop()
onPause:表明Activity处于paused状态,此时Activity无法与用户交互
onStop:一般在onPause后面执行,表明Activity处于完全不可见的状态。

3.点击home后再次回到程序时–>onRestart()–>onStart()–>onResume()
onRestart:表明Activity正在重新启动,从不可见状态变为可见状态

4.退出当前Activity–onPause()–>onStop()–>onDestory()
onDestory:表明Activity正在被销毁,是整个生命周期方法中的最后一个方法,在该方法中我们可以做一些资源回收的工作。

异常情况

在异常情况下比如由于内存不足,系统对Activity进行强制回收,这个时候生命周期就不会正常的执行了,系统会自动调用onSaveInstanceState这个方法,我们可以在这个方法中进行一些数据保存的工作,然后在onCreateonRestoreInstanceState方法中恢复数据。


android中的进程优先级

前台/可见/服务/后台/空

前台:包含正在处于和用户交互的Activity或者是前台Activity绑定了service
可见:activity处于可见状态但不可与用户进行交互
服务:包含一个service服务的进程
后台:处于不可见的状态下(比如按了home键)
:没有活跃的组件 知识为了缓存的目的存在的,随时都可能被系统杀掉


Android任务栈
用于存储Activity,当用户启动Activity或者退出Activity的时候,都会在栈中做一些添加或删除的操作。


Activity启动模式
1.standard
默认的启动模式,每次启动Activity的时候都会创建一个新的实例。不会复用Activity,对内存消耗较大。

2.singleTop
栈顶复用模式,如果要创建的Activity已经在栈顶的话,那么不会重新创建,直接复用,否则,仍然会重新创建。

3.singletask
栈内复用模式,如果要创建的Activity在栈内已经存在的话,不会重新创建,直接复用栈内存在的Activity,且会调用onNewIntent()方法,并且将该Activity以上的所有的Activity销毁。

4.singleInstance
单一实例,独享一个任务栈,整个手机操作系统里面只有一个实例存在。用的较少。


scheme跳转协议
android中的scheme是一种页面内跳转协议,通过自定义的scheme协议,可以方便的跳转app中的各个页面。通过scheme协议,服务端可以定制化告诉App跳转到哪个页面,可以通过通知栏消息定制化跳转页面,也可以通过H5页面跳转页面等。


Fragment相关

fragment在平时项目开发中用的也非常多,是Android3.0后引入的,起初是为了在大屏幕上更灵活的去展现ui。现在通常使用的方式是fragment+viewpager. fragment有自己的生命周期,必须依附Activity。


Fragment加载到Activity的两种方式

1.静态加载,在布局中加载
2.动态加载,在代码中加载(用的较多)
Android面试系列之Android基础知识_第2张图片

fragment经常和viewpager一起使用,不可避免的我们就会接触到FragmentPagerAdapter和FragmentStatePagerAdapter。

FragmentPagerAdapter和FragmentStatePagerAdapter有什么区别呢?
FragmentStatePagerAdapter在切换的时候会回收fragment
而FragmentPagerAdapter在切换时会将fragment与viewPager分离,并保存fragment的ui信息,
相比之下FragmentStatePagerAdapter更节省内存。所以在,在fragment比较多的时候推荐使用FragmentStatePagerAdapter。


Fragment的生命周期
Fragment是必须依附于Activity的,因此Activity的生命周期会直接影响到Fragment的生命周期。

Android面试系列之Android基础知识_第3张图片

详细的生命周期我们来看下面这张图:

Android面试系列之Android基础知识_第4张图片

由图片我们可以看整个fragment和Activity的生命周期执行顺序

fragment从创建到创建完成:

1.调用fragment中的onAttach()				fragment与Activity发生关联时调用
2.调用fragment中的onCreate()				创建fragment时调用
3.调用fragment中的onCreateView()			绘制fragment视图时调用
4.调用fragment中的onViewCreated()			界面绘制完成后调用
5.调用activity中的onCreate()             	activity创建了
6.调用fragment中的onActivityCreated()		在activity的onCreate()方法之后调用,表明activity已经绘制完成
7.调用activity中的onstart()					表明activity可见了
8.调用fragment中的onstart() 				activity可见后调用fragment中的onstart(),表明fragment也可见了
9.调用activity的onresume()方法				表明activity可以跟用户交互了
10.调用fragment的onResume()方法				此时,fragment也可以与用户进行交互了,到此为止,fragment完全初始化完毕了。

fragment的销毁过程:

1.调用fragment中的onPause()				此时fragment不可与用户交互
2.调用activity中的onPause()				此时activity不可与用户交互
3.调用fragment中的onStop()				此时fragment不可见
4.调用activity中的onStop()				此时activity不可见
5.调用fragment中的onDestoryView()      	fragment视图被移除调用
6.调用fragment中的onDestory()			fragment销毁时调用
7.调用fragment中的onDetach()			fragment与activity解除关联时调用
8.调用activity中的ondDestory()			activity销毁

fragment通信

1.fragment调用Activity中的方法
通过getActivity()调用

2.在Activity中调用Fragment中的方法
需要在fragment类中定义一个接口并在Activity中实现它。Fragment在onAttach()回调函数中获取接口的具体实现的对象。然后,fragment就可以调用接口中的方法实现与Activity的通信。

3.在Fragment中调Fragment中的方法
通过getSupportFragmentManager().findFragmentById()


FragmentManager中的add,remove和replace
一般我们两种模式,一种是将fragment添加(add)到容器中,控制其隐藏和显示。这种模式不会销毁fragment。
另一种就是替换(replace)这种方法会把之前的fragment销毁掉。


Service相关

service是四大组件之一,用的地方也很多。可以在后台执行一些逻辑。


什么是Service
Service是一种能在后台执行耗时任务的没有界面显示的组件。需要注意的是Service和BroadCastReceiver都是运行在主线程的,所以,Service本身不能做耗时操作,而是通过子线程去完成!


Service和Thread的区别
详细可以看这篇博客service和thread的区别
讲的非常仔细。

在这里做个总结:
Thread和Service实际上是没有任何关系,只不过因为字面上的意思,我们可能会误解为Service可以执行耗时任务的,实际上Service是运行在主线程上的,也就是说,Service本身并不能做耗时操作,一般都是在Service中启线程去执行耗时任务。

Thread是程序执行的最小单元,是独立与Activity运行的,也就是说,如果我们在Activity中启线程去执行任务,即使这个activity被销毁了,该任务也会继续执行。
而Service是Android中一种机制,在一些运行在后台的不需要界面的地方可以使用Service。


Service的生命周期
onbind/onCreate/onStartCommand/ondestory

onBind(): 该方法返回的是一个IBinder接口,当我们使用bindService的时候才会被调用
onCreate(): 服务首次创建时调用,注意,只有service第一个被创建时才会调用
onStartCommand(): 每次调用startService的时候都会执行该方法,该方法有一个int类型的返回值
Android面试系列之Android基础知识_第5张图片

分别是:START_STICKY、START_NOT_STICKY、START_REDELIVER_INTENT、START_STICKY_COMPATIBILITY。
START_STICKY:“粘性的”,如果service进程被意外kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

onDestory(): 服务销毁时调用,在这里可以做一些资源回收操作。


Service的两种启动方式

startService 和 bindService

startService
1.定义一个类继承自Service
2.在清单配置文件中声明
3.使用Context.startService(Intent)启动Service
4.调用Context.stopService(Intent)停止Service

 Intent intent = new Intent();
 intent.setClass(activity, UpdateApkService.class);
 activity.startService(intent);//开启服务

执行startService时,Service会经历onCreate->onStartCommand。当执行stopService时,直接调用onDestroy方法。调用者如果没有stopService,那么即使Activity被销毁了,Service也会继续执行,下次调用者再起来仍然可以stopService。

bindService
1.创建一个类继承自Service,并在类中创建一个实现IBinder接口的实例对象并提供公共方法。


    /*这里定义一个类  用于返回Service*/
    public class MyBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }

    }
    /*提供一个公共方法*/
    public Date getTime(){
        return new Date();
    }

2.在onBind()中返回自定义的IBinder实例

  private MyBinder myBinder=new MyBinder();


    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

3.在需要调用的地方,从onServiceConnected中获取IBinder实例并调用公共方法

  sc = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i("aaa","onServiceConnected");
                MyService.MyBinder myBinder = (MyService.MyBinder) service;
                Date date = ((MyService.MyBinder) service).getService().getTime();
                Log.i("aaa",date.toString());
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        };

        Intent intent = new Intent(this, MyService.class);
        bindService(intent, sc, BIND_AUTO_CREATE);

执行bindService时,Service会经历onCreate->onBind。这个时候调用者和Service绑定在一起。调用者调用unbindService方法或者调用者Context不存在了(如Activity被finish了),Service就会调用onUnbind->onDestroy。这里所谓的绑定在一起就是说两者共存亡了。


BroadcastReceiver

四大组件之一,在Android中,Broadcast是一种广泛运用在应用程序之间传输信息的机制,Android中我们要发送的是一个intent,intent可易携带我们需要传输的数据。


广播的使用场景
1.同一app中不同组件之间的数据传递
2.不同app之间组件的数据传递


广播的种类

1.普通广播 Context.sendBroadcast
2.有序广播 Context.sendOrderedBroadcast 根据优先级传播,优先级高的接收器和一阻止继续传播活修改数据
3.本地广播 LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); lbm.sendBroadcast(new Intent(LOCAL_ACTION)); 只会在应用内部传播,相对来说数据安全。


广播的注册方式

1.静态注册 在清单配置文件中声明,即使进程被杀死,该广播仍然运行

  
              
                  
                  
              
          

2.动态注册 在代码中注册,受activity生命周期的影响。

MyReceiver receiver = new MyReceiver();  
          
IntentFilter filter = new IntentFilter();  
filter.addAction("android.intent.action.MY_BROADCAST");  
          
registerReceiver(receiver, filter);  

内部实现机制
1.自定义BroadcastReceiver,重写onReceive()方法
2.通过Binder机制向AMS(Activity Manager Service)进行注册
3.广播发送者通过Binder机制向AMS发送广播
4.AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadCastReceiver相应的消息循环队列中
5.消息循环执行拿到广播,回调BroadCastReceiver中的onReceive()方法。


LocalBroadcastManager
1.使用LocalBroadcastManager发送的广播只能在app内部传播,因此数据传输很安全。
2.比系统广播更加高效,底层是通过Handler发送message实现的。


如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

你可能感兴趣的:(Android)