【Android】Activity深度、高质量学习

1 生命周期LifeCycle

Activity任务栈

在这里插入图片描述

4种形态

  • Active:栈顶,可见,能和用户交互
  • Paused:被新的/非全屏的Activity挡住时,失去焦点;可见,但不可交互;所有数据都在,正常情况下不会被系统回收,只有在系统内存不足的时候才被回收;
  • Stopped:完全被覆盖,不可见;所有数据都在,在内存足够的时候数据都是被保存着的,在系统内存不足的时候才被回收(同Paused);
  • Killed:系统回收掉。

总结1:

  • Activity是与用户交互的接口(提供一个让用户完成相关操作的窗口);
  • Android系统是通过Activity栈的形式来管理Activity(Activity自身是通过7个回调方法完成自身的创建和销毁);
  • 4种状态:Active/ Paused / Stopped / Killed。

Activity生命周期

在这里插入图片描述

  1. oncreate() 几乎都会重写;初始化变量等
  2. onstart() 被回调时,Activity正在创建中ing;此时Activity处于可见状态,但只在后台,还没在前台显示,所以此时无法和用户交互;
  3. onResume() 被回调时,表明Activity已经处在前台可见,可与用户交互;
  4. onPause() 正在停止Activity,和onResume成对出现;
  5. onStop() 被新的Activity完全覆盖,处于Stop状态,此时Activity不可见,只能在后台运行;
  6. onDestroy() 表示Activity正在被销毁,做资源回收释放工作,与onCreate是一对;
  7. 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通信

  1. Intent / Bundle
  2. 类静态变量
  3. 全局变量(与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通信

  1. Activity将数据传递给fragment
  2. 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,但此处要讲很基本的接口回调

  1. 在fragment中定义一个内部回调接口
  2. fragment的方法onAttach()(当fragment添加到Activity当中时会调用onAttach()方法)
  3. 调用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通信

  1. 绑定服务,利用ServiceConnection类
  2. 简单通信,利用Intent传值
  3. 定义一个callback接口,监听服务中心的进程变化
1. 绑定服务,利用ServiceConnection类
  1. 让Activity继承自ServiceConnection,将自动重写两个方法onServiceConnected()和onServiceDisconnected();
  2. 在Activity中创建一个Binder对象,在onServiceConnected()方法中获取这个Binder对象;
  3. 最后再通过Binder对象的sendData()方法,向Service传递数据,相当于启动服务;
  4. 终止服务是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
  1. 在Activity中创建intent,利用intent.putExtra(“data”, “data”);传值给Service
  2. 启动服务:startService(intent);
  3. 结束服务:stopService(intent);
  4. 注:只能传递简单数据
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接口来监听服务中的进程的变化
  1. Activity继承自ServiceConnection
  2. 在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种启动模式

  1. standard
  2. singleTop
  3. singleTask
  4. singleInstance

1 standard

  1. 在不指定启动模式的前提下,兄默认使用该模式启动Activity
  2. 每次启动一个Activity,都会重新创建一个新的实例
  3. Activity它的onCreate(),onStart(),onResume()方法都会被依次调用

在这里插入图片描述

2 singleTop (栈顶复用)

  1. 当前栈中,已经有该Activity的实例,并且该实例位于栈顶时,才不会重新创建这个Activity的实例,而是复用栈顶的那个Activity实例; 另外,onNewIntent()方法会被调用,Activity会将Intent对象传入回调函数
  2. 当前栈中,已有该Activity的实例,但是该实例不位于栈顶时,和standard一样
  3. 当前栈中,没有该Activity的实例,和standard一样

只有栈顶的Activity才不重建:
在这里插入图片描述
如果不在栈顶,仍会被重建一个实例:
在这里插入图片描述

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
    }

总结

  1. standard是默认的标准启动模式;
  2. standard和singleTop是在原来的任务栈中新建一个Activity实例,不会开启新的任务栈
  3. singleTop应用场景较多:IM对话框,新闻客户端推送

3 singleTask (栈内复用)

  1. 首先会根据taskAffinity去寻找当前是否存在一个对应名字的任务栈
  2. 如果不存在,则会创建一个新的task任务栈
  3. 如果存在,先得到任务栈,查找该任务栈中是否存在该Activity实例:如果存在实例,将该实例上方的所有Activity实例都出栈,并回调该实例的onNewIntent()方法;如果不存在,会新创建一个Activity,入栈。
  4. 使用时,甚至可以将不同的APP中的Activity,设置成相同的taskAffinity,这样,虽然在两个不同的应用中,但这两个不同应用的Activity,会被分配到同一个task任务栈当中。
  5. 应用场景:应用的主界面(主界面可能包括很多子Activity和小的fragment,回到主界面时会自动销毁这些)

在这里插入图片描述

4 singleInstance

  1. 以singleInstance模式启动的Activity具有全局唯一性,就是在整个系统中,只会存在一个这个实例
  2. 如果在启动这样的Activity时,已经存在了一个实例,会把这个实例所在的任务调到前台,不断复用它
  3. 以singleInstance模式启动的Activity具有独占性,独自占有一个任务栈,任务栈中只有它一个实例,被它开启的其他Activity会处在其他任务栈
  4. 应用场景:呼叫来电
    在这里插入图片描述
    使用singleInstance模式时:
    在这里插入图片描述

4 源码解读:startActivity

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值