四大组件之Activity

来源:互联网 发布:淘宝买苹果游戏可靠吗 编辑:程序博客网 时间:2024/06/02 07:13

一、Activity生命周期
Activity 有三个状态:

当它在屏幕前台时,响应用户操作的Activity, 它是激活或运行状态.

当它上面有另外一个Activity,使它失去了焦点但仍然对用户可见时(如右图), 它处于暂停状态.

当它完全被另一个Activity覆盖时则处于停止状态.

当Activity从一种状态转变到另一种状态时,会调用以下保护方法来通知这种变化:
void onCreate()
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy()
这里写图片描述

- startActivity开启一个Activity时, 生命周期的过程是: onCreate -> onStart(可见, 但不可交互) -> onResume(可见, 可交互)- 点击back键关闭一个Activity时, 生命周期的过程是: onPause(部分可见, 不可交互) -> onStop(完全不可见) -> onDestory(销毁了)- 当开启一个新的Activity(以对话框形式), 新的activity把后面的activity给盖住一部分时, 后面的activity的生命周期执行的方法是: onPause(部分可见, 不可交互)- 当把新开启的Activity(以对话框形式)给关闭时, 后面的activity的生命周期执行的方法是: onResume(可见, 可交互)- 当开启一个新的activity把后面的activity完全盖住时, 生命周期的方法执行顺序: onPause -> onStop(完全不可见)- 当把新开启的activity(完全盖住)给关闭时, 生命周期的方法执行顺序是: onRestart -> onStart -> onResume(可见, 可交互)- 实际工作中使用的方法     - onResume 可见, 可交互. 把动态刷新的操作启动.    - onPause 部分可见, 不可交互.  把动态刷新的一些操作, 给暂停了.    - onCreate 初始化一些大量的数据.    - onDestory 把数据给释放掉, 节省内存.
  • 横竖屏切换时, 生命周期, 默认情况下会把activity销毁再创建.

    • 不让Activity销毁在创建

      • 4.0以下版本

            android:configChanges="orientation|keyboardHidden"
      • 4.0以上版本

            android:configChanges="orientation|screenSize"
      • 兼容所有版本

            android:configChanges="orientation|keyboardHidden|screenSize"

二、跳转到新的Activity
显式开启: 明确知道并且可以引用的是哪一个Activity类对象
//新建一个意图, 指定跳转到哪一个activity类.
Intent intent = new Intent(MainActivity.this, NewActivity.class);

// 使用意图传递参数(参数类型可以是基本类型和实现序列化接口的类)
Intent.putExtra(“name”, “zhangsan”);

// 开始跳转
startActivity(intent);

隐式开启: 不知道将要跳转的是哪一个类, 无法引用到类. 只知道其动作(action), 类型(mimeType)和附加信息.
// 以下是打开系统中浏览器页面.
Intent intent = new Intent();
intent.setAction(“android.intent.action.VIEW”);
intent.addCategory(“android.intent.category.DEFAULT”);
intent.addCategory(“android.intent.category.BROWSABLE”);
intent.setData(Uri.parse(“http://www.baidu.com“));
startActivity(intent);

  • 打开浏览器页面

    /*<intent-filter>    <action android:name="android.intent.action.VIEW" />    <category android:name="android.intent.category.DEFAULT" />    <category android:name="android.intent.category.BROWSABLE" />    <data android:scheme="http" />    <data android:scheme="https" />    <data android:scheme="about" />    <data android:scheme="javascript" /></intent-filter>*/Intent intent = new Intent();intent.setAction("android.intent.action.VIEW");intent.addCategory("android.intent.category.BROWSABLE");Uri uri = Uri.parse("http://www.itheima.com");intent.setData(uri);startActivity(intent);
  • 打开系统短信发送的页面

    /*<intent-filter>    <action android:name="android.intent.action.VIEW" />    <action android:name="android.intent.action.SENDTO" />    <category android:name="android.intent.category.DEFAULT" />    <category android:name="android.intent.category.BROWSABLE" />    <data android:scheme="sms" />    <data android:scheme="smsto" /></intent-filter>*/Intent intent = new Intent();intent.setAction("android.intent.action.VIEW");intent.addCategory("android.intent.category.BROWSABLE");Uri uri = Uri.parse("sms:5556");intent.setData(uri);// 使用intent传递数据intent.putExtra("sms_body", "今晚7天假日酒店旁边的肯德基不见不散!!!");startActivity(intent);

三、Intent传递数据

  • 可传递类型: 八大基本类型和数组, ArrayList, Bundle数据捆, 序列化接口(javabean)

得到新打开Activity 关闭后返回的数据

如果你想在Activity中得到新打开Activity 关闭后返回的数据,你需要使用系统提供的startActivityForResult(Intent intent, int requestCode)方法打开新的Activity,新的Activity 关闭后会向前面的Activity 传回数据,为了得到传回的数据,你必须在前面的Activity中重写onActivityResult(int requestCode, int resultCode, Intent data)方法:
public class MainActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
…….
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){//点击该按钮会打开一个新的Activity
public void onClick(View v) {
//第二个参数为请求码,可以根据业务需求自己编号
startActivityForResult (new Intent(MainActivity.this, NewActivity.class), 1);
}});
}
//第一个参数为请求码,即调用startActivityForResult()传递过去的值
//第二个参数为结果码,结果码用于标识返回数据来自哪个新Activity
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String result = data.getExtras().getString(“result”));//得到新Activity 关闭后返回的数据
}
} 当新Activity关闭后,新Activity返回的数据通过Intent进行传递,android平台会调用前面Activity 的onActivityResult()方法,把存放了返回数据的Intent作为第三个输入参数传入,在onActivityResult()方法中使用第三个输入参数可以取出新Activity返回的数据。

四、Activity 的启动模式

  • 程序打开时就创建了一个任务栈, 用于存储当前程序的activity.

    • 所有的activity属于一个任务栈.
    • 一个任务栈包含了一个activity的集合, 去有序的选择哪一个activity和用户进行交互
    • 只有在任务栈栈顶的activity才可以跟用户进行交互.
    • 任务栈可以移动到后台, 并且保留了每一个activity的状态. 并且有序的给用户列出她们的任务, 而且还不丢失它们状态信息.
    • 退出程序: 把所有的任务栈中所有的activity清除出栈, 任务栈销毁.

    • 问题:

      • 用户体验差, 需要点击多次返回才可以把程序退出了.
      • 数据冗余, 重复数据太多, 会导致内存溢出的问题(OOM)

在清单文件(AndroidManifest.xml)文件中的activity节点里有个属性android:launchMode就是指定Activity的启动模式. 其默认为标准模式(standard), 以下是四种模式:

  • Activity的启动模式, 在activity节点里指定launchMode的属性.

    • standard 标准模式(activity的默认模式), 导致上面的问题出现.

    • singleTop 单一顶部模式: 如果一个activity的实例已经存在当前任务栈的栈顶, 系统会发送一个Intent给那个实例的onNewIntent方法.
      应用场景: 防止别的程序恶意打开我们的页面.

    • singleTask 单一任务栈模式: 如果activity的实例已经存在任务栈中, 系统就不会创建一个新的实例, 而是调用那个实例的onNewIntent方法, 并且把那个已经存在的activity实例以上所有的activity给清除出栈, 把自己变成栈顶的效果.
      应用场景: 商品列表 -> 商品详情 -> 图片详情 -> 大图查看 想从大图查看立刻回到商品列表, 并且把后面开启的三个页面关闭时.

    • singleInstance 单一实例模式: 系统会创建一个新的任务栈把activity的实例放在新的任务栈的栈顶(栈底), 其他的activity页面不会在这个任务栈中创建实例.
      如果activity的实例已经存在, 系统会调用那个实例的onNewIntent方法.
      应用场景: 在整个系统中只需要初始化一次的界面.

案例:人品计算器

public class MainActivity extends Activity {    private EditText etName;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        etName = (EditText) findViewById(R.id.et_name);    }    /**     * 开始计算人品     * @param v     */    public void startCalc(View v) {        String name = etName.getText().toString().trim();        Intent intent = new Intent(this, RPCalcActivity.class);        intent.putExtra("name", name);//      startActivity(intent);        startActivityForResult(intent, 100);    }    /**     * 当被开启的页面回传数据时出发此方法     */    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        if(requestCode == 100 && resultCode == 200) {            String text = data.getStringExtra("rpText");            Toast.makeText(this, text, 0).show();        }    }}
public class RPCalcActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        TextView tv = new TextView(this);        tv.setTextSize(20);        tv.setTextColor(Color.RED);        setContentView(tv); // 当前Activity显示的是一个空白的TextView        // 接收姓名        Intent intent = getIntent();        String name = intent.getStringExtra("name");        String text = "姓名: " + name;        // 计算人品值        byte[] bytes = name.getBytes();        int rpCode = 0;        for (byte b : bytes) {            rpCode += b;        }        System.out.println("人品值为: " + rpCode);        rpCode = Math.abs(rpCode) % 101; // 769  101 % 101 = 0        if("李印东".equals(name)) {            rpCode = 100;        }        text = text + "\n人品得分: " + rpCode;        // 人品评价信息        String rpText = getRPText(rpCode);        text = text + "\n评价: " + rpText;        tv.setText(text);        Intent data = new Intent();        data.putExtra("rpText", rpText);        // 此方法设置的是返回给调用当前activity的那个界面的数据, 不是立刻返回, 而是等待当前activity销毁才去传回去.        setResult(200, data);    }    /**     * 根据给定的人品值, 获取对应的人品评价信息     * @param rp     * @return     */    private String getRPText(int rp) {        String rpText = null;        if (rp == 0) {            rpText = "你一定不是人吧?怎么一点人品都没有?!";        } else if (rp > 0 && rp <= 5) {            rpText = "算了,跟你没什么人品好谈的...";        } else if (rp > 5 && rp <= 10) {            rpText = "是我不好...不应该跟你谈人品问题的...";        } else if (rp > 10 && rp <= 15) {            rpText = "杀过人没有?放过火没有?你应该无恶不做吧?";        } else if (rp > 15 && rp <= 20) {            rpText = "你貌似应该三岁就偷看隔壁大妈洗澡的吧...";        } else if (rp > 20 && rp <= 25) {            rpText = "你的人品之低下实在让人惊讶啊...";        } else if (rp > 25 && rp <= 30) {            rpText = "你的人品太差了。你应该有干坏事的嗜好吧?";        } else if (rp > 30 && rp <= 35) {            rpText = "你的人品真差!肯定经常做偷鸡摸狗的事...";        } else if (rp > 35 && rp <= 40) {            rpText = "你拥有如此差的人品请经常祈求佛祖保佑你吧...";        } else if (rp > 40 && rp <= 45) {            rpText = "老实交待..那些论坛上面经常出现的偷拍照是不是你的杰作?";        } else if (rp > 45 && rp <= 50) {            rpText = "你随地大小便之类的事没少干吧?";        } else if (rp > 50 && rp <= 55) {            rpText = "你的人品太差了..稍不小心就会去干坏事了吧?";        } else if (rp > 55 && rp <= 60) {            rpText = "你的人品很差了..要时刻克制住做坏事的冲动哦..";        } else if (rp > 60 && rp <= 65) {            rpText = "你的人品比较差了..要好好的约束自己啊..";        } else if (rp > 65 && rp <= 70) {            rpText = "你的人品勉勉强强..要自己好自为之..";        } else if (rp > 70 && rp <= 75) {            rpText = "有你这样的人品算是不错了..";        } else if (rp > 75 && rp <= 80) {            rpText = "你有较好的人品..继续保持..";        } else if (rp > 80 && rp <= 85) {            rpText = "你的人品不错..应该一表人才吧?";        } else if (rp > 85 && rp <= 90) {            rpText = "你的人品真好..做好事应该是你的爱好吧..";        } else if (rp > 90 && rp <= 95) {            rpText = "你的人品太好了..你就是当代活雷锋啊...";        } else if (rp > 95 && rp <= 99) {            rpText = "你是世人的榜样!";        } else if (rp == 100) {            rpText = "天啦!你不是人!你是神!!!";        } else {            rpText = "你的人品竟然负溢出了...我对你无语..";        }        return rpText;    }}
原创粉丝点击