Android Activity详解

创建一个Activity

创建一个activity至少需要三个文件:

  • Java类
  • XML布局文件
  • 应用的manifest文件

这三个文件关联密切,需要理解每个文件是干啥的。推荐大家使用Android Studio自带的新建Activity向导功能。

在工具栏中右键点击包名选择New–>Activity–>Empty Activity菜单项启动新建activty向导。
在这里插入图片描述

会弹出下面界面,在这个界面中写好你新建Activity的名字。

在这里插入图片描述

新建好之后,Android Studio会给你默认新建这三个文件**:mainfests中注册activity标签、新建Java类、创建该Activity的布局文件**

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkbEkwHg-1616752213990)(C:\Users\sm\Pictures\图片\1-act-main.png)]

Activity的生命周期

​ 内存中有没有activity的实例,用户是否可以看到,是否活跃到前台(等待或者接受用户输入中),可以参看下面的各种状态。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ptvuP8K-1616752187457)(C:\Users\sm\Pictures\图片\表3.1.png)]

​ 用户可以与当前运行状态下的activity交互。设备上有很多应用,但是,任何时候只能有一个activity处于用户能交互的运行状态。

​ 在生命周期图中可以看到,Activity的子类在activity的生命周期状态发生关键性转换时完成某些工作。这些方法通常被称为生命周期回调方法。

​ 如**onCreate(Bundle)**方法。在创建activity实例后,在此实例出现在屏幕上之前,Android操作系统会调用该方法。通常会覆盖onCreate(Bundle)方法,activity可以预处理一下UI相关工作:

  • 实例化组件并将他们放置在屏幕上(调用setContentView(int)方法);
  • 引用已实例化的组件;
  • 为组件设置监听器以处理用户的交互;
  • 访问外部模型数据。

​ 切记,千万不要自己去调用onCreate(Bundle)方法或任何其他activity生命周期方法。为通知activty状态变化,你只需在Activity子类里覆盖这些方法,Android会适时调用他们(看当前用户状态以及系统运行情况)。

Activity()生命周期方法执行顺序

重写Activty()生命周期方法,并打上日志来进行输出

public class CheatActivity extends AppCompatActivity {

    private static final String TAG = "CheatActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate(Bundle) 被调用了");
        setContentView(R.layout.activity_cheat);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart(Bundle) 被调用了");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop(Bundle) 被调用了");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy(Bundle) 被调用了");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause(Bundle) 被调用了");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume(Bundle) 被调用了");
    }
}

输出如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8qXFYRd9-1616752187458)(C:\Users\sm\Pictures\图片\1-生命周期.png)]

打开Activity()

​ 当打开该Activity时,调用顺序为:onCreate-()–>onStart()–>onResume()

点击主屏幕返回时

​ 调用顺序为:onPause(Bundle),onStop(Bundle) 被调用了;可以看到onDestroy()方法没有被调用,说明,返回主屏幕时,Activity()并没有被摧毁,而是被暂停了,当再次打开时,则回复暂停状态

回退Activity()

​ 然后进行回退时,依次调用onPause(), onStop(),onDestroy();表明,点击回退时说明该Activity没用了,可以进行摧毁

设备旋转与Activity()生命周期

​ 当设备旋转时,看看Activity()的生命周期方法是如何执行的?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oGgLUXYO-1616752187459)(C:\Users\sm\Pictures\图片\1-旋转.png)]

​ 设备进行旋转时,系统会销毁当前Activity(),然后创建一个新的Activity()实例。再次旋转设备,又一次见证这个销毁与再创建的过程。

​ 所以你看到日常用到的软件,旋转属性直接被禁止了ovo3

​ 这就出问题了。每次旋转设备,当前的Activity()实例会完全销毁,实例中的存储的一些值就会从内存里被抹掉。旋转后,Android重新创建了Activity的新实例,存储的值被重新初始化。

保存数据以应对设备旋转

​ 如何解决设备旋转数据丢失的问题,两种方法

方法一:直接固定方向,不让他旋转(简单暴力)

方法二:通过保存数据来解决

​ 若设备旋转,需要想个办法保存以前的数据。覆盖Activity的一个方法

protected void omSaveInstanceState(Bundle outState)

​ 该方法通常在onStop()方法之前由系统调用,除非用户按后退键。(按后退建就是告诉Android, activity用完了,该activity就完全从内存中被抹掉,自然,也就没必要重建保存数据了。)

​ 方法**onsaveIntsanceState(Bundle)**的默认实现要求所有activity视图将自身状态数据保存在Bundle对象中。Bundle是存储字符串键与限定类型值之间映射关系(键值对)的一种结构。

​ 如下:

 @Override
public void onCreate(Bundle saveInstanceState){
    super.onCreate(saveInstanceState);
    ...
}

​ 覆盖onCreate(Bundle)方法时,我们实际是在调用activity超类的onCreate(Bundle)方法,并传入收到的bunle。在超类代码实现里,通过取出保存的视图状态数据,activity的视图层级结构得以重建。

启动另一个Activity

启动另一个activity最简单的方式是使用StartActivity()方法:

public void startAcvtvity(Intent intent)

​ sartActivity(Intent intent )并不是一个简单的静态方法,activity调用satrtActivity(Intent intent)方法时,调用请求实际发给了操作系统。

​ 准确的说,调用请求发送给了操作系统的ActivityManager,就是那个Activity超级管理员。然后管理员负责创建Activity实例并调用其onCreate(Bundle)方法,如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rcPCukKh-1616752187460)(C:\Users\sm\Pictures\图片\1-mang.png)]

基于intent的通信

​ intent对象是component用来与操作系统通信的一种媒介工具。常用的组件(component)包括:service、broadcast receiver 以及content provider。

​ intent 是一种多用途的通信工具。Intent类有多个构造方法,却满足不同的使用需求。

​ intent用来告诉我ActivityManager该启动哪个activty,因此可使用以下构造方法:

public Intent(Context packageContext, Class<?> cls)

​ 传入该方法的Class类型参数告诉ActivityManager应该启动哪个activity;Context参数告 诉ActivityManager在哪里可以找到它

比如我想启动CheatActivity

public void btn1(View view) {
    //新建一个activity并开启
    btn_activity_life.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startActivity(new Intent(MainActivity.this,CheatActivity.class));
        }
    });
}

Activity之间数据传递

​ 比如现在有俩个activity:MainActivity与CheatActivity,想要让这两个Activity之间进行数据传递,毕竟如果数据没法传递,那真的是没啥意思。

父activity给子发信息

​ 这个比较简单,直接在inetnt中塞需要发送的信息就好了,比如下面这个,点击按钮之后,发生一个键值对

 public void btn1(View view) {
        //新建一个activity并开启
        btn_activity_life.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, CheatActivity.class);
                intent.putExtra("username", "suian");
	              startActivity(intent);
            }
        });
    }

​ 子activity直接从intent中获取信息就可以了

String username = getIntent().getStringExtra("username");
Log.d(TAG, "username: " + username);

从子activity中获取信息

比如,父activity给子activity发送消息后,需要子activity给一个回执信息,具体实现如下:

先把父activity改造一下

 private static final int REQUEST_CODE_CHEAT = 0;	//确认码
public void btn1(View view) {
        //新建一个activity并开启
        btn_activity_life.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, CheatActivity.class);
                intent.putExtra("username", "suian");
                startActivityForResult(intent,REQUEST_CODE_CHEAT);
            }
        });
    }

给子activity发消息时带个确认码REQUEST_CODE_CHEAT,收到信息后需要进行确认是否是的。

子activity发送消息如下:

Intent resData = new Intent();
resData.putExtra("password", "123456");
setResult(RESULT_OK, resData);

用户回退到父activity时,ActivityManager调用父activity的以下方法:

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) 

该方法的参数来自MainActicity的原始请求代码REQUEST_CODE_CHEAT以及传入setResult(int,Intent )方法的结果代码和intent

父activity接受消息如下:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode != Activity.RESULT_OK) {
        return;
    }
    if (requestCode == REQUEST_CODE_CHEAT) {
        if (data == null) {
            return;
        }
        String password = data.getStringExtra("password");
        Log.d("CheatActivity", "MainActivity接收到:" + password);
    }
}

日志打印如下:当进行回退时,父Activity成功接受到子Activity的信息:password:123456

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MuybkmQb-1616752187461)(C:\Users\sm\Pictures\图片\1-rece.png)]

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汪随安

朝看天色暮看云行也思君坐也思君

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值