01:Activity生命周期?
这几乎是个老少咸宜,永远不会过时的问题,而且极有可能是第一个问题。这个问题当然没什么好讲的啦,死记硬背是没什么用的了,关键是理解。本人就曾遇到这个问题的变种问题,问onStart(),与onResume()有什么区别?如果面试官抛出这个问题,是不是有点措手不及。今天又听说有同学遭遇了更变态的问题:什么情况下Activity走了onCreat(),而不走onStart(),这简直就是脑筋急转弯嘛。
知识点链接:http://www.jianshu.com/p/c5604ccd40ea
02:什么情况下,Activity的onNewInstent()方法会执行?Activity的启动模式相关。
当此Activity的实例已经存在,并且此时的启动模式为SingleTask
和SingleInstance
,另外当这个实例位于栈顶,且启动模式为SingleTop
时也会触发onNewInstance()方法。
03:Service生命周期?
这里要注意service有两种启动方式:startService()和bindService()
在Service的生命周期中,常用的方法有:
4个手动调用的方法
startService() //启动服务
stopService() //关闭服务
bindService() //绑定服务
unbindService() //解绑服务```
5个内部自动调用的方法
onCreat() //创建服务
onStartCommand() //开始服务
onDestroy() //销毁服务
onBind() //绑定服务
onUnbind() //解绑服务```
- 手动调用startService()启动服务,自动调用内部方法:onCreate(),onStartCommand(),如果一个Service被startService()多次启动,那么onCreate()也只会调用一次。
- 手动调用stopService()关闭服务,自动调用内部方法:onDestory(),如果一个Service被启动且被绑定,如果在没有解绑的前提下使用stopService()关闭服务是无法停止服务的。
- 手动调用bindService()后,自动调用内部方法:onCreate()、onBind()。
- 手动调用unbindService()后,自动调用内部方法:onUnbind()、onDestory()。
- startService()和stopService()只能开启和关闭Service,无法操作Service,调用者退出后Service仍然存在;bindService()和unbindService()可以操作Service,调用者退出后,Service随着调用者销毁。
Service知识总结
Android activity和service的生命周期对比
Service服务史上最全面解析
04:IntentService深入了解?
IntentService集成与Service,用来处理异步请求。客服端可以通过startService(Intent intent)方法传递请求给IntentService。IntentService在onCreate()函数中通过HandlerThread单独开启一个线程来依次处理所有Intent请求对象所对应的任务(这样以免事务处理阻塞主线程,出现ANR异常)执行完一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service,否则执行下一个Intent请求所对应的任务。
IntentService在处理事务时,还是采用的Handler方式,创建一个名叫ServiceHandler的内部Handler,并把它直接绑定到HandlerThread所对应的子线程。ServiceHandler把处理一个intent所对应的事务都封装到叫做onHandleIntent的虚函数中;因此我们直接实现虚函数onHandleIntent,再在里面根据intent的不同进行不同的事务处理就可以了。另外,IntentService默认实现了onBind()方法,返回值为null.
使用IntentService需要实现的两个方法:
-
构造函数
IntentService的构造函数一定是参数为空的构造函数,然后再在其中调用super("name")这种形式的构造函数。因为Service的实例化是系统来完成的,而且系统是参数为空的构造函数来实例化Service的。 -
实现虚函数onHandleIntent
在里面根据intent的不同进行不同的事务处理。
好处:处理异步请求的时间可以减少些代码的工作量,比较轻松的实现项目的需求。
IntentService实例介绍
首先是myIntentService.java
public class myIntentService extends IntentService {
//------------------必须实现-----------------------------
public myIntentService() {
super("myIntentService");
// 注意构造函数参数为空,这个字符串就是worker thread的名字
}
@Override
protected void onHandleIntent(Intent intent) {
//根据Intent的不同进行不同的事务处理
String taskName = intent.getExtras().getString("taskName");
switch (taskName) {
case "task1":
Log.i("myIntentService", "do task1");
break;
case "task2":
Log.i("myIntentService", "do task2");
break;
default:
break;
}
}
//--------------------用于打印生命周期--------------------
@Override
public void onCreate() {
Log.i("myIntentService", "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("myIntentService", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i("myIntentService", "onDestroy");
super.onDestroy();
}
}
然后记得在Manifest.xml中注册服务
<service android:name=".myIntentService">
<intent-filter >
<action android:name="cn.scu.finch"/>
</intent-filter>
</service>```
最后在Activity中开启服务
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//同一服务只会开启一个worker thread,
//在onHandleIntent函数里依次处理intent请求。
Intent i = new Intent("cn.scu.finch");
Bundle bundle = new Bundle();
bundle.putString("taskName", "task1");
i.putExtras(bundle);
startService(i);
Intent i2 = new Intent("cn.scu.finch");
Bundle bundle2 = new Bundle();
bundle2.putString("taskName", "task2");
i2.putExtras(bundle2);
startService(i2);
startService(i); //多次启动
}
}```
运行结果:
总结:IntentService在onCreate()函数中通过HandlerThread单独开启一个线程来依次处理所有Intent请求对象所对应的任务。通过onStartCommand()传递给服务intent被依次插入到工作队列中。工作队列又把intent逐个发送给onHandleIntent()。
注意:它只有一个工作线程,名字就是构造函数的那个字符串,也就是"myIntentService",我们知道多次开启service,只会调用一次onCreate()方法(创建一个工作线程),多次onStartCommand()方法(用于传入intent通过工作队列再发给onHandleIntent函数做处理)。
05:IntentService与Service的区别
Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。
IntentService它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents(把intent插入到工作队列中)。通过工作队列把intent逐个发送到onHandleIntent()。不需要主动调用stopSelft()来结束服务。因为,所有的intent被处理完毕之后,系统会自动关闭服务。
默认实现的onBind(),返回null。
06:理解Activity,View,Window三者关系
首先用一个比喻来解释三者之间的关系:Activity像一个工匠(控制单元),Windows像窗户(承载模型),View像窗花(显示视图),LayoutInflater像剪刀,Xml配置像剪窗花的图纸。下面介绍:
1.Activity构造的时候会初始化一个Windows,准确的说是PhoneWindow
2.这个PhoneWindow有一个“ViewRoot”,这个“ViewRoot”是一个View或者ViewGroup,是最具初始化的根视图。
3.“ViewRoot”通过addView方法来一个个的添加View。比如TextView,Button等
4.这些View的事件监听,是由WindowManagerService来接受消息,并且回调Activity函数。比如:onClickListener,onKeyDown等
07:Fragment能否不依赖于Activity存在?简析一下Fragment的栈管理。
Fragment不能独立存在的,它必须嵌入到activity中,而且Fragment的生命周期直接受所在的activity的影响。
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();```
transaction只是记录了从一个状态到另一个状态的变化过程,既比如从FragmentA替换到FragmentB的过程,当通过函数transaction.addToBackStack(null)将这个事务添加到回退栈,则会记录这个事务的状态变化过程,如从FragmentA——>FragmentB,当用户点击手机回退键时,因为transaction的状态变化过程被保存,则可以将事务的变化过程还原,既将FragmentB——>FragmentA.
**添加到回退栈的函数:transaction.addToBackStack(null);**
[参考文章: http://blog.csdn.net/u011026329/article/details/47903177](http://blog.csdn.net/u011026329/article/details/47903177)
**08:对于同一个Service,在被start启动之后还能不能被bind?**
是可以的,Service服务基本上分为两种形式:
**启动**
当应用组件(如Activity)通过调用startService()启动服务时,服务既处于“启动”状态。一旦启动,服务既可在后台无限期运行,即使启动服务的组件已被销毁也不会受到影响。已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。例如,它可以通过网络下载或上传文件。操作完成后,服务会自行停止运行。
**绑定**
当应用组件通过bindService()方法绑定到服务时,服务既处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务器进行交互、发送请求、获取结果,甚至是利用进程间通信(IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可以同时绑定到该服务,但全部取消绑定后,该服务既会被销毁。
**虽然本文档是分开概括讨论这两种服务的,但是您的服务可以同时以这两种方式运行,也就是说,它既可以是启动服务(以无限期运行),也允许绑定。问题只是在于您是否实现一组回调方法:onStartCommand()(允许组件启动服务)和onBind()(允许绑定服务)。**
**09:Android中动画**
Android中动画分别有:**帧动画、补间动画、属性动画(Android3.0以后)**
**帧动画**
帧动画是最容易实现的一种动画,这种动画更多的依赖于完善的UI资源,他的原理就是讲一张张单独的图片连贯的进行播放(类似于与动画片的制作过程),从视觉上产生一种动画的效果;有些类似于某些软件制作gif动画的方式。有些代码中,我们还会看到```android:oneshot="false"```,这个oneshot的含义就是动画执行一次(true)还是循环执行多次。
定义代码如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/a_0"
android:duration="100" />
<item
android:drawable="@drawable/a_1"
android:duration="100" />
<item
android:drawable="@drawable/a_2"
android:duration="100" />
</animation-list>```
补间动画
补间动画又可以分为四种形式,分别是:alpha(淡入淡出)、translate(位移)、scale(缩放大小)、rotate(旋转)。
补间动画的实现,一般采用xml文件的形式;代码会更容易书写和阅读,同时也更容易复用。Interpolator主要作用是可以控制动画的变化速率,就是动画进行的快慢节奏。pivot决定了当前动画执行的参考位置。
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<alpha
android:fromAlpha="float"
android:toAlpha="float" />
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float" />
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
<set>
...
</set>
</set>
属性动画
属性动画,顾名思义它是对于对象属性的动画。因此,所有补间动画的内容,都可以通过属性动画实现。属性动画的运行机制是不断地进行操作来实现的,而初始值和结束值之间的动画过度就是由ValueAnimator这个类负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式以及对动画设置监听器等。
10:消息推送的方式
- 方案1:使用极光、友盟、信鸽、个推等第三方推送平台(优点:方便省事,有较为完善的功能解决方案)
-
方案2:使用XMPP协议(Openfire + Spark + Smack)
简介:基于XML协议的通讯协议,前身是Jabber,目前已由IETF国际标准化组织完成了标准化工作。
优点:协议成熟、强大、可扩展性强、目前主要应用到许多聊天系统中,且已有开源的Java版的开发实例androidpn。
缺点:协议比较复杂、冗余(基于XML)、费流量、费电,部署硬件成本高。 -
方案3:使用MQTT协议(更多信息见:http://mqtt.org/)
简介:轻量级、基于代理的“发布/订阅”模式的消息传输协议。
优点:协议简洁、小巧、可扩展性强、省流量、省电,目前已经应用到企业领域(参考:http://mqtt.org/software),且已有C++版的服务端组件rsmb
缺点:够成熟、实现较复杂、服务端组件rsmb不开源,部署硬件成本较高。 -
方案4:使用HTTP轮循方式
简介:定时向HTTP服务器接口(Web Service API)获取最新的消息。
优点:实现简单、可控制强,部署硬件成本低。
缺点:实时性差。
11:Android的数据存储
- 使用SharedPreferences存储数据;它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。只能在同一个包内使用,不能再不同的包之间使用。
- 文件存储数据;文件存储方式是一种比较常用的方法,在Android中读取和写入文件的方法,与Java中实现的I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来实读取设备上的文件。
- SQLite数据库存储数据;SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库。
- 使用ContentProvider存储数据;主要用于应用程序之间进行数据交换,从而能够让其他的应用保存或读取此ContentProvider的各种数据类型。
- 网络存储数据;通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息。
12:Android ANR是什么?如何避免它?
在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框就称为:应用程序无响应(ANR:Application Not Responding)对话框。
用户可以选择让程序继续进行,但是,人们在使用应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要。这样,系统才不会显示ANR给用户。不同的组件发生ANR异常的时间,也是不一样的,如:主线程(Activity,Service)需要5秒,BroadCastReceiver需要10秒。
解决方案:将所有耗时操作,比如:访问网络、Socket通信、查询大量SQL语句、复杂逻辑计算等都放在子线程中去完成,然后通过handler.sendMessage()、runUIThread()、AsyncTask()等方式更新UI。无论如何都要确保用户界面操作的流畅度。如果耗时操作需要让用户等待,那么最好在UI界面上给用户显示进度条。
13:Android 自定义View的绘制流程
1.自定义View的属性
2.在View的构造方法中获取我们自定义的属性
[3.重写onMesure()方法]
4.重写onDraw()方法
注意:3用[]标出来,所以说3,不一定是必须的,当然了大部分的情况下还是需要重写的。
鸿洋大神--自定义View文章汇总
14:Android 自定义View的事件分发机制
Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
Android事件分发机制完全解析,带你从源码的角度彻底理解(下)