1.数据库的操作类型有哪些,如何导入外部数据库?
把原数据库包括在项目源码的 res/raw
android
系统下数据库应该存放在 /data/data/com.*.*(package name)/
目录下,所以我们需要做的是把已有的数据库传入那个目录下.操作方法是用FileInputStream
读取原数据库,再用FileOutputStream
把读取到的东西写入到那个目录.
2.是否使用过本地广播,和全局广播有什么差别?
因广播数据在本应用范围内传播,不用担心隐私数据泄露的问题。 不用担心别的应用伪造广播,造成安全隐患。 相比在系统内发送全局广播,它更高效。
3.是否使用过intentServer
,作用是什么,AIDL
解决了什么问题?(小米)
生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至 `onStartCommand() `方法的`Intetnt`。
生成一个工作队列来传送Intent对象给你的`onHandleIntent()`方法,同一时刻只传送一个`Intent`对象,这样一来,你就不必担心多线程的问题。
在所有的请求(Intent)都被执行完以后会自动停止服务,所以,你不需要自己去调用`stopSelf()`方法来停止该服务
提供了一个`onBind()`方法的默认实现,它返回null
提供了一个`onStartCommand()`方法的默认实现,它将`Intent`先传送至工作队列,然后从工作队列中每次取出一个传送至`onHandleIntent()`方法,在该方法中对Intent对相应的处理。
AIDL (Android Interface Definition Language)
是一种IDL
语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)
的代码。如果在一个进程中(例如Activity
)要调用另一个进程中(例如Service
)对象的操作,就可以使用AIDL
生成可序列化的参数。 AIDL IPC
机制是面向接口的,像COM
或Corba
一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。
4.Activity、Window、View
三者的差别,fragment
的特点?(360)
Activity
像一个工匠(控制单元),Window
像窗户(承载模型),View
像窗花(显示视图) LayoutInflater
像剪刀,Xml
配置像窗花图纸。
Activity
中调用attach
,创建了一个Window
window
是其子类PhoneWindow
,在attach中创建PhoneWindow
Activity
中调用setContentView(R.layout.xxx)
getWindow().setContentView()
PhoneWindow
中的setContentView
方法ParentView
:作为ViewGroup
的子类,实际是创建的DecorView(
作为FramLayout
的子类)R.layout.xxx
进行填充通过布局填充器进行填充【其中的parent
指的就是DecorView
】ViewGroup
ViewGroup的removeAllView()
,先将所有的view移除掉view:addView()
关于文中所说到的知识点,我都放在GitHub上了,如有需要,可自行查看。
同时我也推荐一下我的Android交流裙Android技术交流,不仅可以免费获取资料,而且还能有一帮大佬为你摆平关于Android的技术问题~
fragment 特点
Fragment
可以作为Activity界面的一部分组成出现;Activity
中同时出现多个Fragment
,并且一个Fragment
也可以在多个Activity
中使用;Activity
运行过程中,可以添加、移除或者替换Fragment
;Fragment
可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主Activity
的生命周期影响。5.描述一次网络请求的流程(新浪)
6.Handler、Thread
和HandlerThread
的差别(小米)
http://blog.csdn.net/guolin_blog/article/details/9991569
http://droidyue.com/blog/2015/11/08/make-use-of-handlerthread/
从Android
中Thread(java.lang.Thread -> java.lang.Object)
描述可以看出,Android
的Thread
没有对Java
的Thread
做任何封装,但是Android
提供了一个继承自Thread
的类HandlerThread(android.os.HandlerThread -> java.lang.Thread)
,这个类对Java
的Thread做了很多便利Android
系统的封装。
android.os.Handler
可以通过Looper
对象实例化,并运行于另外的线程中,Android
提供了让Handler
运行于其它线程的线程实现,也是就HandlerThread
。HandlerThread
对象start后可以获得其Looper
对象,并且使用这个Looper
对象实例Handler
。
7.低版本SDK实现高版本api
(小米)
自己实现或@TargetApi annotation
8.编译安卓系统(百度)
1.创建一个大小写敏感的磁盘镜像文件 2.首先你要安装的就是Xcode 3.
从macports.org
安装MacPorts
工具 4.从MacPorts
安装make
,git
, and GPG packages
5.修改文件标识符限制 6.创建~/bin
/目录 7.安装repo
8.设置repo
可执行权限 9.修改~/bin
/repo
文件将第五行 10.新建目录gingerbread
,并进入该目录 11.执行repoinit
12. reposync
13.设置必要的编译环境-编译 14.利用Eclipse
调试代码
9.launch mode
应用场景(百度、小米、乐视)
standard
,创建一个新的Activity
。
singleTop
,栈顶不是该类型的Activity
,创建一个新的Activity
。否则,onNewIntent
。
singleTask
,回退栈中没有该类型的Activity
,创建Activity
,否则,onNewIntent+ClearTop
。
注意: 1.设置了"singleTask
"启动模式的Activity
,它在启动的时候,会先在系统中查找属性值affinity
等于它的属性值taskAffinity
的Task
存在; 如果存在这样的Task
,它就会在这个Task
中启动,否则就会在新的任务栈中启动。因此, 如果我们想要设置了"singleTask
"启动模式的Activity
在新的任务中启动,就要为它设置一个独立的taskAffinity
属性值。 2.如果设置了"singleTask
"启动模式的Activity
不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity
实例, 如果存在,就会把位于这个Activity
实例上面的Activity
全部结束掉,即最终这个Activity
实例会位于任务的Stack
顶端中。 3.在一个任务栈中只有一个”singleTask
”启动模式的Activity
存在。他的上面可以有其他的Activity
。这点与singleInstance
是有区别的。
singleInstance
,回退栈中,只有这一个Activity,没有其他Activity。
singleTop
适合接收通知启动的内容显示页面。 例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。 singleTask
适合作为程序入口点。 例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent
,并且会清空主界面上面的其他页面。 singleInstance
应用场景:闹铃的响铃界面。 你以前设置了一个闹铃:上午6点。在上午5点58分,你启动了闹铃设置界面,并按 Home
键回桌面;在上午5点59分时,你在微信和朋友聊天; 在6点时,闹铃响了,并且弹出了一个对话框形式的 Activity(名为 AlarmAlertActivity
) 提示你到6点了(这个 Activity 就是以 SingleInstance
加载模式打开的),你按返回键,回到的是微信的聊天界面,这是因为 AlarmAlertActivity
所在的 Task
的栈只有他一个元素, 因此退出之后这个 Task
的栈空了。如果是以 SingleTask
打开AlarmAlertActivity
,那么当闹铃响了的时候,按返回键应该进入闹铃设置界面。
10.touch 事件传递流程(小米)
http://hanhailong.com/2015/09/24/Android-%E4%B8%89%E5%BC%A0%E5%9B%BE%E6%90%9E%E5%AE%9ATouch%E4%BA%8B%E4%BB%B6%E4%BC%A0%E9%80%92%E6%9C%BA%E5%88%B6/
11.view绘制流程(百度)
http://www.codekk.com/blogs/detail/54cfab086c4761e5001b253f
12.多线程(360)
13.线程同步(百度)
http://www.itzhai.com/java-based-notebook-thread-synchronization-problem-solving-synchronization-problems-synchronized-block-synchronized-methods.html#read-more
http://www.juwends.com/tech/android/android-inter-thread-comm.html
单例
public class Singleton{
private volatile static Singleton mSingleton;
private Singleton(){
}
public static Singleton getInstance(){
if(mSingleton == null){\\A
synchronized(Singleton.class){\\C
if(mSingleton == null)
mSingleton = new Singleton();\\B
}
}
return mSingleton;
}
}
14.什么情况导致内存泄漏(美团)
1.资源对象没关闭造成的内存泄漏
描述: 资源性对象比如(Cursor
,File
文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于 java
虚拟机内,还存在于java
虚拟机外。如果我们仅仅是把它的引用设置为null
,而不关闭它们,往往会造成内存泄漏。因为有些资源性对象,比如 SQLiteCurso
r(在析构函数finalize()
,如果我们没有关闭它,它自己会调close()
关闭),如果我们没有关闭它,系统在回收它时也会关闭它,但是这样的效率太低了。因此对于资源性对象在不使用的时候,应该调用它的close()函数,将其关闭掉,然后才置为null
.在我们的程序退出时一定要确保我们的资源性对象已经关闭。 程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor
后没有关闭的情况。如果我们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险。
2.构造Adapter
时,没有使用缓存的convertView
描述: 以构造ListView
的BaseAdapter
为例,在BaseAdapter
中提供了方法: public View getView(int position, ViewconvertView, ViewGroup parent)
来向ListView提供每一个item
所需要的view
对象。初始时ListView
会从BaseAdapter
中根据当前的屏幕布局实例化一定数量的 view
对象,同时ListView
会将这些view
对象缓存起来。当向上滚动ListView
时,原先位于最上面的list item
的view对象会被回收,然后被用来构造新出现的最下面的list item
。这个构造过程就是由getView()
方法完成的,getView()
的第二个形参View convertView
就是被缓存起来的list item的view
对象(初始化时缓存中没有view对象则convertView
是null
)。由此可以看出,如果我们不去使用 convertView
,而是每次都在getView()
中重新实例化一个View
对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。 ListView
回收list item
的view
对象的过程可以查看: android.widget.AbsListView.java
--> voidaddScrapView(View scrap)
方法。 示例代码:
public View getView(int position, ViewconvertView, ViewGroup parent) {
View view = new Xxx(...);
... ...
return view;
}
修正示例代码:
public View getView(int position, ViewconvertView, ViewGroup parent) {
View view = null;
if (convertView != null) {
view = convertView;
populate(view, getItem(position));
...
} else {
view = new Xxx(...);
...
}
return view;
}
3.Bitmap
对象不在使用时调用recycle()
释放内存
描述: 有时我们会手工的操作Bitmap对象,如果一个Bitmap
对象比较占内存,当它不在被使用的时候,可以调用Bitmap.recycle()
方法回收此对象的像素所占用的内存,但这不是必须的,视情况而定。可以看一下代码中的注释:
/** •Free up the memory associated with thisbitmap's pixels, and mark the •bitmap as "dead", meaning itwill throw an exception if getPixels() or •setPixels() is called, and will drawnothing. This operation cannot be •reversed, so it should only be called ifyou are sure there are no •further uses for the bitmap. This is anadvanced call, and normally need •not be called, since the normal GCprocess will free up this memory when •there are no more references to thisbitmap. */
4.试着使用关于application
的context
来替代和activity
相关的context
这是一个很隐晦的内存泄漏的情况。有一种简单的方法来避免context
相关的内存泄漏。最显著地一个是避免context
逃出他自己的范围之外。使用Application context
。这个context
的生存周期和你的应用的生存周期一样长,而不是取决于activity
的生存周期。如果你想保持一个长期生存的对象,并且这个对象需要一个context
,记得使用application
对象。你可以通过调用 Context.getApplicationContext() or Activity.getApplication()
来获得。更多的请看这篇文章如何避免 Android
内存泄漏。
5.注册没取消造成的内存泄漏
一些Android程序可能引用我们的Anroid
程序的对象(比如注册机制)。即使我们的Android
程序已经结束了,但是别的引用程序仍然还有对我们的Android
程序的某个对象的引用,泄漏的内存依然不能被垃圾回收。调用registerReceiver
后未调用unregisterReceiver
。 比如:假设我们希望在锁屏界面(LockScreen)
中,监听系统中的电话服务以获取一些信息(如信号强度等),则可以在LockScreen
中定义一个PhoneStateListener
的对象,同时将它注册到TelephonyManager
服务中。对于LockScreen
对象,当需要显示锁屏界面的时候就会创建一个LockScreen
对象,而当锁屏界面消失的时候LockScreen
对象就会被释放掉。 但是如果在释放 LockScreen
对象的时候忘记取消我们之前注册的PhoneStateListener
对象,则会导致LockScreen
无法被垃圾回收。如果不断的使锁屏界面显示和消失,则最终会由于大量的LockScreen
对象没有办法被回收而引起OutOfMemory
,使得system_process
进程挂掉。 虽然有些系统程序,它本身好像是可以自动取消注册的(当然不及时),但是我们还是应该在我们的程序中明确的取消注册,程序结束时应该把所有的注册都取消掉。
6.集合中对象没清理造成的内存泄漏
我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static
的话,那情况就更严重了。
15.ANR
定位和修正
如果开发机器上出现问题,我们可以通过查看/data/anr/traces.txt
即可,最新的ANR
信息在最开始部分。
主线程被IO操作(从4.0之后网络IO不允许在主线程中)阻塞。
主线程中存在耗时的计算
主线程中错误的操作,比如Thread.wait
或者Thread.sleep
等 Android
系统会监控程序的响应状况,一旦出现下面两种情况,则弹出ANR
对话框
应用在5秒内未响应用户的输入事件(如按键或者触摸)
BroadcastReceiver
未在10秒内完成相关的处理
Service
在特定的时间内无法处理完成 20秒
使用AsyncTask
处理耗时IO操作。
使用Thread
或者HandlerThread
时,调用Process.setThreadPriority(Process.THREAD*PRIORITY*BACKGROUND)
设置优先级,否则仍然会降低程序响应,因为默认Thread
的优先级和主线程相同。
使用Handler
处理工作线程结果,而不是使用Thread.wait()
或者Thread.sleep()
来阻塞主线程。
Activity
的onCreate
和onResume
回调中尽量避免耗时的代码
BroadcastReceiver
中onReceive
代码也要尽量减少耗时,建议使用IntentService
处理。
16.什么情况导致oom
(乐视、美团)
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html
1)使用更加轻量的数据结构 2)Android里面使用Enum 3)Bitmap对象的内存占用 4)更大的图片 5)onDraw方法里面执行对象的创建 6)StringBuilder
17.Android Service
与Activity
之间通信的几种方式
Binder
对象broadcast
(广播)的形式18.Android
各个版本API
的区别
http://blog.csdn.net/lijun952048910/article/details/7980562
19. Android
代码中实现WAP
方式联网(360)
http://blog.csdn.net/asce1885/article/details/7844159
20.如何保证service
在后台不被kill
一、onStartCommand
方法,返回START_STICKY
1、START_STICKY
在运行onStartCommand
后service
进程被kill后,那将保留在开始状态,但是不保留那些传入的intent
。不久后service
就会再次尝试重新创建,因为保留在开始状态,在创建 service
后将保证调用onstartCommand
。如果没有传递任何开始命令给service
,那将获取到null
的intent
。
2、START*NOT*STICKY
在运行onStartCommand
后service
进程被kill
后,并且没有新的intent
传递给它。Service将移出开始状态,并且直到新的明显的方法(startService)
调用才重新创建。因为如果没有传递任何未决定的intent那么service
是不会启动,也就是期间onstartCommand
不会接收到任何null
的intent
。
3、START*REDELIVER*INTENT
在运行onStartCommand
后service
进程被kill后,系统将会再次启动service,并传入最后一个intent
给onstartCommand
。直到调用stopSelf(int)
才停止传递intent
。如果在被kill
后还有未处理好的intent
,那被kill
后服务还是会自动启动。因此onstartCommand
不会接收到任何null
的intent
。
二、提升service
优先级
在AndroidManifest.xml
文件中对于intent-filter
可以通过android:priority = "1000"
这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。
三、提升service
进程优先级
Android
中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android
将进程分为6个等级,它们按优先级顺序由高到低依次是: 1.前台进程( FOREGROUND*APP)
2.可视进程(VISIBLE*APP )
3. 次要服务进程(SECONDARY*SERVER )
4.后台进程 (HIDDEN*APP)
5.内容供应节点(CONTENT*PROVIDER)
6.空进程(EMPTY*APP)
当service
运行在低内存的环境时,将会kill
掉一些存在的进程。因此进程的优先级将会很重要,可以使用startForeground
将service
放到前台状态。这样在低内存时被kill的几率会低一些。
四、onDestroy
方法里重启service
service +broadcast
方式,就是当service
走ondestory
的时候,发送一个自定义的广播,当收到广播的时候,重新启动service
;
五、Application
加上Persistent
属性
六、监听系统广播判断Service
状态
通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service
是否还存活,别忘记加权限啊。
21.Requestlayout,onlayout,onDraw,DrawChild
区别与联系(猎豹)
requestLayout()
方法 :会导致调用measure()
过程 和 layout()
过程 。 说明:只是对View
树重新布局layout
过程包括measure()
和layout()
过程,不会调用draw()
过程,但不会重新绘制任何视图包括该调用者本身。
onLayout()
方法(如果该View
是ViewGroup
对象,需要实现该方法,对每个子视图进行布局)
调用onDraw()
方法绘制视图本身 (每个View
都需要重载该方法,ViewGroup
不需要实现该方法)
drawChild()
去重新回调每个子视图的draw()
方法
22.invalidate()
和postInvalidate()
的区别及使用(百度)
http://blog.csdn.net/mars2639/article/details/6650876
23.Android
动画框架实现原理
Animation
框架定义了透明度,旋转,缩放和位移几种常见的动画,而且控制的是整个View
,实现原理是每次绘制视图时View
所在的ViewGroup
中的drawChild
函数获取该View
的Animation
的Transformation
值,然后调用canvas.concat(transformToApply.getMatrix())
,通过矩阵运算完成动画帧,如果动画没有完成,继续调用invalidate()
函数,启动下次绘制来驱动动画,动画过程中的帧之间间隙时间是绘制函数所消耗的时间,可能会导致动画消耗比较多的CPU
资源,最重要的是,动画改变的只是显示,并不能相应事件。
24.Android
为每个应用程序分配的内存大小是多少?(美团)
android
程序内存一般限制在16M
,也有的是24M
25.Android View
刷新机制(百度、美团)
由ViewRoot
对象的performTraversals()
方法调用draw()
方法发起绘制该View
树,值得注意的是每次发起绘图时,并不会重新绘制每个View
树的视图,而只会重新绘制那些“需要重绘”的视图,View
类内部变量包含了一个标志位DRAWN
,当该视图需要重绘时,就会为该View
添加该标志位。
调用流程 :
mView.draw()
开始绘制,draw()
方法实现的功能如下:
绘制该View
的背景
为显示渐变框做一些准备操作(见5,大多数情况下,不需要改渐变框)
调用onDraw()
方法绘制视图本身 (每个View
都需要重载该方法,ViewGroup
不需要实现该方法)
调用dispatchDraw ()
方法绘制子视图(如果该View
类型不为ViewGroup
,即不包含子视图,不需要重载该方法)值得说明的是,ViewGroup
类已经为我们重写了dispatchDraw ()
的功能实现,应用程序一般不需要重写该方法,但可以重载父类函数实现具体的功能。
26.LinearLayout
对比RelativeLayout
(百度)
1.RelativeLayout
会让子View调用2次onMeasure
,LinearLayout
在有weight
时,也会调用子View
2次onMeasure
2.RelativeLayout
的子View
如果高度和RelativeLayout
不同,则会引发效率问题,当子View
很复杂时,这个问题会更加严重。如果可以,尽量使用padding
代替margin
。 3.在不影响层级深度的情况下,使用LinearLayout
和FrameLayout
而不是RelativeLayout
。 最后再思考一下文章开头那个矛盾的问题,为什么Google
给开发者默认新建了个RelativeLayout
,而自己却在DecorView
中用了个LinearLayout
。因为DecorView
的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout
并不会降低层级深度,所以此时在根节点上用LinearLayout
是效率最高的。而之所以给开发者默认新建了个RelativeLayout
是希望开发者能采用尽量少的View
层级来表达布局以实现性能最优,因为复杂的View
嵌套对性能的影响会更大一些。
27.优化自定义view
(百度、乐视、小米)
为了加速你的view
,对于频繁调用的方法,需要尽量减少不必要的代码。先从onDraw
开始,需要特别注意不应该在这里做内存分配的事情,因为它会导致GC
,从而导致卡顿。在初始化或者动画间隙期间做分配内存的动作。不要在动画正在执行的时候做内存分配的事情。
你还需要尽可能的减少onDraw
被调用的次数,大多数时候导致onDraw
都是因为调用了invalidate().
因此请尽量减少调用invaildate()
的次数。如果可能的话,尽量调用含有4个参数的invalidate()
方法而不是没有参数的invalidate()
。没有参数的invalidate
会强制重绘整个view
。
另外一个非常耗时的操作是请求layout
。任何时候执行requestLayout()
,会使得Android UI
系统去遍历整个View
的层级来计算出每一个view
的大小。如果找到有冲突的值,它会需要重新计算好几次。另外需要尽量保持View
的层级是扁平化的,这样对提高效率很有帮助。
如果你有一个复杂的UI
,你应该考虑写一个自定义的ViewGroup
来执行他的layout
操作。与内置的view
不同,自定义的view
可以使得程序仅仅测量这一部分,这避免了遍历整个view
的层级结构来计算大小。这个PieChart
例子展示了如何继承ViewGroup
作为自定义view
的一部分。PieChart
有子views
,但是它从来不测量它们。而是根据他自身的layout
法则,直接设置它们的大小。
28.ContentProvider
(乐视)
http://blog.csdn.net/coder_pig/article/details/47858489
29.ragment
生命周期
30.volley
解析(美团、乐视)
http://a.codekk.com/detail/Android/grumoon/Volley%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90
31.Android Glide
源码解析
http://www.lightskystreet.com/2015/10/12/glidesourceanalysis/ http://frodoking.github.io/2015/10/10/android-glide/
32.Android
设计模式
http://blog.csdn.net/bboyfeiyu/article/details/44563871
33.架构设计(搜狐)
http://www.tianmaying.com/tutorial/AndroidMVC
34.Android
属性动画特性(乐视、小米)
如果你的需求中只需要对View进行移动、缩放、旋转和淡入淡出操作,那么补间动画确实已经足够健全了。但是很显然,这些功能是不足以覆盖所有的场景的,一旦我们的需求超出了移动、缩放、旋转和淡入淡出这四种对View
的操作,那么补间动画就不能再帮我们忙了,也就是说它在功能和可扩展方面都有相当大的局限性,那么下面我们就来看看补间动画所不能胜任的场景。
注意上面我在介绍补间动画的时候都有使用“对View
进行操作”这样的描述,没错,补间动画是只能够作用在View上的。也就是说,我们可以对一个Button
、TextView
、甚至是LinearLayout
、或者其它任何继承自View
的组件进行动画操作,但是如果我们想要对一个非View
的对象进行动画操作,抱歉,补间动画就帮不上忙了。可能有的朋友会感到不能理解,我怎么会需要对一个非View
的对象进行动画操作呢?这里我举一个简单的例子,比如说我们有一个自定义的View
,在这个View
当中有一个Point
对象用于管理坐标,然后在onDraw()
方法当中就是根据这个Point
对象的坐标值来进行绘制的。也就是说,如果我们可以对Point
对象进行动画操作,那么整个自定义View
的动画效果就有了。显然,补间动画是不具备这个功能的,这是它的第一个缺陷。
然后补间动画还有一个缺陷,就是它只能够实现移动、缩放、旋转和淡入淡出这四种动画操作,那如果我们希望可以对View
的背景色进行动态地改变呢?很遗憾,我们只能靠自己去实现了。说白了,之前的补间动画机制就是使用硬编码的方式来完成的,功能限定死就是这些,基本上没有任何扩展性可言。
最后,补间动画还有一个致命的缺陷,就是它只是改变了View
的显示效果而已,而不会真正去改变View
的属性。什么意思呢?比如说,现在屏幕的左上角有一个按钮,然后我们通过补间动画将它移动到了屏幕的右下角,现在你可以去尝试点击一下这个按钮,点击事件是绝对不会触发的,因为实际上这个按钮还是停留在屏幕的左上角,只不过补间动画将这个按钮绘制到了屏幕的右下角而已。