字节-Android开发面经(一)
共 4018字,需浏览 9分钟
·
2021-05-28 15:46
点击蓝字关注我们,获取更多面经
当我们创建一个handler时,会调用looper的mylooper方法来获得当前线程的looper。如果没有,就会新建一个looper并存放在looper线程池里,保证每个线程都有自己唯一的looper。而looper中持有MessageQueue,当新建一个Message时,通过handler发送时,会将这个Message存放到MessageQueue中,而loop方法一直在循环从messageQueue中取消息,发送的message会被取到,并处理。当发送了多个message时,会遵循先进先出原则维持在messageQueue中。那么,不同线程中发送的message,最终是怎么在主线程中完成处理的呢。要从target的dispatchMessage方法中找答案。
在Android中会维持一个Activity Stack(Activity栈),当一个新的Activity创建时,它就会放到栈顶,这个Activity就处于运行状态。当再有一个新的Activity被创建后,会重新压人栈顶,而之前的Activity则会在这个新的Activity底下,就像枪梭压入子弹一样。而且之前的Activity就会进入后台。
一个Activity实质上有四种状态:
a.运行中(Running/Active):这时Activity位于栈顶,是可见的,并且可以用户交互。
b.暂停(Paused):当Activity失去焦点,不能跟用户交互了,但依然可见,就处于暂停状态。当一个新的非全屏的Activity或者一个透明的Activity放置在栈顶,Activity就处于暂停状态;这个时候Activity的各种数据还被保持着;只有在系统内存在极低的状态下,系统才会自动的去销毁Activity。
c.停止(Stoped):当一个Activity被另一个Activity完全覆盖,或者点击HOME键退入了后台,这时候Activity处于停止状态。这里有些是跟暂停状态相似的:这个时候Activity的各种数据还被保持着;当系统的别的地方需要用到内容时,系统会自动的去销毁Activity。
d.销毁(Detroyed):当我们点击返回键或者系统在内存不够用的情况下就会把Activity从栈里移除销毁,被系统回收,这时候,Activity处于销毁状态。
3.Fragment生命周期执行流程
Fragment创建:setUserVisibleHint()->onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume();
Fragment变为不可见状态(锁屏、回到桌面、被Activity完全覆盖):onPause()->onSaveInstanceState()->onStop();
Fragment变为部分可见状态(打开Dialog样式的Activity):onPause()->onSaveInstanceState();
Fragment由不可见变为活动状态:onStart()->OnResume();
Fragment由部分可见变为活动状态:onResume();
退出应用:onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()(注意退出不会调用onSaveInstanceState方法,因为是人为退出,没有必要再保存数据);
Fragment被回收又重新创建:被回收执行onPause()->onSaveInstanceState()->onStop()->onDestroyView()->onDestroy()->onDetach(),重新创建执行onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()->setUserVisibleHint();
横竖屏切换:与Fragment被回收又重新创建一样。
(1)startService();此种开启方式Service会经历onCreate()--onStart()。若Service还没运行,则先调用onCreate(),然后调用onStart();如果Service已经启动,则只会调用onStart()。一个Service的onStart()方法可以被调用多次。stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。
注:多次调用startService()方法并不会嵌套,所以无论同一个服务被启动了多少次,一旦调用stopService()或者sopSelf(),他都会立刻停止。
(2)bindService():此种启动方式Service会经历onCreate()--onBind(),onBind将会返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的运行状态等。这个时候调用者会和Service绑定在一起,调用者退出的时候,Service就会调用onUnbind--onDestroy退出。
Android中的持久化方式主要有三种:
文件存储
SharedPreference存储
数据库存储
一、文件存储
文件存储是将数据原封不动地保存到文件中,适用于一些简单的额文本数据或者二进制数据。
存数据主要用到了Context的openFileOutput(String fileName,int mode)方法,该方法可以在底层产生一个FileOutputStream对象,然后用BufferedWriter等包装类对其进行包装后,就可以对指定文件进行写数据了。其中的mode是 文件操作模式,有MODE_PRIVATE和MODE_APPEND两种模式,前者是默认的,后者是当文件存在的时候,数据以追加的方式写入文件。
当在一个Context调用该方法时,会在 data/data/工程包名/files 目录下发现保存刚刚数据的文件。
二、SharedPreference存储
SharedPreferences是用 键值对 的方式存储数据的,并且保存的当保存一条数据的时候,需要给这条数据提供一个对应的key,然后在读取该数据的时候通过该key读取。
1、存数据到SharedPreferences中
2、利用SharedPreferences从文件中读取数据
三、SQLite存储
SQLite是Android中内置的一款轻量级的关系型数据库,它的运算速度非常快,占用资源少。Android中提供了一个SQLiteOpenHelper帮助抽象类,借助这个类可以对数据库进行创建和升级。利用SQLiteOpenHelper中的getReadableDatabase()和getWritableDatabase()方法可以获取对数据库进行读和写的对象。
HashMap 是基于哈希表的Map 接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null 值和null 键(允许一个null键,HashTable不允许entry的键或者值为空)。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash值 判断当前元素存放的位置(这里的 n 指的是数组的长度)。如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖;不相同就通过拉链法解决冲突。
所谓 “拉链法” 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。
HashMap 底层数据结构为 Node 类型数组,Node 类型为 HashMap 的内部类,数据结构为链表。当新建一个HashMap 的时候,就会初始化一个数组。
更多面经
扫描二维码
获取更多面经
扶摇就业