🔥51、如何判断Android APP应用被强制杀死?🔥
可以在Application中定义一个static常量,赋值为-1,然后在欢迎页面修改值为0,如果被强杀,Application被重新初始化,这个时候如果父Activity判断该常量是多少。
🔥52、如何解决应用被强制杀死?🔥
如果在每一个Activity的onCreate里判断是否被强杀,冗余了,封装到Activity的父类中,如果被强杀,跳转回主界面,如果没有被强杀,执行Activity的初始化操作,给主界面传递intent参数,主界面会调用onNewIntent方法,在onNewIntent跳转到欢迎页面,重新来一遍流程。
🔥53、Android Asset和res目录的区别?🔥
res和assets资源的主要区别如下:
1、引用资源的方式不同
res目录中的所有资源都会在R类的相应子类中生成对应的int类型变量,需要使用这些变量来引用资源。例如res/layout/main.xml是布局文件资源,会在R.layout类中生成一个名为main的变量,所以需要使用R.layout.main来引用main.xml。
assets目录中的资源需要直接使用文件名来引用,例如assets/xyz.xml、assets/abc/test.db是assets目录中的两个资源文件,其中abc是assets中的子目录。可以使用如下的代码引用这两个资源文件,并返回与资源文件对应的InputStream对象,剩下的操作就是普通的Java代码输入流操作了。
InputStream is1=getResources().getAssets().open(“xyz.xml”);
InputStream is2=getResources().getAssets().open(“abc/test.db”);
2、处理方式不同
res目录中的资源子目录除了raw外,其他资源目录中的资源文件都会被编译,这也是为什么将APK文件解压后无法直接查看XML格式资源文件内容的原因。
而assets与res/raw目录中的资源文件不会做任何处理,所以将APK解压后,这两个目录中的资源文件都会保持原样.
3、子目录不同
res目录只能有一层子目录,而且这些子目录必须是预定义的,如res/layout、res/values等都是合法的,而res/abc,res/xyz并不是合法的资源目录,在assets目录中可以建任意层次的子目录(只受操作系统的限制)
🔥 54、 简述Handler机制的原理?🔥
Andriod提供了 Handler 和 Looper 来满足线程间的通信。
Handler 先进先出原则。
Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
🔥 55、 简述MVC模式的原理,并且在Android中的运用?🔥
android的官方建议应用程序的开发采用mvc模式。何谓mvc?
mvc是model,view,controller的缩写,mvc包含三个部分:
l模型(model)对象:是应用程序的主体部分,所有的业务逻辑都应该写在该层。
l视图(view)对象:是应用程序中负责生成用户界面的部分。也是在整个mvc架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。
l控制器(control)对象:是根据用户的输入,控制用户界面数据显示及更新model对象状态的部分,控制器更重要的一种导航功能,想用用户出发的相关事件,交给m哦得了处理。
android鼓励弱耦合和组件的重用,在android中mvc的具体体现如下:
1)视图层(view):一般采用xml文件进行界面的描述,使用的时候可以非常方便的引入,当然,如何你对android了解的比较的多了话,就一定 可以想到在android中也可以使用javascript+html等的方式作为view层,当然这里需要进行java和javascript之间的通 信,幸运的是,android提供了它们之间非常方便的通信实现。
2)控制层(controller):android的控制层的重 任通常落在了众多的acitvity的肩上,这句话也就暗含了不要在acitivity中写代码,要通过activity交割model业务逻辑层处理, 这样做的另外一个原因是android中的acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。
3)模型层(model):对数据库的操作、对网络等的操作都应该在model里面处理,当然对业务计算等操作也是必须放在的该层的
🔥56、后台Activity被系统回收怎么办:onSaveInstanceState?🔥
当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B
这个时候A会执行
Java代码
public
void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong("id", 1234567890);
}
B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回
收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数
savedInstanceState,没被收回的就还是onResume就好了。
savedInstanceState是一个Bundle对象,你基本上可以把他理解为系统帮你维护的一个Map对象。在onCreate()里你可能会用到它,如果正常启动onCreate就不会有它,所以用的时候要判断一下是否为空。
Java代码
if(savedInstanceState != null){
long id = savedInstanceState.getLong("id");
}
就像官方的Notepad教程 里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦, 没准你需要记住滚动条的位置...
🔥57、 简述Android内存泄露的原因?🔥
资源对象没关闭。
如Cursor、File等资源。他们会在finalize中关闭,但这样效率太低。容易造成内存泄露。
SQLiteCursor,当数据量大的时候容易泄露
使用Adapter时,没有使用系统缓存的converView。
即时调用recycle()释放不再使用的Bitmap。
适当降低Bitmap的采样率,如:
BitmapFactory.Options options = newBitmapFactory.Options();
options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
Bitmap bitmap =BitmapFactory.decodeStream(cr.openInputStream(uri), null, options); preview.setImageBitmap(bitmap);
使用application的context来替代activity相关的context。
尽量避免activity的context在自己的范围外被使用,这样会导致activity无法释放。
注册没取消造成内存泄露
如:广播
集合中的对象没清理造成的内存泄露我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
Handler应该申明为静态对象, 并在其内部类中保存一个对外部类的弱引用。如下:
static class MyHandler extends Handler
{
WeakReference mActivityReference;
MyHandler(Activity activity)
{
mActivityReference= new WeakReference(activity);
}
@Override
public void handleMessage(Message msg)
{
final Activity activity = mActivityReference.get();
if (activity != null)
{
mImageView.setImageBitmap(mBitmap);
}
}
}
🔥58、请简述Android中Iterator和Enumeration的不同?🔥
1 函数接口不同
Enumeration只有2个函数接口。通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。 Iterator只有3个函数接口。Iterator除了能读取集合的数据之外,也能数据进行删除操作。
2 Iterator支持fail-fast机制,而Enumeration不支持。
Enumeration 是JDK
1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK
1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、
Hashtable实现Enumeration时,添加了同步。而Iterator 是JDK
1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的:当多个线程对
同一个集合的内容进行操作时,就可能会产生fail-fast事件。
🔥 59、Activity切换时生命周期交集 ?🔥
1.1、正常情况下,没有用户参与的情况,Activity的生命周期的改变
(1)onCreate:标识Activity正在创建,是生命周期的第一个方法,这里可以做界面布局的资源加载、初始化Activity的所需数据,控件的一些事件等
(2)onRestart:表示Activity正在重新启动。一般由Activity从不可见到可见状态时,会调用。比如切换到其它界面,或者通过Home键切换到桌面,当前Activity会被暂停,同时,OnPause和onStop被调用。然后紧接着又切换回这个Activity,则出现这种情况。
(3)onStart:表示Activity正在被启动,这是Activity可见,但还没有显示在前台,无法进行用户交互,可以理解为在后台。
(4)onResume:Activity已经可见,已经显示在前台,并开始活动。
(5)onPuase:表示Activity正在停止,正常情况下,onStop会被调用,可做一些非耗时的保存数据操作。
(6)onStop:Activity即将停止,可以做一些稍微重量将的回收工作,不能太耗时。
(7)onDestroy:Activity即将被销毁,这是最后一个生命周期,这里可以做最终的回收工作和资源释放。
1.2、异常情况下,Activity被系统收回或者当前设备Configuration发生改变导致Activity被销毁重建
1、资源相关的系统配置发生改变,导致Activity被杀死或者重新创建
举例说明:当我们的手机横竖屏切换时,Activity会被销毁并重新创建,通过onSaveInstanceState和onRestoreInstanceState方法做数据的保存和恢复,如下图,当然也可以阻止系统重新创建Activity。
2、资源内存不足导致低优先级的Activity被销毁
三类Activity优先等级:高—低
(1)前台Activity—正在用户交互的Activity,优先级最高
(2)可见但非前台Activity—例如弹窗,导致Activity可见,但在后台无法和用户交互
(3)后台Activity—已经被暂停的Activity,如调用了onstop,优先级最低
所以当系统内存不足的情况下,后台Activity是最容易被杀死的,同样通过onSaveInstanceState和onRestoreInstanceState方法做数据的保存和恢复,如果一个后台工作,没有进行四大组件的执行,很容易被杀死,较好的方法就是放在Service中进行,保证进程具有一定优先级,不容易被系统杀死。
当然也可以指定Activity的configChanges属性,如果要指定多个属性,用”|“连接
🔥60、两个Activity之间跳转时必然会执行的是哪几个方法?🔥
两个Activity之间跳转必然会执行的是下面几个方法。
onCreate()//在Activity生命周期开始时调用。
onRestoreInstanceState()//用来恢复UI状态。
onRestart()//当Activity重新启动时调用。
onStart()//当Activity对用户即将可见时调用。
onResume()//当Activity与用户交互时,绘制界面。
onSaveInstanceState()//即将移出栈顶保留UI状态时调用。
onPause()//暂停当前活动Activity,提交持久数据的改变,停止动画或其他占用GPU资源的东西,由于下一个Activity在这个方法返回之前不会resume,所以这个方法的代码执行要快。
onStop()//Activity不再可见时调用。
onDestroy()//Activity销毁栈时被调用的最后一个方法。