写在前面
跳槽无非就是钱少了或不爽了,无论怎么样,记住:
不要裸辞!
不要裸辞!
不要裸辞!
为什么呢?
1、裸辞就没有钱拿了,还不如骑驴找马。
2、裸辞之后如果一个月内没有找到工作,那么社保就会断了,除非你自己找渠道交了。
3、裸辞之后真的会很颓废!
当初还在上班的时候就想着,裸辞了,首先花几天时间吧简历完善一下,把知识点恶补一下,然后投简历,面试,妥妥的妥妥。
结果呢?每次裸辞之后都是:
首先躺尸一个星期;
然后用了一个星期才慢吞吞的改完简历;
然后海投,没回复,修改简历;
再次海投,面试,被虐得体无完肤,怀疑人生;
再改简历,再海投,一不小心中了。
当然海投也是有个目标范围的。
如果不是裸辞,那么现在应该还是在公司上班,在完成工作之余,就会逼着自己复习知识点了,起码不会在家堕落。在家不上班就是睡觉、看电影,樯橹灰飞烟灭,所以不要裸辞。
然并卵,我依然裸辞了。请假面试真的很烦。
技术题
Activity相关
Activity是一个单独的界面,从MVC的角度来说一般作为Controller,接收View反馈过来的触摸等事件,转交给Model处理,最后反馈给View渲染。
- 经测试,onPause方法在弹出Dialog的时候是不会被调用的,而在被一个透明的或者Dialog样式的Activity覆盖的时候才会被调用。
在onPause保存临时数据好还是在onStop好
onPause,假如从ActivityA启动B,如果B是透明的,则不会回调A的onStop方法。
如果判断Activity是否已经被销毁
方法一:
activity == null || activity.isDestroyed() || activity.isFinishing()
方法二:
if (Build.VERSION.SDK_INT >= 17) {
return super.isDestroyed();
} else {
return getSupportFragmentManager() != null && getSupportFragmentManager().isDestroyed();
}
Activity的四种启动模式
standard
默认模式,每启动一个新的Activity,都会创建一个新的实例。singleTop
如果需要启动的Activity在栈顶,则直接使用,参数回调到onNewIntent
方法中,不再新建实例。需要配合FLAG_ACTIVITY_CLEAR_TOP
使用。singleTask
如果需要启动的Activity在栈中,则直接使用,参数回到到onNewIntent
方法中,并把此Activity上面的所有Activity清除,需要配合FLAG_ACTIVITY_CLEAR_TOP
使用。singleInstance
在新的任务栈中启动Activity,如果此Activity已经存在,则直接使用,并且此栈有且只有一个Activity。需要配合FLAG_ACTIVITY_NEW_TASK
使用。
如何设置Activity的跳转动画
1、写好动画文件R.anim.enter
、R.anim.exit
2、调用overridePendingTransition
设置动画
public static void start(Activity context) {
Intent starter = new Intent(context, MainActivity.class);
context.startActivity(starter);
context.overridePendingTransition(R.anim.enter, R.anim.exit);
}
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.enter, R.anim.exit);
}
引申:如Activity设置为singleInstance,则应该怎么设置跳转动画?
Service相关
Service是一个没有界面的安卓组件,一般用于后台处理耗时任务。
Service运行在主线程
Service的两种启动模式
1、startService 启动方与Service并没有关联,只有当Service调用stopSelf
或者其它组件调用stopService
的时候服务才会终止。
2、bindService 启动方绑定Service,并且可以通过Binder与之交互,当启动方销毁时,也会自动unbindService,当所有启动方都unbindService之后,Service也就自动销毁了。
BroadcastReceiver相关
广播接收者,可以接收应用自身的广播,和其他应用的广播。也可以用于进程间通讯。
- 不要在onReceive方法中执行耗时操作,也不要开子线程执行
为什么呢?官方文档是这样写的:
However, once your code returns from onReceive(), the BroadcastReceiver is no longer active. The receiver's host process becomes only as important as the other app components that are running in it. If that process hosts only a manifest-declared receiver (a common case for apps that the user has never or not recently interacted with), then upon returning from onReceive(), the system considers its process to be a low-priority process and may kill it to make resources available for other more important processes.
大概意思是onReceive()
执行完毕之后,它所在的进程就会变成低优先级进程,极易被系统杀死。
分两种情况分析一下:
一、收到广播的时候,应用正在运行:
此时如果没有在Manifest中设置了独立进程,则onReceive()
就直接在主进程主线程执行,这里很明显不能执行耗时操作。
二、收到广播的时候,应用没有启动:
这时候系统会启动一个进程去执行onReceive()
,(如果Manifest中没有设置进程名,则进程名为包名),(插一句,所有进程都会创建一个Application实例),当onReceive执行完毕之后,此进程就变成低优先级了,随时有可能被系统杀死,如果你在onReceive里面启动了线程执行耗时任务,那很有可能子线程没执行完毕,进程就被杀死了,进程没了,线程自然就挂了。
那么确实要执行耗时操作呢,怎么办?
方法一:goAsync()
@Override
public void onReceive(final Context context, final Intent intent) {
final PendingResult async = goAsync();
new AsyncTask<String, Integer, String>() {
@Override
protected String doInBackground(String... params) {
// 这里执行一系列耗时操作
async.finish();
return "";
}
}.execute();
}
方法二:schedule a JobService from the receiver using the JobScheduler
ContentProvider相关
主要用于应用间(进程间)数据共享的组件。
Fragment相关
自定义View流程
绘制从根视图
ViewRoot
的performTraversals()
,ViewRoot
的实现类为ViewRootImpl
,performTraversals()
内部会依次调用performMeasure()
、performLayout()
、performDraw()
三种实现方法
1、继承现有的组件,如TextView等,进行拓展。
2、继承ViewGroup,自定义布局。
3、继承View,在onDraw()中描绘。
onMeasure()
-
MeasureSpec
是一个32位的整形数,高2位代表测量模式,分别为UNSPECIFIED
、EXACTLY
、AT_MOST
。 - 调用方法
setMeasureDimension()
设定View的宽高。
onLayout()
- 如果继承自
ViewGroup
,则必须实现此方法。
onDraw()
- 如果继承自
ViewGroup
,默认不会调用onDraw()
,需要设置setWillNotDraw(false)
其它
- 状态保存,
onSaveInstanceState
和onRestoreInstanceState
-
Activity
的onSaveInstanceState
方法会循环调用设置了ID
的View的onSaveInstanceState
LayoutInflater.inflate中的参数attachToRoot有什么用?
public View inflate(int resource, ViewGroup root, boolean attachToRoot)
attachToRoot
从字面理解就是是否绑定到root
上面去了。
1、attachToRoot=true
:则返回的view为root的子view;
2、attachToRoot=false
:则返回的view是个单独的view,传入的root只是提供一些参数给view使用而已。
public View inflate(int resource, ViewGroup root) {
return inflate(resource, root, root != null);
}
那么这里不传入attachToRoot
呢?那就看root是否为空了,如果传入root不为空,则默认绑定到root,作为root的子view返回。
Touch事件分发
说说Android的动画机制
- 逐帧动画(Drawable Animation)
也就是所谓的Frame动画。指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果。
可以通过插入器Interpolator
控制动画的变化速度。
- 视图动画(View Animation)
也就是所谓补间动画。指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有AlphaAnimation
、TranslateAnimation
、ScaleAnimation
、RotateAnimation
四种。
注意:只是在视图层实现了动画效果,并没有真正改变View的属性。
- 属性动画(Property Animation)
属性动画,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。
注意:Android 3.0(API 11)以上才支持。
最常用的类有ObjectAnimator
Dialog的cancel()和dismiss()有什么区别?
-
cancel()
内部调用了dismiss()
-
cancel()
会触发setOnCancelListener
和setOnDismissListener
的回调 -
dismiss()
会触发setOnDismissListener
的回调
P.S. 我不明白cancel存在的意义。
另外,DialogFragment
是没有cancel的。
监听网络变化
ping
内存管理机制
内存大致分为三个区:栈区、堆区、方法区。
栈区
- 每个线程一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用
- 每个栈中的数据(原始类型和对象引用)都是私有的
- 栈分为3个部分:基础类型变量区、执行环境上下文、操作指令区
- 数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失
堆区
- 存储的是对象,每个对象都包含一个与之对应的class
- JVM只有一个堆区被所有线程共享,堆中不存放基本数据类型和对象的引用,只存放对象本身
- 对象由垃圾回收器负责回收,生命周期不确定
方法区
- 静态区,跟堆一样,被所有的线程共享
- 方法区中包含的都是整个程序中永远唯一的元素,如class,静态变量等
大概说说垃圾回收机制
JAVA不允许手动释放内存,只能通过垃圾回收程序不定期对那些不再被引用的对象进行回收。
那么怎么判断哪些对象需要回收?
1、引用计数法
就是给对象添加一个引用计数器,引用对象时+1,引用失效时-1。但是这种方法解决不了对象相互引用的情况。
2、可达性分析法
通过一系列“GCRoots”对象作为起点进行搜索,当GCRoots和一个对象之间没有可达路径,则认为此对象不可用,但是不可用不一定会成为可回收对象。
Android中四种线程池的区别
Android中的进程优先级
前台进程
可见进程
服务进程
后台进程
空进程
进程间通讯
文件共享(Linux支持文件并发写,注意同步)
Messenger
AIDL
编写AIDL文件,定义接口。
编译生成JAVA文件。
定义进程级Service,onBind中返回Interface.Stub()。
onServiceConnected中Interface aidl = Interface.Stub.asInterface(service);
ContentProvider
Socket
RelativeLayout和LinearLayout有什么区别
面向对象编程的三大特性
封装 把同一类事物的共性,包括属性和方法,归到同一个类中,并且隐藏起来,之对外提供特定的方法。
继承 描述一类事物属于另一类事物,比如狗属于动物。在JAVA中只有单继承,没有多继承。JAVA8之后接口支持多继承了。
多态 指一个行为的多种表现形态。比如人要工作,画家的工作是画画,而我们的工作是写代码。
热修复大概原理
把已修复的class文件打包成dex文件,网络传输到用户手机中,利用类加载器把这些类加载到类队列的前面即可。
HTTP协议
【未完待续】
情商题
说说你三五年的规划
如果公司录用我,不管是三年还是五年,首先我都会先把公司的任务做好,然后不断深入研究Android的相关技术,特别是Android源码,了解Android底层原理,以便更好的优化性能,避免一些不必要的奇葩问题,还有就是研究一些新的框架的原理,学习别人的思维。最后就是学习周边语言,比如后台,前端等等。
以上的所有问题的答案都是自己根据经验和百度总结出来的,尽可能的简洁,不一定正确,如有错误,望留言指出。