2019-06-04

Activity的生命周期

正常的流程:

onCreate():被创建的时候被回调,

onStart():Activity正在启动状态,处于可见但无法交互,但处在后台

onResume():已经在前台可见,可以和用户交互,Activity已经在运行

onPause():Activity正在停止,和onResume()成对出现

onStop():即将停止,或被新的Activity覆盖,Activity不可见,在后台运行

onDestory():Activity正在被销毁,回收和资源的释放,和onCreate()成对

onRestart():Activity正在重新启动不会执行此方法

异常的流程(1、系统发生改变 2、内存不足造成的改变):

只有在Activity异常的情况下才会调用

onSaveInstanceState()是出现异常情况下,会自动调用,来保存当前Activity的信息,(当异常启动的时候,这个方法中的bunlder可能为空,所以要进行非空判断)

onRestoreInstanceState()当Activity重新创建后,自动调用,会通过onSaveInstanceState()的Bundle来保存状态

一旦被异常启动,Bundle()方法不会为空

总结: 1、Activity正常启动:onCreate--onStart--onResume

2、点击Back回退:onPause--onStop--onDestroy

3、打开新的Activity:onPause--onStop

4、Activity异常:onSaveInstanceState来保存数据

5、Activity重新创建:调用onRestoreInstanceState


1.任务栈    

四种形态:

Active:Activity处于栈顶

Paused:可见但不可交互  只是失去了和用户的交互,只有在系统内存不足时才会被回收

Stopped:不可见  被完全覆盖时,只有在系统内存不足时才会被回收

Killed:系统回收掉

(在内存不足的时候,会回收栈底部的Activity)

总结:1、Activity是与用户交互的接口 2、Android系统是通过Activity栈的形式来管理Activity 3、四种形态:Active/Paused/Stopped/Killed

2.四种启动模式

Activity启动模式(当多次启动Activity的时候,系统会创建多个实例,按照先后进出的顺序放入任务栈中,当按下Back键的时候,整个任务栈就会为空,系统就会回收)

1、standard(标准模式)(默认启动模式)

一、在不指定启动模式的前提下,系统默认使用该模式启动每个Activity

二、每次启动一个Activity都会重写创建一个新的实例(消耗资源)

三、Activity在启动的时候,onCreate(),onStart(),onResume()都会依次调用

2、singleTop(栈顶复用) ps:只有在栈顶才可以

一、当前栈中已有该Activity实例并且该实例位于栈顶时

二、当前栈中已有该Activity实例单实该实例不再栈顶时

三、当前栈中不存在该Activity的实例

SingleTop应用场景:

IM对话框

新闻客户端推送

3、singleTask(栈内复用模式),检测的是整个栈中是否存在要启动的Activity

(适合于应用中主界面模式)

一、首先根据taskAffinity去寻找当前是否存在一个对应名字(就是包名)的任务栈

(任务相关性)

二、如果不存在,就重新创建一个Task任务栈

然后创建新的Activity的实例假如栈中

三、如果存在,先得到该任务栈,查找该任务栈中是否存在该Activity实例

存在的话,就会将所有这个实例的Activity都出栈

SingleTask应用场景

应用的主界面

4、singleInstance(单一实例模式)

singleInstance模式下,所有的Activity中只有一个实例,所有Activity会独享一个任务栈

如果有别的Activity使用的话,这两个Activity会使用一个任务栈

应用场景:呼叫来电、

特性:

1、以SingleInstance模式启动的Activity具有全局唯一性

2、如果在启动这样的Activity时,已经存在了一个实例

3、以SingleInstance模式启动的Activity具有独占性



Activity和Activity之间的通信

1、Intent/Bundle

Intent:首先创建Bundle对象,通过Key,Value传递数据

例:

第一个Activity发送

Bundle bundle = new Bundle();

bundle.putString("Key","value");

bundle.putInt("Key2",1);

Intent intent = new Intent(GoActivity.this,ToActivity.class);

intent.putExtras(bundle);

startActivity(intent);

将Bundle对象和Intent建立联系

第二个Activity接收

Intent intent = getIntent();

String key = intent.getStringExtra("Key");

int value = intent.getIntExtra("Key2",1);

第二个Activity中获取第一个Activity传过来的值

2、类静态变量

3、全局变量

Activity和Service之间的通信

1、绑定服务,利用ServiceConnection类

在Activity中实现接口(ServiceConnection)

重写onServiceConnected(绑定成功执行) onServiceDisconnected(进程崩溃执行)这两个方法,这两个方法是在绑定成功和进程崩溃的时候调用

首先在onServiceConnected()中创建Binder对象,利用binder的setData()方法,向Service中传递数据

2、简单通信,利用Intent进行传值

用Intent进行传值,从Activity中传值(putExtras.("key","value"))

在Service中直接用(getIntent)获取

3、定义一个CallBack接口来监听服务中的进程的变化

在Service中定义一个接口

在Activity中,在onServiceConnected()方法中,用binder对象来实现Callback中重写的方法

如果是在子线程中,需要通过Handler来发送到主线程中,

Activity和Fragment之间的通信

Activity将数据传递给Fragment

Bundle:

当用Bundle来传递数据时,用fragment.setArguments(bundle对象名);

在Fragment的时候,用(isAdded()方法)判断是否已经依附在Activity上。

直接在Activity中定义方法:

在第一个Activity中定义构造方法

然后在需要接收数据的Fragment中用onAttach()方法中强转为Activity的类型

Fragment将数据传递给Activity

1、接口回调:

一、在fragment中定义一个内部回调接口//Acticity实现这个接口就行

二、fragment的方法onAttch()//检查fragment中是否实现了内部接口

三、调用onDetach方法,销毁,把Activity传过来的资源释放


Fragment与Service数据通信

Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我们可以利用回调方法

 Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好


Fragment复用

 为什么要复用Fragment?

Activity 在重建的时候会恢复其包含的 FragmentManager ,FragmentManager 又会恢复其管理的 Fragment ,同理 Fragment 也会恢复其包含的 FragmentManager,层层递进,直到全部恢复

复用的好处:

避免显示错乱

避免重复添加

避免多余的内存占用

优化界面启动速度


两种适配器的区别?

(1).FragmentPagerAdapter

适合于 Fragment数量不多的情况。当某个页面不可见时,该页面对应的View可能会被销毁,

但是所有的Fragment都会一直存在于内存中。

如果Fragment需要保存的状态较多时,会导致占用内存较大,

(2).FragmentStatePagerAdapter

适合于Fragment数量较多的情况。当页面不可见时, 对应的Fragment实例可能会被销毁,

但是Fragment的状态会被保存。

因此每个Fragment占用的内存会更少,但是页面切换会引起较大开销。

1、service和线程(Thread)的区别和场景

Thread:程序执行的最小单元,它是分配CPU的基本单位

Thread:生命周期

1.新建new

2.就绪runnable

3.运行running

4.死亡death

5.阻塞block

缺点:无法控制,当Activity被关闭之后,无法控制线程

场景:Thread需要连续不断地每隔一段时间就要连接服务器一次做某种操作

2、如何管理service生命周期

不管如何启动service,oncreate()和ondestory()都会运行

Service运行在后台

Service时Android的一种机制,服务是运行在主线程上的

Service生命周期:

onCreate()通过onCreate开始

onStart()

onDestroy()到onDestory结束

onBind()

onUnbind()

四种情况:

1:StartService:

2:stopService:

3:bindService:

4:unBindService:

3、Service和IntentService的区别

Service:不建议在service中执行耗时操作,否则会报ANR

IntentService:内部有一个工作线程HandlerThread来处理耗时操作


工作机制:继承与Service,

和Service不同点:在onCreate()方法中会创建并启动HandlerThread,还创建了ServiceHandler异步处理类,执行异步任务

当持有IntentService会实现onHandlerIntent方法,

如果后台只有一个任务,执行完onHandlerIntent会进行销毁

如果后台有很多任务,onHandlerIntent会依次执行,直到执行完毕之后,才会销毁(调用StopSelf()结束操作)

总结:

1、IntentService是继承并处理异步请求的一个类

2、内有一个工作线程(也就是HandlerThread)来处理耗时操作

3、IntentService内部则是通过消息的方式发送给HandlerThread的,然后由Handler中的Looper来处理消息

4、启动服务和绑定服务先后次序问题

Android中只会又一个服务

启动服务:service会无限期的运行

先绑定service后启动

绑定服务会转为启动服务状态,不会影响服务运行,之到onStop为止

先启动service后绑定

不会转为绑定的状态,当Activity解除绑定服务的时候,还会按照启动的生命周期在后台运行,之到onStop为止

总结: 1、启动服务的优先级比绑定服务高

2、服务在其托管进程的主线程中执行,主线程

ALDL:

AIDL:是一种android内部进程通信接口描述语言,用过它我们可以定义进程间的通信接口但是记住仅仅只是 android ,换个平台就不是AIDL 了。                                                                                                                    AIDL进程间通讯的原理:

  1.通过编写aidl文件夹来定义进程间通信接口

  2.编译后会自动生成相应的java文件  在各未见中我们可以看到是继承啦一个Binder对象,实现刚刚定义的接口

  3.服务器我们通过一个服务实现里面的Binder方法,将接口的具体实现写在stub中,用ibinder对象传递给客户端

  4.客户端bindservice的时候,服务是实现serviceConnection重写里面的方法,用asinterface的形式将ibinder还原成接口,在调用其接口中的方法来实现通信


Binder机制:

         Android使用Linux内核拥有这非常多的跨进程通信机制,比如Socket,管道。为什么还要binder呢?

性能:Binder相比较于传统的socket/管道通信而言,更加高效,它在IPC时,只需要数据拷贝1次,而传统的socket之类的需要2次;

出于安全上的考虑:传统的进程间通信对于通信双方的身份没有进行严格的验证,只有上层协议才会进行架构,比如说,socket通信时,IP地址是手动填写的,可以进行人为的伪造,而Binder支持通信双方进行身份校验,极大的保障了安全性;

Binder的通信模型:

我们其实可以进程通信的双方一方称为服务端进程,另一方称为客户端进程,我们知道,由于进程隔离的存在,在不进行进程间通信的方式的情况下,客户端进程是无法访问服务端进程的;

对于A和B相当于两个进程,他们要打电话就相当于要进行通信,其中电话基站就想到与Binder驱动,而通信录则相当于其中的一个ServerManager

ServerManager其实就是一个进程,它里面维护了一张表,表里面存储的是向他注册过的进程信息,在通信之初,首先需要有一个进程向驱动申请成为ServerManager,当内核驱动同意之后,这个成为ServerManager的进程就负责管理所有需要通信的进程信息,当客户端进程要访问服务端进程时,服务端进程首先会向ServerManager注册,让ServerManager保存自己的有关信息,当ServerManger保存完毕后,客户端进程就会通过Binder驱动向ServerManger查询服务端进程的信息,ServerManage就会将服务端进程的信息返回给客户端进程,客户端与服务端进程之间就可以通过这些信息,利用Binder驱动来进行通信了;

总结来说,Binder通信机制分三步:

第一步:ServerManager在其内部维护一张表;

第二步:服务端进程向ServerManager注册信息;

第三步:客户端进程向ServerManager取得信息,通过Binder驱动与服务端进程通信;

手写网络框架:理解http网络请求的过程,会存在的问题记录下来,对比okhttp, 为啥要手写?

问题?

扩展性:不能只处理Json/Xml,image,file,video

易用性:解决问题只需要调用一两个API

稳定性,封装性,模块化

和其他框架能不能集成(数据库,网络,MVC,MVVM,资源加载)

对比?

okhttp:

1.占用储存空间

okhttp占用内存空间过大。

2.功能介绍

Square 公司开源的 OkHttp 是一个专注于连接效率的 HTTP 客户端。OkHttp 提供了对 HTTP/2 和 SPDY 的支持,并提供了连接池,GZIP 压缩和 HTTP 响应缓存功能。

3.优点

支持http请求,https请求。

支持文件下载。

使用的是HttpURLConnection,不要担心android版本的变换。(至少目前是都支持的)。

支持get,post请求。

基于Http的文件上传。

加载图片。

4.缺点

比如callback回来是在线程里面, 不能刷新UI,需要我们手动处理。

封装比较麻烦。

Volley

1.占用储存空间

占用内存空间小。

2.功能介绍

Volley是Goole在2013年Google I/O大会上推出了一个新的网络通信框架,它是开源的。

Volley 的特点:特别适合数据量小,通信频繁的网络操作。

3.优点

非常适合进行数据量不大,但通信频繁的网络操作。

内部分装了异步线程。

支持get,post网络请求。

图片下载。

可直接在主线程调用服务端并处理返回结果。

可以取消请求,容易扩展,面向接口编程。

4.缺点

对大文件下载 Volley的表现非常糟糕。

只支持http请求。

为啥手写?

因为在项目中,可以使代码简介明了,做到代码职责划分明显,实现某一块功能不会有多余的代码,而使用别人的开源框架会使我们的代码混乱,代码过多,不简洁,从而导致App的内存占用太大,而且某些开源框架,不能满足我们功能上的需求,而且自己写的更方便自己理解和修改。

你可能感兴趣的:(2019-06-04)