各种面试题-虐虐虐

各种面试问题来的更猛烈些吧

不分种类不分题型就是做

不需要答案就是看题就是做

1. JAVA内存空间:方法区、堆、栈?
1. 所有对象实例都是在Java堆上分配内存
2. 方法区用于存放ClassLoader加载的类的相关信息,包括类、静态变量和常量,String常量池也在方法区内。
3. Java栈存放方法调用时的局部变量、方法操作、方法出口与方法执行的相关信息,无限递归调用会撑爆Java栈。

2、TCP、UDP区别?
1. TCP是传输控制协议,面向字节流,提供拥塞控制功能;UDP是用户数据报协议,面向报文,尽最大努力交付数据;
2. TCP是面向连接的协议,UDP是面向非连接的协议。
3. TCP是传输可靠型协议,UDP是传输不可靠型协议。
4. TCP的速度较慢,UDP的速度较快。

3、TCP为什么断开连接要四次握手?

TCP是全双工的,每一个方向都必须单独进行开关,所以需要四次握手。而建立连接时发起者A的两个方向是默认打开的,B可以省去一个通知A打开的请求,所以只需要三次握手。

4、HashMap和HashTable的区别?

5、SoftReference和WeakReference的区别?

6、Java虚拟机GC的原理?

  1. JVM的GC采用根搜索算法。
  2. GC Roots一般有四种:栈帧的本地变量表中引用的对象,方法区中的静态成员,方法区中的常量引用的对象(final全局变量),本地方法栈JNI方法引用的对象。
  3. 现代GC回收算法主要有三种:标记-清除算法,复制算法和标记-整理算法。
  4. 标记清除算法缺点是效率比较低,容易出现内存碎片,一般很少用到。
  5. 复制算法缺点是浪费内存多,不适用于大对象和存活时间长的对象,一般用于新生代对象的GC。
  6. 标记整理算法克服了内存碎片,但缺点仍是效率不高,一般用于老年代对象的GC。
  7. HotSpot虚拟机默认Eden和Survivor的比例是8比1,老年代使用标记整理算法,新生代使用复制算法。
  8. Survivor空间不够时大对象会直接进入老年代。
  9. 当一个对象不可达时会调用finalize()方法,但是仅调用一次。

7、如何理解String的不变性?

  1. 所有在编译期间确定的字符串都会在常量池中。
  2. 所谓的不变性是指引用的对象实例的是不可以改变的,但是可以改变引用地址,所以通过改变引用地址就可以改变值了。
  3. new String(“xxx”)会在堆中创建对象。
  4. string.intern()会根据字符串内容去常量池中寻找并返回相同内容的字符串,如果没有则先创建。

8、String为什么要设计成不变的?
1. 字符串不变时,字符串池才有可能实现,运行时能节约很多堆空间。
2. 字符串不变,就不用考虑多线程同步问题,是线程安全的。
3. 类加载器要用到字符串,字符串不变性提供了安全性,保证正确的类被加载。
4. 字符串不变hashcode就能被缓存,作为HashMap的键要比其他对象速度快。

9、触摸事件的分发?

  1. 触摸事件的处理涉及三个方法:dispatchTouchEvent()、onInterceptEvent()、onTouchEvent()
  2. 从Activity的dispatch开始传递,如果没有拦截,则一直传递到子view。
  3. 如果子View没有消费事件,事件会向上传递,这时父Group才可以消费事件。
  4. 如果子View没有消费DOWN事件(没有返回 true),后续事件都不会再传递进来,直到下一次DOWN。
  5. OnTouchListener的处理优先级高于onTouchEvent()

10、handler的send和post的区别?

到了这里,我们发现貌似这玩意也就是转了一圈又调用了线程的run而已么,那么这又有什么用呢。
如果我们给handler传入的是一个message,那么最后会调用我们的handler的handleMessage(Message)方法,然后我们再去判断最后再去处理
,但是我们用runnable可以直接传入如何操作的对象,不需要再接收到消息后再去判断message的what然后选择做什么操作,从代码清晰的角度,
我也觉得这样子会比在判断一遍要清晰,容易理解很多。

  1. post和sendMessage本质上是没有区别的,只是实际用法中有一点差别
  2. post也没有独特的作用,post本质上还是用sendMessage实现的,post只是一中更方便的用法而已

11、Serializable和Parcelable的区别?

  1. S是Java的序列化方案,P是Android的。在使用内存的时候,Parcelable 类比Serializable性能高,所以推荐使用Parcelable类。
  2. S在序列化的时候会产生大量的临时变量,导致频繁GC,P则不会。因此在内存中使用时(如网络中传递或进程间传递)推荐使用P。
  3. P被设计为IPC通信数据序列化方案,不适用于保存在磁盘上,此时应用S。
  4. S只需要继承Serializable接口即可,P则需要重写writeToParcel方法、重写describeContents方法、实例化Parcelable.Creator。

12、一个Activity启动另外一个Activity并返回的生命周期调用?

  1. A.onCreate()
  2. A.onStart()
  3. A.onResume()
  4. 启动B
  5. A.onPause()
  6. B.onCreate()
  7. B.onStart()
  8. B.onResume()
  9. A.onStop()
  10. 返回A
  11. B.onPause()
  12. A.onRestart()
  13. A.onStart()
  14. A.onResume()
  15. B.onStop()
  16. B.onDestory()

13、startService和bindService的区别?

  1. startService启动的Service在调用者自己退出而没有调用stopService时会继续在后台运行。
  2. bindService启动的Service生命周期会和调用者绑定,调用者退出时Service也会调用unBind()->onDestory()退出。
  3. 先调用startService再调用bindService时Service也只会走一遍生命周期。
  4. 除了startService和bindService,Service的生命周期只有三个方法:onCreate()、onStartCommand()、onDestoty()。

14、Android系统是如何保证一个线程只有一个Looper的?

Looper.prepare()使用了ThreadLocal来保证一个线程只有一个Looper。

ThreadLocal实现了线程本地存储。所有线程共享同一个ThreadLocal对象,但不同线程仅能访问与其线程相关联的值,一个线程修改ThreadLocal对象对其他线程没有影响。

ThreadLocal为编写多线程并发程序提供了一个新的思路。如下图所示,我们可以将ThreadLocal理解为一块存储区,将这一大块存储区分割为多块小的存储区,每一个线程拥有一块属于自己的存储区,那么对自己的存储区操作就不会影响其他线程。对于ThreadLocal,则每一小块存储区中就保存了与特定线程关联的Looper。

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

15、 Android中为什么主线程不会因为Looper.loop()方法造成阻塞?

参考: http://blog.csdn.net/u013435893/article/details/50903082

16、什么是ViewStub?

  1. ViewStub是一个轻量级的View,用于延迟加载布局和视图
  2. 它不可见时不占布局位置、所占资源非常少。当可见时或调用ViewStub.inflate时它所指向的布局才会初始化
  3. ViewStub只能被inflate一次
  4. ViewStub只能用来inflate一个布局,不能inflate一个具体的View

17、如何调试ANR?

  1. DDMS输出的LOG可以判断ANR发生在哪个类,但无法确定在类中哪个位置
  2. 在/data/anr/traces.txt文件中保存了ANR发生时的代码调用栈,可以跟踪到发生ANR的所有代码段
  3. adb pull 来pull traces文件到电脑上

18、Activity的启动模式

19、HTTP报文头是怎样的?

请求行、请求头部、空行、请求数据

状态行、消息包头、空行、相应数据

20、HTTP状态码有哪些?

200 OK:客户端请求成功。
400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
403 Forbidden:服务器收到请求,但是拒绝提供服务。
404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
500 Internal Server Error:服务器发生不可预期的错误。
503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常,举个例子:HTTP/1.1 200 OK(CRLF)。

21、Java创建对象的过程?

检测类是否被加载没有加载的先加载→为新生对象分配内存→将分配到的内存空间都初始化为零值→对对象进行必要的设置→执行方法把对象进行初始化

22、并发和并行的区别?

23、进程和线程的区别?

24、Android进程间通信方法?

  1. Bundle
  2. 文件共享
  3. Messenger
  4. AIDL
  5. ContenProvider
  6. Socket

25、线程间如何通信?

由于多线程共享地址空间和数据空间,所以多个线程间的通信是一个线程的数据可以直接提供给其他线程使用,而不必通过操作系统。
所以线程间通信和同步的方式主要有锁、信号、信号量

Android线程间通信:AsyncTask机制、Handler、共享内存

26、单例模式?饿汉子懒汉子

27、Activity生命周期,异常退出恢复数据,启动模式?

28、静态内部类与非静态内部类、匿名类的区别?

首先我们知道一个类一旦被定义为静态的,那么这个类一定是内部类,所以我们如果想定义一个内部类,当然可以是静态的也可以是非静态的,

所谓匿名类是一种特殊的内部类,它是在一个表达式内部包含一个完整的类定义,常见的匿名类有监听器,并且匿名类只在该表达式内部有效

  1. 静态内部类可以有静态成员(方法、属性),而非静态内部类则不能有静态成员(方法、属性)
  2. 静态内部类只能够访问外部的静态成员和静态方法,而非静态内部类则可以访问外部类的所有成员(方法、属性)
  3. 实例化一个非静态内部类的方法:
//先生成一个外部类对象实例
OutClassTest oc1 = new OutClassTest();
//通过外部类的对象实力生成内部类对象
OutClassTest.InnerClass no_static_inner = oc1.new.InnerClass();

4、实例化一个静态内部类的方法:

//不依赖外部类的实例,直接实例化内部类对象:
OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();

5、调用内部静态类的方法或者静态变量,通过类名直接调用

OutClassTest.InnerStaticClass.static_value
OutClassTest.InnerStaticClass.getMessage

29、ListView优化?

  1. convertView的使用,主要优化加载布局问题
  2. 内部类ViewHolder的使用。
  3. 分批加载

30、二叉树遍历(前序、中序、后序、递归非递归)

31、okhttp

32、Android优化

参考:http://www.jianshu.com/p/f7006ab64da7

布局优化、绘制优化、内存泄漏优化、响应速度优化、ListView优化、Bitmap优化、线程优化。

33、hashmap原理

34、事件冲突

外部拦截和内部拦截

35、dp px关系口头换算?

px = dp * (dpi / 160)。

dp也就是dip:device independent pixels(设备独立像素)。

dp是一种与密度无关的像素单位,在每英寸160点的屏幕上,1dp = 1px。

px(像素):屏幕上的点。

36、线程池的优点?

线程:进程中负责程序执行的执行单元。一个进程中至少有一个线程。

多线程:解决多任务同时执行的需求,合理使用CPU资源。多线程的运行是根据CPU切换完成,如何切换由CPU决定,因此多线程运行具有不确定性。

线程池:基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。

1)避免线程的创建和销毁带来的性能开销。

2)避免大量的线程间因互相抢占系统资源导致的阻塞现象。

3}能够对线程进行简单的管理并提供定时执行、间隔执行等功能。

37、wait 和 sleep的区别?

作者:孙立伟
链接:https://www.zhihu.com/question/23328075/answer/24228413
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 首先,要记住这个差别,“sleep是Thread类的方法,wait是Object类中定义的方法”。尽管这两个方法都会影响线程的执行行为,但是本质上是有区别的。
  • Thread.sleep不会导致锁行为的改变,如果当前线程是拥有锁的,那么Thread.sleep不会让线程释放锁。如果能够帮助你记忆的话,可以简单认为和锁相关的方法都定义在Object类中,因此调用Thread.sleep是不会影响锁的相关行为。
  • Thread.sleep和Object.wait都会暂停当前的线程,对于CPU资源来说,不管是哪种方式暂停的线程,都表示它暂时不再需要CPU的执行时间。OS会将执行时间分配给其它线程。区别是,调用wait后,需要别的线程执行notify/notifyAll才能够重新获得CPU执行时间。
  • 线程的状态参考 Thread.State的定义。新创建的但是没有执行(还没有调用start())的线程处于“就绪”,或者说Thread.State.NEW状态。
  • Thread.State.BLOCKED(阻塞)表示线程正在获取锁时,因为锁不能获取到而被迫暂停执行下面的指令,一直等到这个锁被别的线程释放。BLOCKED状态下线程,OS调度机制需要决定下一个能够获取锁的线程是哪个,这种情况下,就是产生锁的争用,无论如何这都是很耗时的操作。

38、MVC 和 MVP

MVC中,用户的请求首先会到达Controller,由Controller从Model获取数据,选择合适的View,把处理结果呈现到View上;

MVP中,用户的请求首先会到达View,View传递请求到特定的Presenter,Presenter从Model中获取数据后,再把处理结果通过接口传递到View.

那么该如何解决activity的问题呢?目前常见的MVP在Android里的实践有两种解决方案:

  1. 直接将Activity看作View,让它只承担View的责任。

  2. 将Activity看作一个MVP三者以外的一个Controller,只控制生命周期。

39、Android UI绘制原理

mearsure、 layout、draw

40、怎么做断点续传?

参考:http://blog.csdn.net/lu1024188315/article/details/51803471

对于断点续传,关键点是两个:

  1. 终端知道当前的文件和上一次加载的文件是不是内容发生了变化,如果有变化,需要重新从offset 0 的位置开始下载

  2. 终端记录好上次成功下载到的offset,告诉server端,server端支持从特定的offset 开始吐数据

GET /down.zip HTTP/1.0 
User-Agent: NetFox 
RANGE: bytes=2000070-  //新增这一行即可。这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 

41、JAVA父类、子类6种构造方法的顺序?

静态优先执行,父类优先于子类执行。静态代码块是在JVM加载类的时候执行的,而且静态代码块执行且仅执行一次

1、父类静态代码块

2、子类静态代码块

3、父类非静态代码块

4、父类构造函数

5、子类非静态代码块

6、子类构造函数

42、Android中 asset和resource文件的区别?

1.两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。

2、res/raw中的文件会被映射到R.Java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.Java中,访问的时候需要AssetManager类。

3、res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹

*读取文件资源:

1.读取res/raw下的文件资源,通过以下方式获取输入流来进行写操作

InputStream is = getResources().openRawResource(R.id.filename);

2.读取assets下的文件资源,通过以下方式获取输入流来进行写操作

AssetManager am = null;  
am = getAssets();  
InputStream is = am.open("filename");

43、Fragment的使用?

首先在一个Activity的布局中添加Fragment的布局,

然后新建一个自定义的Fragment类,继承自Fragment。重写其onCreateView方法加载我们自定义的view。

之后可以在MainActivity中动态添加Fragment。主要分为5步:

(1) 创建待添加的Fragment实例

(2) 获取到FragmentManager,getFragmentManager

(3) 开启一个事物,beginTransaction

(4) 向容器中添加Fragment,一般用replace

(5) 提交事物,comit

44、传输层协议?

TCP、UDP。

45、 介绍一下TCP流量控制、拥塞控制、

参考:http://blog.csdn.net/sicofield/article/details/9708383

参考:http://www.cnblogs.com/newwy/p/3254029.html

流量控制

所谓流量控制就是让发送发送速率不要过快,让接收方来得及接收。利用滑动窗口机制就可以实施流量控制。

原理这就是运用TCP报文段中的窗口大小字段来控制,发送方的发送窗口不可以大于接收方发回的窗口大小。

考虑一种特殊的情况,就是接收方若没有缓存足够使用,就会发送零窗口大小的报文,此时发送放将发送窗口设置为0,停止发送数据。之后接收方有足够的缓存,发送了非零窗口大小的报文,但是这个报文在中途丢失的,那么发送方的发送窗口就一直为零导致死锁。

解决这个问题,TCP为每一个连接设置一个持续计时器(persistence timer)。只要TCP的一方收到对方的零窗口通知,就启动该计时器,周期性的发送一个零窗口探测报文段。对方就在确认这个报文的时候给出现在的窗口大小(注意:TCP规定,即使设置为零窗口,也必须接收以下几种报文段:零窗口探测报文段、确认报文段和携带紧急数据的报文段)。

拥塞控制

在某段时间,若对网络中的某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变化,这种情况叫做拥塞。

所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能承受现有的网络负荷。

流量控制往往指的是点对点通信量的控制,是个端到端的问题。流量控制所要做的就是控制发送端发送数据的速率,以便使接收端来得及接受。

因特网建议标准RFC2581定义了进行拥塞控制的四种算法,即慢开始(Slow-start),拥塞避免(Congestion Avoidance)快重传(Fast Restrangsmit)和快回复(Fast Recovery)

慢开始和拥塞避免

发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口。

慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。

快重传和快恢复

快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。

一条TCP连接有时会因等待重传计时器的超时而空闲较长的时间,慢开始和拥塞避免无法很好的解决这类问题,因此提出了快重传和快恢复的拥塞控制方法。

快重传算法并非取消了重传机制,只是在某些情况下更早的重传丢失的报文段(如果当发送端接收到三个重复的确认ACK时,则断定分组丢失,立即重传丢失的报文段,而不必等待重传计时器超时)。慢开始算法只是在TCP建立时才使用

46、TCP需要三次握手,两次行不行?

三次握手的关键在于双方都需要确认自己的发信和收信功能正常,收信功能通过接受对方信息得到确认,发信功能需要发出信息 ->对方回复信息得到确认。

需要第三次握手的原因在于Server端在第二次握手(发出信息)后并不知道对方是否能接收、己方的发送功能是否正常。但此时数据的单向通道已经建立,对于CLient来说,已经确认了Server端可以接受信号,因此可以单向给Server发送数据了。

采用三次握手是为了防止失效的连接请求报文段突然又传送到主机B,因而产生错误。失效的连接请求报文段是指:主机A发出的连接请求没有收到主机B的确认,于是经过一段时间后,主机A又重新向主机B发送连接请求,且建立成功,顺序完成数据传输。考虑这样一种特殊情况,主机A第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟达到主机B,主机B以为是主机A又发起的新连接,于是主机B同意连接,并向主机A发回确认,但是此时主机A根本不会理会,主机B就一直在等待主机A发送数据,导致主机B的资源浪费。

47、TIME_WAIT状态什么情况下会产生?

通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态

客户端主动关闭连接时,会发送最后一个ack后,然后会进入TIME_WAIT状态,再停留2个MSL时间(后有MSL的解释),进入CLOSED状态。

1)可靠地实现TCP全双工连接的终止

TCP协议在关闭连接的四次握手过程中,最终的ACK是由主动关闭连接的一端(后面统称A端)发出的,如果这个ACK丢失,对方(后面统称B端)将重发出最终的FIN,因此A端必须维护状态信息(TIME_WAIT)允许它重发最终的ACK。如果A端不维持TIME_WAIT状态,而是处于CLOSED 状态,那么A端将响应RST分节,B端收到后将此分节解释成一个错误(在Java中会抛出connection reset的SocketException)。

因而,要实现TCP全双工连接的正常终止,必须处理终止过程中四个分节任何一个分节的丢失情况,主动关闭连接的A端必须维持TIME_WAIT状态 。

2)允许老的重复分节在网络中消逝

TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个迟到的迷途分节到达时可能会引起问题。在关闭“前一个连接”之后,马上又重新建立起一个相同的IP和端口之间的“新连接”,“前一个连接”的迷途重复分组在“前一个连接”终止后到达,而被“新连接”收到了。为了避免这个情况,TCP协议不允许处于TIME_WAIT状态的连接启动一个新的可用连接,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个新TCP连接的时候,来自旧连接重复分组已经在网络中消逝。

48、Android自定义控件?

参考: http://www.cnblogs.com/0616–ataozhijia/p/4003380.html

开发自定义控件的步骤:

1、了解View的工作原理

2、 编写继承自View的子类

3、 为自定义View类增加属性

4、 绘制控件

5、 响应用户消息

6 、自定义回调函数

49、自定义View的几种方式?

自定义控件的实现有三种方式,分别是:组合控件、自绘控件和继承控件。

一)组合控件

组合控件,顾名思义就是将一些小的控件组合起来形成一个新的控件,这些小的控件多是系统自带的控件。比如很多应用中普遍使用的标题栏控件,其实用的就是组合控件

二)自绘控件

自绘控件的内容都是自己绘制出来的,在View的onDraw方法中完成绘制。

三)继承控件

就是继承已有的控件,创建新控件,保留继承的父控件的特性,并且还可以引入新特性。

50、为什么要序列化?

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为对象。

把对象转换为字节序列的过程称为对象的序列化。

把字节序列恢复为对象的过程称为对象的反序列化。

说的再直接点,序列化的目的就是为了跨进程传递格式化数据

51、Service和IntentService的区别

Android中的Service是用于后台服务的,当应用程序被挂到后台的时候,问了保证应用某些组件仍然可以工作而引入了Service这个概念,那么这里面要强调的是Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。

那么我们当我们编写的耗时逻辑,不得不被service来管理的时候,就需要引入IntentService,IntentService是继承Service的,那么它包含了Service的全部特性,当然也包含service的生命周期,那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去你执行你的耗时操作。

52、Android动画的几种方式

1、View Animation(视图动画)

视图动画,也叫Tween(补间)动画可以在一个视图容器内执行一系列简单变换(位置、大小、旋转、透明度)。譬如,如果你有一个TextView对象,您可以移动、旋转、缩放、透明度设置其文本,当然,如果它有一个背景图像,背景图像会随着文本变化。

2、Drawable Animation(Drawable动画)

Drawable动画其实就是Frame动画(帧动画),它允许你实现像播放幻灯片一样的效果,这种动画的实质其实是Drawable,所以这种动画的XML定义方式文件一般放在res/drawable/目录下。

3、Property Animation(属性动画)

属性动画,这个是在Android 3.0中才引进的,它可以直接更改我们对象的属性。在上面提到的Tween Animation中,只是更改View的绘画效果而View的真实属性是不改变的。假设你用Tween动画将一个Button从左边移到右边,无论你怎么点击移动后的Button,他都没有反应。而当你点击移动前Button的位置时才有反应,因为Button的位置属性木有改变。而Property Animation则可以直接改变View对象的属性值,这样可以让我们少做一些处理工作,提高效率与代码的可读性。

你可能感兴趣的:(JAVA)