1 生命周期LifeCycle
Activity任务栈
4种形态
- Active:栈顶,可见,能和用户交互;
- Paused:被新的/非全屏的Activity挡住时,失去焦点;可见,但不可交互;所有数据都在,正常情况下不会被系统回收,只有在系统内存不足的时候才被回收;
- Stopped:完全被覆盖,不可见;所有数据都在,在内存足够的时候数据都是被保存着的,在系统内存不足的时候才被回收(同Paused);
- Killed:系统回收掉。
总结1:
- Activity是与用户交互的接口(提供一个让用户完成相关操作的窗口);
- Android系统是通过Activity栈的形式来管理Activity(Activity自身是通过7个回调方法完成自身的创建和销毁);
- 4种状态:Active/ Paused / Stopped / Killed。
Activity生命周期
oncreate()
几乎都会重写;初始化变量等onstart()
被回调时,Activity正在创建中ing;此时Activity处于可见状态,但只在后台,还没在前台显示,所以此时无法和用户交互;onResume()
被回调时,表明Activity已经处在前台可见,可与用户交互;onPause()
正在停止Activity,和onResume成对出现;onStop()
被新的Activity完全覆盖,处于Stop状态,此时Activity不可见,只能在后台运行;onDestroy()
表示Activity正在被销毁,做资源回收释放工作,与onCreate是一对;onRestart()
表示Activity正在被重新启动,从onStop()后变为onStart()时,会回调onRestart()。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Activity异常情况下的生命周期
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
当activity异常终止时,会调用onSaveInstanceState()
保存数据。
之后activity重新创建时,系统会调用oncreate()
方法和onRestoreInstanceState()
方法。
因此,可以在oncreate()
方法或者onRestoreInstanceState()
方法中进行数据恢复。
推荐在onRestoreInstanceState()
中进行数据恢复,因为他的Bundle对象不可能为空,只有真的发生异常后恢复时才会调这个函数。onCreate()
的Bundle对象则可能为空,在创建全新Activity的时候就为空。
总结
- Activity正常启动:onCreate----》onStart----》onResume
- 点击back回退:onPause----》onStop----》onDestroy
- 打开新的Activity:onPause----》onStop(存在争议,取决于新Activity是否透明,部分遮盖)
- Activity异常:onSaveInstanceState来保存数据
- Activity重新创建:onRestoreInstanceState恢复数据
2 Activity组件之间的通信
Activity和Activity通信
- Intent / Bundle
- 类静态变量
- 全局变量(与2类似)
在第一个Activity,
首先构建Bundle,将数据存入Bundle;
然后构建Intent对象,将Bundle嵌入Intent对象中;
最后利用Intent开启另外一个Activity。
// 创建用于封装数据的Bundle对象
Bundle bundle = new Bundle();
bundle.putString("name", "yuchen");
bundle.putInt("age", 18);
// 创建Intent
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
// 将bundle对象嵌入Intent中
intent.putExtras(bundle);
startActivity(intent);
第二个Activity:在oncreate中先拿到Intent对象,再从intent对象中,根据key获得参数value。
// intent要用this的getIntent()获取
Intent intent = getIntent();
// 用intent.getXXXExtra("key-name") 或 intent.getXXXExtra("key-name", default-value);
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age", 0);
Activity和Fragment通信
- Activity将数据传递给fragment
- fragment将数据传递给Activity
Activity将数据传递给fragment
- Bundle
- 直接在Activity中定义方法,fragment获取这个Activity,进而获取该Activity的方法
第一种方式:Bundle
在Activity中:
Bundle bundle = new Bundle();
bundle.putString("name", "yuchen");
Fragment fragment = null;
fragment.setArguments(bundle);
在Fragment中:
@Override
public void onStart() {
super.onStart();
if(isAdded()){ // 判断Fragment是否已经依附Activity
String name = getArguments().getString("name");
}
}
第二种方式:直接在Activity中定义方法,fragment获取这个Activity,进而获取该Activity的方法
在Activity中:
public String getName(){
return "yuchen";
}
在Fragment中:
@Override
public void onAttach(@NonNull Activity activity) {
super.onAttach(activity);
String name = ((FragmentActivity1) activity).getName(); // 通过强转成宿主Activity,可获取参数
}
Fragment将数据传给Activity
有很多方法可实现,如广播,如EventBus,但此处要讲很基本的接口回调。
- 在fragment中定义一个内部回调接口
- fragment的方法onAttach()(当fragment添加到Activity当中时会调用onAttach()方法)
- 调用onDetach()方法,这时要把传递进来的Activity对象释放掉(防止内存泄漏)
在fragment中:
// 1 定义了所有Activity必须实现的接口方法
public interface FragmentListener{
void process(String str);
}
// 2.1 定义用来与外部Activity交互,获取到宿主Activity:
private FragmentListener listener;
// 当Fragment被加载到Activity的时候会被回调:
@Override
public void onAttach(@NonNull Activity activity) {
super.onAttach(activity);
if(activity instanceof FragmentListener){
// 2.2 获取到宿主Activity并赋值:
listener = (FragmentListener) activity;
} else{
throw new IllegalArgumentException("activity must implements FragmentListener!");
}
}
//3.1 点击,执行Activity中的回调方法:
@Override
public void onClick(View v) {
listener.process("我是接口"); 往Activity传字符串"我是接口"
}
//把传递进来的Activity对象释放掉:
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
在Activity中:
继承接口,并实现回调方法
public class FragmentActivity1 extends AppCompatActivity implements Fragment1.FragmentListener{
@Override
public void process(String str) {
// TODO
此时拿到了str数据:"我是接口"
}
}
Activity和Service通信
- 绑定服务,利用ServiceConnection类
- 简单通信,利用Intent传值
- 定义一个callback接口,监听服务中心的进程变化
1. 绑定服务,利用ServiceConnection类
- 让Activity继承自ServiceConnection,将自动重写两个方法onServiceConnected()和onServiceDisconnected();
- 在Activity中创建一个Binder对象,在onServiceConnected()方法中获取这个Binder对象;
- 最后再通过Binder对象的
sendData()
方法,向Service传递数据,相当于启动服务; - 终止服务是stopService(intent);
注:这个Binder对象,是在service中定义的内部类
Activity:
public class ServiceActivity2 extends Activity implements View.OnClickListener, ServiceConnection {
private Intent intent;
public MyService2.Binder myBinder = null;//①
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(ServiceActivity2.this, MyService1.class);
findViewById(R.id.btyStartService).setOnClickListener(this);
findViewById(R.id.btyStopService).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btyStartService://启动服务
if (myBinder != null)
myBinder.setData("启动服务了");//③
break;
case R.id.btyStopService://终止服务
stopService(intent);
break;
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService2.Binder) service;//②
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
服务:
public class MyService2 extends Service {
public String data = "服务器正在执行";
public MyService2() {
}
@Nullable
@Override
public IBinder onBind(Intent intent) { 因extends Service而须重写的函数
return new Binder(); 这里new的Binder类,是下面定义的这个内部类
}
public class Binder extends android.os.Binder { 内部Binder类
public void setData(String data) { 里面多加一个方法
MyService2.this.data = data; 更新data值
}
}
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
data = intent.getStringExtra("data");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
2. 简单通信,利用intent
- 在Activity中创建intent,利用intent.putExtra(“data”, “data”);传值给Service
- 启动服务:startService(intent);
- 结束服务:stopService(intent);
- 注:只能传递简单数据
Activity:
public class ServiceActivity1 extends Activity implements View.OnClickListener {
private Intent intent;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(ServiceActivity1.this, MyService1.class);
findViewById(R.id.btyStartService).setOnClickListener(this);
findViewById(R.id.btyStopService).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btyStartService://启动服务
intent.putExtra("data", "data");
startService(intent);
break;
case R.id.btyStopService://终止服务
stopService(intent);
break;
}
}
}
服务:
public class MyService1 extends Service {
public String data = "服务器正在执行";
public MyService1() {
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new Binder(); // import android.os.Binder;
}
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
data = intent.getStringExtra("data");
return super.onStartCommand(intent, flags, startId);
}
}
3. 定义一个callback接口来监听服务中的进程的变化
- Activity继承自ServiceConnection
- 在Activity连接上Service之后,获得Binder对象;通过Binder对象,获得服务本身;然后设置服务中的接口,接口中有个必须重写的方法onDataChange。
Activity:
public class ServiceActivity3 extends Activity implements ServiceConnection {
private Intent intent;
public MyService3.Binder myBinder = null;//①
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(ServiceActivity3.this, MyService3.class);
findViewById(R.id.btyStartService).setOnClickListener(this);
findViewById(R.id.btyStopService).setOnClickListener(this);
}
在主线程中操作UI
private Handler hander = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
textView.setText(msg.getData().getString("data"));
}
};
一旦绑定服务成功就会执行该函数
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
myBinder = (MyService3.Binder) iBinder; 获得Binder对象
通过Binder对象,获得服务本身,然后设置服务中的接口,接口中有个必须重写的方法onDataChange:
myBinder.getMyService().setCallback(new MyService3.Callback(){
@Override
public void onDataChange(String data) {
Message msg = new Message();
Bundle b = new Bundle();
b.putString("data",data);
msg.setData(b);
hander.sendMessage(msg);
}
});
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
服务:
public class MyService3 extends Service {
private static final String TAG = "ActivityTest";
private Callback callback; 定义接口
public String data = "服务器正在执行";
public MyService3() {
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "服务器已绑定");
return new Binder();
}
public class Binder extends android.os.Binder {
public MyService3 getMyService() { 获得当前服务本身
return MyService3.this;
}
}
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
data = intent.getStringExtra("data");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
public void setCallback(Callback callback) { 设置回调接口
this.callback = callback;
}
public Callback getCallback() { 获得回调接口
return callback;
}
public interface Callback { 接口本身,接口中定义必须实现的方法
void onDataChange(String data);
}
}
3 启动模式
4种启动模式
- standard
- singleTop
- singleTask
- singleInstance
1 standard
- 在不指定启动模式的前提下,兄默认使用该模式启动Activity
- 每次启动一个Activity,都会重新创建一个新的实例
- Activity它的onCreate(),onStart(),onResume()方法都会被依次调用
2 singleTop (栈顶复用)
- 当前栈中,已经有该Activity的实例,并且该实例位于栈顶时,才不会重新创建这个Activity的实例,而是复用栈顶的那个Activity实例; 另外,
onNewIntent()
方法会被调用,Activity会将Intent对象传入回调函数 - 当前栈中,已有该Activity的实例,但是该实例不位于栈顶时,和standard一样
- 当前栈中,没有该Activity的实例,和standard一样
只有栈顶的Activity才不重建:
如果不在栈顶,仍会被重建一个实例:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
总结
- standard是默认的标准启动模式;
- standard和singleTop是在原来的任务栈中新建一个Activity实例,不会开启新的任务栈
- singleTop应用场景较多:IM对话框,新闻客户端推送
3 singleTask (栈内复用)
- 首先会根据taskAffinity去寻找当前是否存在一个对应名字的任务栈
- 如果不存在,则会创建一个新的task任务栈
- 如果存在,先得到任务栈,查找该任务栈中是否存在该Activity实例:如果存在实例,将该实例上方的所有Activity实例都出栈,并回调该实例的onNewIntent()方法;如果不存在,会新创建一个Activity,入栈。
- 使用时,甚至可以将不同的APP中的Activity,设置成相同的taskAffinity,这样,虽然在两个不同的应用中,但这两个不同应用的Activity,会被分配到同一个task任务栈当中。
- 应用场景:应用的主界面(主界面可能包括很多子Activity和小的fragment,回到主界面时会自动销毁这些)
4 singleInstance
- 以singleInstance模式启动的Activity具有全局唯一性,就是在整个系统中,只会存在一个这个实例
- 如果在启动这样的Activity时,已经存在了一个实例,会把这个实例所在的任务调到前台,不断复用它
- 以singleInstance模式启动的Activity具有独占性,独自占有一个任务栈,任务栈中只有它一个实例,被它开启的其他Activity会处在其他任务栈
- 应用场景:呼叫来电
使用singleInstance模式时: