关于ANR
一、什么是ANR?
ANR就是Application Not Responding,是安卓中弹出的一个对话框,让用户来选择等待或者直接关闭程序。activity响应超过5秒,service响应超过10秒,都会出现ANR。
二、ANR产生的原因
刚才也说了,activity响应超过5秒,service响应超过10秒,都会出现ANR。那么为什么activity或者service会用这么长时间来响应呢?最大的原因可能就是主线程被阻塞了。所以产生ANR的原因有以下两个:
- 主线程中存在耗时的计算
- 主线程被IO操作阻塞(安卓4.0以后,网络IO禁止在主线程执行)
那么安卓中有哪些是在主线程中执行的呢?
- activity的所有生命周期方法;
- service默认是在主线程的;、
- broadcast中的onReceive()回调方法;
- AsyncTask中除了doInBackgroud方法,其他的四个方法都是在主线程中的;
- Handler的handleMessage()和post(Runnable)方法,前提是这个Handler没有使用子线程的looper。
基本上就是这么多,所以在上述这些方法中是绝对不能做耗时操作的,否则就会出现ANR异常。
三、怎么避免ANR?
避免ANR的总方针就是不要阻塞主线程,具体的方法有以下这些:
- 使用AsyncTask来进行耗时操作;
- 使用Thread或者HandlerThread来提高线程优先级;
- 使用Handler来处理工作线程;
- 不要在Activity中执行耗时的计算。
一般做到以上几步就可以避免ANR了。
关于Activity
一、简述一下Activity的生命周期
- 首先在回答这个问题之前,我们先来说一下什么是Activity。
- Activity是安卓中与用户进行交互的接口,它提供了一个界面,可以让用户进行点击、滑动等一系列操作。
- 在了解了activity是什么以后,我们还必须了解一下activity的四种状态
- running状态:这时activity处于活跃状态,用户可以与其进行交互,可以进行点击、滑动等操作,界面会做出响应。
- pause状态:这时activity处于可见状态,但是失去触摸的能力。一般activity被一个透明的activity或者非全屏的activity覆盖,此时被覆盖的activity就处于pause状态。如果内存紧张,会被系统回收。
- stop状态:此时的activity处于完全不可见状态。一般是被另一个activity完全覆盖时,被覆盖的activity处于的状态。如果内存紧张,会被系统回收。
- killed状态:此时的activity已经被系统回收,它保存的信息以及成员变量都会被销毁。
在了解了以上内容以后,我们就可以来说一下activity的生命周期了。
activity一共有7个生命周期方法。
- 当activity启动的时候,它会经过如下生命周期方法,依次是:onCreate()–>onStart()–>onResume()
- onCreate():一般是完成界面以及数据的初始化工作,是activity启动时第一个被调用的方法。
- onStart():此时的activity处于可见状态,但是还不可以与用户进行交互。
- onResume():此时的activity已经完全完成加载动作,用户可以对其进行滑动、点击等操作。
- 当点击Home键返回主界面的时候,此时的activity处于不可见状态了,它会经过以下生命周期方法:onPause()–>onStop()
- onPause():此时activity还是处于可见状态的,但是已经失去与用户进行交互的能力了。与之对应的是onResume()方法。
- onStop():此时的activity处于完全不可见状态了。
- 再次返回原Activity,由于之前已经缓存过activity,所以再次回来不会走onCreate()方法,它的生命周期方法如下:onRestart()–>onStart()–>onResume()
- onRestart():从缓存中重新加载activity会走此方法。
- 退出activity,它会走如下生命周期方法:onPause()–>onStop()–>onDestroy()
- onDestroy():走到该方法表示activity已经被销毁了,它的成员变量等已经被系统回收了。
二、Android任务栈
任务栈是后进先出的栈结构,Android通过任务栈可以有序管理每一个Activity。任务栈并不是唯一的,一个App中可以有多个任务栈,但是,在某些情况下,一个Activity也可以独享一个任务栈。
三、activity有几种启动模式,各有什么区别?
1.Standard模式 :每次启动Activity都会创建一个Activity实例,加入任务栈中,不会考虑任务栈中是否有相同的Activity。较为消耗资源。
2.SingleTop模式 :栈顶复用模式,如果新创建的Activity与当前的Activity一致,处于栈顶的话,就不会创建新的Activity,而是复用栈顶的Activity。
3.SingleTask模式 :任务栈复用模式,在新建Activity之前会检测任务栈中是否有相同的Activity,有的话直接把Activity移到栈顶,这个Activity以上的Activity都会被移除和销毁;没有就新建一个。
4.SingleInstance模式 :在整个系统中,有且只有一个实例,而且这个Activity独享任务栈。
四、Android进程优先级
1.前台进程 :处于前台正在与用户进行交互的Activity,或者在前台绑定的Service。
2.可见进程 :可见但不可交互的Activity。
3.服务进程 :在后台开启的Service就是服务进程。
4.后台进程 :当处于前台的Activity,被按下Home键之后,该Activity会变成后台进程,但后台进程不会被立马销毁,系统会根据内存情况进行相应的回收。
5.空进程 :表示没有活跃的组件,只是出于缓存的目的而保留,可被随时收回。
五、Scheme跳转模式
android中的scheme是一种页面内跳转协议,是一种非常好的实现机制,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面;通过scheme协议,服务器可以定制化告诉app跳转哪个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转页面等。
关于Fragment
一、Fragment为什么被称为第五大组件?
首先在使用频率上,fragment不低于其他四大组件,而且它有自己的生命周期。使用fragment比activity更加节省内存,同时,它可以很灵活的加载到activity中,所以它被称为第五大组件。虽然它有自己的生命周期,但是它必须依附于宿主activity存在。
二、Fragment加载到activity中的两种方式?
- 静态加载:在activity的布局文件中以标签的形式添加fragment。
- 动态加载:在java文件中以代码的形式加载fragmet。
- 1、获取FragmentManager管理者对象;
- 2、通过上述对象的beginTranscation()方法创建FragmentTranscation对象;
- 3、通过transcation对象的add()/remove()/replace()/hide()/show()等方法来显示或者移除fragment;
- 4、通过transcation对象的commit()方法来提交。
总结起来就是如下两行代码:
getFragmentManager().beginTranscation().add()
getFragmentManager().beginTranscation().commit()
注意:
1、同一个fragment只能被add一次;
2、同一个transcation只能被提交一次;
3、transcation.addToBackStack(null)将碎片添加到返回栈中,此时按下返回键,不会退出程序,而是返回上一个碎片。
三、fragmentPagerAdapter和fragmentStatePagerAdapter的区别?
fragmentPagerAdapter在destroyItem()的时候调用的是detach()方法,只是把UI进行了分离,并没有真正的移除fragment,所以只适用于页面较少的情况。而fragmentStatePagerAdapter在切换页面的时候调用的是remove()方法,是真正回收内存的,所以它适用于页面较多的情况。
四、fragment的生命周期?
onAttach()–>onCreate()–>onCreateView()–>onViewCreate()–>activity.onCreate()–>onActivityCreate()–>activity.onStart()–>activity.onResume()–>activity.onPause()–>activity.onStop()–>onDestroyView()–>onDetach()
五、fragment与activity之间的传值通信?
1、fragment向activity之间的传值:
- 在fragment中通过getActivity()获取activity的对象,然后调用activity中的方法;
- 接口回调:在fragment中设置一个接口,然后让activity实现这个接口,这样就可以在接口中将数据传递给activity.
2、activity向fragment传值:
- 在 activity中创建Bundle数据包,通过putExtra()方法将数据放进去,然后调用fragment对象的setArguments(bundle)方法,在fragment中就可以通过getArguments()方法获取数据。
- 在activity中通过getFragmentManager.findFragmentById()获取fragment对象,然后就可以调用fragment的方法了。
3、fragment与fragment传值:
- 在第一个fragment中调用getActivity().getFragmentManager().findFragmentById()获取第二个fragment的对象,然后调用第二个fragment中的方法;
- 接口回调:在fragment1中设置一个接口,宿主activity实现这个接口,fragment1在接口中与activity实现通信,然后在activity中的回调方法中,实现与fragment2的通信。
总结:fragment与activity通信的关键点就是要拿到对方的对象,fragment通过getActivity()获取activity的对象,activity通过getFragmentManager().getFragmentById()来获取fragment对象。fragment与activity之间可以直接通信,而fragment之间必须通过activity这个宿主来实现通信。
关于service
一、什么是Service?
Service是一个可以在后台长时间运行操作而且没有用户界面的组件。它是运行在主线程中的,所以不能在Service中执行耗时操作。它可以由其他组件来启动,比如activity或者broadcast,服务一旦启动,就会一直在后台运行,即使启动它的组件被销毁了,也不会影响它的运行。我们可以把service和activity进行绑定,这样就可以实现两者之间的数据交互。
二、service和thread的区别?
- 定义:thread是程序运行的最小单元,我们可以通过开启子线程来完成一些耗时操作,而service是后台服务,是安卓中的一种机制,如果是本地的service,那么它就运行在它所在的主线程,所以service中不能进行耗时操作。
- 实际开发:不能在service中进行耗时操作,如果一定要进行,那么也必须要开启子线程,那为什么不在activity中开启子线程呢?因为activity很难对子线程进行把控,一旦activity销毁了,那么将很难获得子线程的实例,容易造成内存泄漏。而service不一样,即使activity被销毁了,service依然可以在后台执行。
- 应用场景:如果我们需要进行耗时操作,那么就必须要开启子线程。而service是需要长时间在后台运行,并且不需要用户界面的情况下才会使用,比如后台播放音乐,天气预报的统计等。
三、service的两种启动方式以及区别?
- startService:通过此种方式启动的服务,会一直在后台运行,除非手动关闭。
- 执行步骤如下:
- 1、定义一个类继承service;
- 2、在manifest.xml文件中注册service;
- 3、使用context的startService()启动服务;
- 4、如果不再使用,调用stopService()方法来停止该服务。
- bindService:此时service和activity处于绑定状态,两者之间可以进行数据交互。
- 执行步骤如下:
- 定义一个服务端继承service,并且在类中实现IBinder接口的实例对象,并提供公共方法给客户端调用;
- 在onBind()方法中返回此Binder实例;
- 客户端在onServiceConnected()方法中接收Binder实例,并通过服务端提供的方法绑定服务。
接下来通过代码来深刻理解两种启动service的方法到底什么区别。
- 首先是startService
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
-接下来是bindService
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78