Activity
1、 什么是Activity?
Activity是四大组件之一,他给用户的感受就是一个用户交互界面。一个Activity就是一个可见的界面。
他的特点是:1、可见 2、可交互
他之所以可交互,是因为他同时实现了Window.Callback和KeyEvent.Callback, 可以处理与窗体用户交互的事件和按键事件.这两个特点,是他和service最大的区别。
一个Activity在创建于销毁的过程中,会经历一些生命周期。
如果界面有共同的特点或者功能的时候,还会自己定义一个BaseActivity.
2、Activity的生命周期
a、简述一下生命周期
生命周期描述的是一个类 从创建(new出来)到死亡(垃圾回收)的过程中会执行的方法…
在这个过程中 会针对不同的生命阶段会调用不同的方法
Activity从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:onCreate onDestroy onStop onStart onResume onPause onRestart
当从A界面跳转到B界面的时候,A界面会调用onPause onStop B界面会调用onCreate、onStart、onResume等。在回到A界面的时候,A界面会调用onReStart、onStart、onResume
如果B界面是透明的activity,那么进行跳转的时候,A界面是不会调用onStop的,只会调用onPause 再回到A界面的时候,A界面会调用onResume
b、A界面跳转到B界面的时候,再回到A界面,A界面必然会执行的是哪几个方法。
两个Activity之间的跳转必然会执行的是onResume方法,这个具体的应用场景是每次回到该界面的时候,如果界面需要展示最新的数据,那么可以在该方法中实现。
多媒体播放视频的时候, 来了一个电话. onStop() 视频, 视频声音设置为0 , 记录视频播放的位置 mediaplayer.pause();
onResume() 根据保存的状态恢复现场. mediaplayer.start();
c、在屏幕旋转的时候,activity的生命周期是怎样的?
横竖屏进行切换的时候,默认的情况下,Activity会重新的调用onCreate方法。因为竖屏的activity销毁了,再生成一个横屏的activity 。
在AndroidManifest.xml可以进行配置,我们可以通过android:configChanges进行配置。android:configChanges=“orientation|keyboardHidden|screenSize” 配置了之后,横竖屏切换的时候,就不会调用onCreate了,而是调用onConfigurationChanged的方法。
在一些特殊应用中,屏幕的方向是写死的,比如游戏。在AndroidManifest中配置android:screenOrientation=“landscape"就可以了。
d、讲一讲你对activity的理解
e、设置activity的样式为窗口的样式,对生命周期有什么影响?
设置窗口样式,需要在配置文件中增加theme的属性
android:theme=”@android:style/Theme.Dialog"
activity设置为窗口样式的时候,当启动这个activity的时候,之前那个activity是不会走onStop方法的,而是只走到了onPause方法。
3、你后台的Activity被系统 回收如何在被系统回收之前保存当前状态?
除了在栈顶的activity,其他的activity在系统资源匮乏的时候,都有可能会被系统回收。这时候系统会调用onSaveInstanceState方法,我们可以往bundle里面存放数据。在activity onCreate里面我们先判断一下bundle是不是为空,如果不为空,就代表这个activity之前被系统回收掉,应该恢复一下现场。我们就可以从bundle里面取值。
4、对android主线程的运用和理解
a、主线程也就是UI线程,四大组件都是运行在主线程中的。
b、主线程中有一个消息队列,主要处理窗口绘制、按钮响应等消息。
c、如果在主线程里面做耗时的操作,会导致窗口绘制等消息得不到及时的处理,从而有可能会报出anr的错误。
5、如何避免anr?如何解决anr?
anr是android not response 安卓无响应,这里指的是主线程无响应。将耗时的操作放在子线程中进行可以有效的避免anr。如果出现了anr,我们可以通过log信息以及traces.txt文件进行分析。
traces.txt里面记录的是stack信息。
6、Activity的数据传递
a、基础的数据类型通过Bundle进行传递
b、传递对象的话,需要该对象实现Serializable或者Parcelable接口,放到bundle进行传递。
c、在Application中进行存储。其他界面要用的话,就直接来application取就可以了。一个应用程序application的实例只有一个。
d、大对象,比如bitmap,我们一般都不传递这个对象,我们传递的一般都是路径就可以了。然后通过URI.fromFile()来传递URI
standard", “singleTop”, “singleTask”, “singleInstance”。
standard模式, 是默认的也是标准的Task模式,在没有其他因素的影响下,使用此模式的Activity,会构造一个Activity的实例,加入到调用者的Task栈中去,对于使用频度一般开销一般什么都一般的Activity而言,standard模式无疑是最合适的,因为它逻辑简单条理清晰,所以是默认的选择。
而singleTop模式,基本上于standard一致,仅在请求的Activity正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载onNewIntent来处理新的Intent(当然,也可以无视…)。这个模式,降低了位于栈顶时的一些重复开销
singleTask,和singleInstance,则都采取的另辟Task的蹊径。
标志为singleTask的Activity,最多仅有一个实例存在,并且,位于以它为根的Task中。所有对该Activity的请求,都会跳到该Activity的Task中展开进行。singleTask,很象概念中的单件模式,所有的修改都是基于一个实例,这通常用在构造成本很大,但切换成本较小的Activity中。最典型的例子,还是浏览器应用的主Activity(名为Browser…),它是展示当前tab,当前页面内容的窗口。它的构造成本大,但页面的切换还是较快的,于singleTask相配,还是挺天作之合的。
singleInstance显得更为极端一些。在大部分时候singleInstance与singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在栈中仅有的一个Activity, 这个栈,只有一个activity
activity是运行在任务栈中的,一个activity启动另外一个activity,默认的情况下,新的activity也是运行在同一个任务栈里的。service和广播接收者也是没有任务栈的,所以,他们启动activity的时候,给intent设置flag, Intent的flag添加FLAG_ACTIVITY_NEW_TASK
Service
9、什么是Service以及描述下它的生命周期?
service是一个服务,它是不可见的,同样也是运行在主线程中。它的生命周期的方法有onCreate、onStart、onDestory,它还有一些activity的没有的生命周期方法,onBind和onUnbind
不同的启动方式,生命周期调用的也不同。
启动Service的方式有两种,一种是startService和bindService
a、通过startService
Service会经历 onCreate 到onStart,然后处于运行状态,stopService的时候调用onDestroy方法。
这种方式,activity和service是相互独立的。如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行
b、通过bindService
Service会运行onCreate,然后是调用onBind, 这个时候调用者和Service绑定在一起。调用者退出了,Service就会调用onUnbind->onDestroyed方法。
这种方式,activity就和service相互捆绑在一起了。所谓绑定在一起就共存亡了。调用者也可以通过调用unbindService方法来停止服务,这时候Service就会调用onUnbind->onDestroyed方法。
Activity为什么要绑定Service?是因为有些情况下,我们需要调用service里面的方法。startService的方式我们是调用不到Service里面的方法的。
如何让服务长期在后台运行,而activity又可以调用到服务里面的方法?
先startService 然后bindService进行绑定,这个时候就可以调用服务里面的方法了。调用完了之后,你就unBindService,这时候退出界面的时候,服务是一直在后台跑的。
默认情况下,服务是运行在主线程中的,在特殊的情况下,我们可以通过AndroidManifest文件中进行配置android:process="" 这种情况下,服务就在另外一个进程的主线程中。
10. 什么是IntentService?有何优点?
普通的service ,默认运行在ui main 主线程(ID默认是1)
Sdk给我们提供的方便的,带有异步处理的service类,
OnHandleIntent() 处理耗时的操作
11、什么时候需要使用到Service
因为service是具有较高优先级。Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。所以我们需要使用到服务Service
在某些情况下,比如服务以及onStart了,那么此时服务的优先级会稍微的低一些,这时候还是有可能被系统回收,可以通过startForground提高服务的优先级,这个时候,系统就不会回收这个服务了。
因为服务的优先级较高,所以在一些场景中比较适合使用服务,比如:
a、拥有长连接QQ
b、定时轮询、耗时操作
c、服务里面注册广播接收者。有些广播接收者只能通过代码注册,比如屏幕锁屏、屏幕解锁
广播接收者
12、简单描述一下广播接收者
广播接收者有两类,一种是系统本身就有的,一种是我们自己写的广播接收者。
广播接收者注册的方式也有两种,一种是动态注册,一种是静态注册。
只能用代码注册的广播,这种广播产生的频率是比较高的。比如电量变化的广播,屏幕解锁的广播。电量变化的广播。
广播接收者在注册的时候可以指定优先级,用于提高接收到广播的顺序。
广播一般是用于跨进程通讯的时候。
13、如何发广播
广播分为两种,一种是有序广播,一种是无序广播
有序广播是按顺序被接收的,是可以被拦截和修改里面的数据的。而无序广播则没有接收顺序,也无法修改广播里面的数据。
拦截广播可以使用abortBroadcast()将有序广播给abort掉
数据存储
14、ContentProvider的使用
把自己的数据通过uri的形式共享出去,这个uri是事先约定好的。
android 系统下 不同程序 数据默认是不能共享访问,通过ContentProvider可以将自己应用的数据提供给别的应用。
我们在写内容提供者的时候,需要写一个类继承ContentProvider,然后实现里面的增删改查方法
query(Uri, String[], String, String[], String)
insert(Uri, ContentValues)
update(Uri, ContentValues, String, String[])
delete(Uri, String, String[])
15、Android提供的数据存储方式有哪些(内存:效率快,文件中存储临时文件,开关等)
a、SharedPreferences、sd卡的文件
b、数据库sqlite(大量的数据存储)
c、数据存储到服务器上(http协议访问后台接口传输上去)
View
16、View的绘制流程,自定义控件的使用
View如何绘制到手机上,一般用onDraw(Canvas canvas)在画布上(不过在此之前要 onMeasure和onLayout)
onMeasure->onLayout->onDraw
onMeasure:计算宽和高,调用setMeasuredDimension
onLayout: 计算位置
onDraw: 画在画布上
自定义控件需要在onMeasure、onLayout、onDraw中的某些方法进行修改,这样才能保证自定义的控件能够在正确的位置正确的大小被正确的画出来。
自定义属性的使用?
在values的目录下需要建立一个文件,叫做attrs.xml 这个文件是定义属性规则的。一个属性的名字、取值类型、取值范围
在布局文件中需要加入命名空间,最后在自定义控件中获取这些值。
17、View的事件传递
事件分发dispatchTouchEvent
事件拦截onInterceptTouchEvent{如在桌面中滑动时,返回true时父拦截事件,点击事件 时,点击时返回false时,不拦截事件传递给子控件就响应了点击事件}
事件响应onTouchEvent
事件传递的方向是由父类到子类,事件响应的方向是从子类到父类。
18、ListView的优化
listView是由item充填,每个item都是有getView返回的(如果有千百个item,就会有千百个inflate会很占内存的所以系统就给提供了convertView)
重用了convertView,减少了inflate的次数
使用ViewHolder,减少findViewById的次数,很大程度上的减少了内存的消耗。
19、布局的优化(就是提高UI的流程度)
优化布局层次。不要不断的嵌套LinearLayout ,多使用RelativeLayout 尽可能的减少布局的层次。如:左边是图片,右边是文字的,可以就使用一个TextView来完成。drawableLeft。
ViewStub(延时加载的view,当使用时才加载)、include(提取一个basePager.xml),listview子元素高度的计算
其他
20、线程间的通讯
Handler是用来进行线程间的通信。
Looper是用来管理所属线程的消息队列MessageQueue的
每一个线程都需要有一个looper,每一个looper管理一个MessageQueue
Handler.sendMessage的意思是将某一个message放到MessageQueue中去,looper是个死循环,不断的读MessageQueue中的新消息。
要让looper的死循环运行起来,得调用Looper.loop()方法。
我们通常都会在子线程中,发一个消息到主线程中的messagequeue中去。
21、内存泄露的查找
内存泄漏本身不会产生什么危害,真正有危害的是内存泄漏的堆积。Android应用内存泄漏的的原因有以下几个:
0、register之后没有unregister
1查询数据库后没有关闭游标cursor file没有close
2 构造Adapter时,没有使用 convertView 重用
3 Bitmap对象不在使用时调用recycle()释放内存
4 对象被生命周期长的对象引用,如activity被静态集合引用导致activity不能释放
内存泄漏如何解决:
生成hprof文件可以通过adt的工具也可以通过代码生成。debug的dump方法
22、如何处理大图片,图片缓存