一、Service的启动方式
1.采用startService的方式开启服务
生命周期 : onCreate()
--->onStartCommand()
(onStart()
方法已过时) ---> onDestory()
特点 : 一旦服务开启跟调用者(开启者)就没有任何关系了,开启者退出了,开启者挂了,服务再后台长期运行,开启者不能调用服务里面的方法
如果希望能调用
2. 采用bindService的方式开启服务
生命周期 : onCreate()
--->onBind()
--->onunbind()
--->onDestory()
特点 : bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉,绑定者可以调用服务里面的方法
二、BroadcastReceiver注册方式
1.动态注册广播和静态广播的区别
第一种不是常驻型广播,也就是说广播跟随程序的生命周期
第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行
2.发送广播的方式
无序广播 、有序广播 、自定广播
三、进程保活
黑色保活 : 不同的app进程,用广播相互唤醒(包括利用系统提供的广播进行唤醒)
白色保活 : 启动前台Service
灰色保活 : 利用系统的漏洞启动前台Service
黑色保活的原理 : 就是利用不同的app进程使用广播来进行相互唤醒
白色保活的原理 : 调用系统api启动一个前台的Service进程,这样会在系统的通知栏生成一个Notification,用来让用户知道有这样一个app在运行着,哪怕当前的app退到了后台
灰色保活的原理 : 白色保活的基础之上,不会让系统通知栏有一个Notification这样的通知
同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理
private final static int GRAY_SERVICE_ID = 1001;
public static class GrayInnerService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(GRAY_SERVICE_ID, new Notification()); stopForeground(true); stopSelf(); return super.onStartCommand(intent, flags, startId); }
}
四、自定义View
onMeasure()、onLayout()、onDraw()三种方法
onMeasure() : 为了测量控件的距离,有三种模式 : 1.自适应 2.全局布局 3.用户已经设置好距离
五、View的事件分发
六、TCP和UDP的区别 TCP属于传输层,用于数据传输 http属于应用层,用于数据的封装
1.基于连接与无连接;
2.对系统资源的要求(TCP较多,UDP少);
3.UDP程序结构较简单;
4.流模式与数据报模式 ;
5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。
TCP UDP (应用场景 IP电话,实时视频会议)
是否连接 面向连接 面向非连接
传输可靠性 可靠 不可靠
应用场合 传输大量数据 少量数据
速度 慢 快
七、ANR产生的原因以及解决的办法
1.产生ANR的限制条件
a.只有主线程才会发生ANR的问题
b.主线程执行超过5会发生ANR、 主线程BroadcastReceiver的onCreate的方法超过10、主线程执行Service超过20秒没有执行完毕
2.产生ANR的案例:
a.调用Service的join、wait、sleep或者加锁导致主线程等待超时
b.Service的binder数量达到上限
c.大量的数据读写
d.System Servvice 中产生WatchDog的ANR
e.其他的线程的崩溃或者终止导致主线程一直等待
3.解决ANR的问题
a.主线程开启子线程来去执行耗时的操作
b.BroadcastReceiver执行耗时的操作去开启一个Service去后台执行
八、OMM产生的场景:
1.文件的读写、数据库以及网路启用没有及时关闭
2.static的对象的生命周期过长
3.注册广播需要注销广播
4.构造Adapter时,没有使用缓存的convertView
5.非静态内部类默认会持有外部类的引用(非静态内部类和匿名类内部类都会潜在持有它们所属的外部类的引用)
public class MainActivity extends AppCompatActivity {
private static TestResource mResource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mResource == null){
mResource = new TestResource();
} //...
}
class TestResource { //... }
//修改
static Class TestResource
{......} 或者改为单例模式
}
6.静态内部类中使用非静态外部成员变量
7.AsyncTask和Runnable都使用了匿名内部类,那么它们将持有其所在Activity的隐式引用 解决办法:把他们转换为静态内部类
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new MyRunnable()).start();
new MyAsyncTask(this).execute();
}
class MyAsyncTask extends AsyncTask<Void, Void, Void> {
// ...
public MyAsyncTask(Context context) {
// ...
}
@Override
protected Void doInBackground(Void... params) {
// ...
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
// ...
}
}
class MyRunnable implements Runnable {
@Override public void run() {
// ...
}
}
}
九、线程池的理解:
1.总结: Java-五种线程池,四种拒绝策略,三种阻塞队列
2. 五种线程池
threadPool = Executors.newCachedThreadPool();//有缓冲的线程池,线程数 JVM 控制
threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池
threadPool = Executors.newScheduledThreadPool(2);
threadPool = Executors.newSingleThreadExecutor();//单线程的线程池,只有一个线程在工作
threadPool = new ThreadPoolExecutor();//默认线程池,可控制参数比较多
3.四种拒绝策略
RejectedExecutionHandler rejected = null;
rejected = new ThreadPoolExecutor.AbortPolicy();//默认,队列满了丢任务抛出异常
rejected = new ThreadPoolExecutor.DiscardPolicy();//队列满了丢任务不异常
rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早进入队列的任务删,之后再尝试加入队列
rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到线程池失败,那么主线程会自己去执行该任务
4.三种阻塞队列
BlockingQueue<Runnable> workQueue = null;
workQueue = new ArrayBlockingQueue<>(5);//基于数组的先进先出队列,有界
workQueue = new LinkedBlockingQueue<>();//基于链表的先进先出队列,*
workQueue = new SynchronousQueue<>();//无缓冲的等待队列,*
SynchronousQueue——直接提交策略,适用于CachedThreadPool
LinkedBlockingQueue——*队列,适用于FixedThreadPool与SingleThreadExcutor