安卓基础第六天(四大组件之Activity)

  • Activity 是Android 四大组件之一,它用于展示界面。
  • 是一个负责与用户交互的组件,可以通过setContentView(View)来显示指定控件。
  • Activity 之间通过Intent 进行通信。### Activity之间的跳转

Activity清单配置

  • 定义类继承Activity
  • 在AndroidManifest.xml 的节点中声明

application中lable指程序的名字,
activity中的lable是指activity 的名字
name 属性::包名.Activity 类名
包名如果与mainfest 的package 一致,可以用“.”代替。或者不写
Intent-filter 子节点:
- 添加意图过滤,可以通过隐式意图启动。
- 可以在桌面生成快捷方式,应用程序的入口
如果此activity还指定了以下filter那么这个界面就会在桌面创建快捷方式

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

Icon 属性:图标
theme 属性:指定主题

Activity 之间的跳转

显式意图跳转

  • 可以引用到那个类, 并且可以引用到那个类的字节码时可以使用。
  • 一般用于自己程序的内部。显式跳转不可以跳转到其他程序的页面中。

隐式意图跳转

  • 可以在当前程序跳转到另一个程序的页面
  • 隐式跳转不需要引用到那个类,但是必须得知道那个界面的动作(action)和信息(category)。

使用Intent意图传递数据

Activity 之间通过Intent 进行通信。Intent 即意图,用于描述一个页面的信息,同时也是一个数据的载体。

  • 案例 RP计算器
public class MainActivity extends Activity {

    private EditText et_name;
    private RadioGroup rg_group;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        et_name = (EditText) findViewById(R.id.et_name);
        rg_group = (RadioGroup) findViewById(R.id.radioGroup1);

    }

    // 点击按钮 实现计算人品 跳转到ResultActivity页面
    public void click(View v) {
        // [1]获取用户名
        String name = et_name.getText().toString().trim();
        // [2] 判断一下name 是否为空
        if (TextUtils.isEmpty(name)) {
            Toast.makeText(getApplicationContext(), "亲 请输入姓名", 1).show();
            return;
        }
        // [3]判断用户选择的性别
        int radioButtonId = rg_group.getCheckedRadioButtonId();
        int sex  = 0;


        switch (radioButtonId) {
        case R.id.rb_male: // 代表选择的是男

            sex = 1;
            break;

        case R.id.rb_female: // 代表选择的是女

            sex = 2;

            break;

        case R.id.rb_other: // 代表选择的是人妖

            sex = 3;
            break;

        }
        if(sex == 0){
            Toast.makeText(getApplicationContext(), "请选择性别", 1).show();
            return;
        }

        //[4]跳转到ResultActivity页面   用显示意图跳转
        Intent intent = new Intent(this, ResultActiviyt.class);
        //传递姓名
        intent.putExtra("name", name);
        //传递性别 
        intent.putExtra("sex", sex);


        startActivity(intent);




    }

}

跳转页

public class ResultActiviyt extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // [1]加载布局
        setContentView(R.layout.activity_result);

        TextView tv_name = (TextView) findViewById(R.id.tv_name);
        TextView tv_sex = (TextView) findViewById(R.id.tv_sex);
        TextView tv_result = (TextView) findViewById(R.id.tv_result);
        // [2]获取mainActivity 传递过来的数据
        Intent intent = getIntent(); // 获取开启此Activity的意图对象
        // [3]获取name 和 sex 的值 小技巧 :传递的是什么数据类型 这边就按照传递的数据类型取
        String name = intent.getStringExtra("name");
        int sex = intent.getIntExtra("sex", 0);

        // [4]根据name 和 sex 显示数据
        tv_name.setText(name);

        byte[] bytes = null;

        // [5]显示性别
        try {
            switch (sex) {
            case 1:

                tv_sex.setText("男");
                bytes = name.getBytes("gbk"); 

                break;

            case 2:
                tv_sex.setText("女");
                bytes = name.getBytes("utf-8"); 
                break;

            case 3:
                tv_sex.setText("人妖");
                bytes = name.getBytes("iso-8859-1"); 
                break;

            default:
                break;
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //[6]计算人品结果 市面上大多数应用采用的是随机数  

        int total = 0;
        for (byte b : bytes) {                  // 0001 1111 
            int number = b&0xff;               // 1111 1111
            total+=number;
        }
        // 获取得分
        int score =  Math.abs(total)%100;
        if (score > 90) {
            tv_result.setText("您的人品非常好,您家的祖坟都冒青烟啦");
        }else if (score > 80) {
            tv_result.setText("您的人品还可以  ");
        }else if (score > 60) {
            tv_result.setText("您的人品刚及格");
        }else{
            tv_result.setText("您的人品太次了  您需要努力啊");

        }

    }

}
  • 案例 短信发送器 (请求码,结果码)

    • requestCode 开启activity时设置的请求吗
    • resultCode 在目标activity中设置的结果码
      主页面
public class MainActivity extends Activity {

    private EditText et_number;
    private EditText et_content;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //[1]找到我们关心的控件

        et_number = (EditText) findViewById(R.id.et_number);
        et_content = (EditText) findViewById(R.id.et_content);


    }

    //点击按钮跳转到发送短信模板页面
    public void insertsms(View v){
        Intent intent = new Intent(this,SmsTemplateActivity.class);
        startActivityForResult(intent, 2);
    }


    //点击按钮 跳转到ContactActivity 页面 
    public void add(View v){
        Intent intent = new Intent(this,ContactActivity.class);
//      startActivity(intent);
        //小细节 如果点击按钮 开启了另外一Activity   并且当开启的这个Activity关闭的时候  我想要这个开启Activity的数据  用下面这个方法开启activity
        startActivityForResult(intent, 1);          
    }


    //当我们开启的Activity 页面关闭的时候 这个方法就调用
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode==1) {
            //代表请求ContactActivity这个页面的数据 
            String phone = data.getStringExtra("phone");
            et_number.setText(phone);

        }else if (requestCode == 2) {
            //代表请求 短信模板页面的数据 

            String smsContent = data.getStringExtra("smscontent");
            et_content.setText(smsContent);
        }


        /*
        if (resultCode == 10) {
            //说明数据是从 ContactActivity 返回 
            String phone = data.getStringExtra("phone");
            et_number.setText(phone);

        }else if (resultCode == 20) {
            //说明数据 是从 SmsTempate 返回 
            String smsContent = data.getStringExtra("smscontent");
            et_content.setText(smsContent);
        }
        */

        super.onActivityResult(requestCode, resultCode, data);
    }


    //点击按钮 发送短信 
    public void send(View v){

        //[1]获取发送短信的号码 和 发送的内容 
        String number = et_number.getText().toString().trim();
        String content = et_content.getText().toString().trim();
        //[2]获取到smsmanager的实例 
        SmsManager smsManager = SmsManager.getDefault();

        ArrayList<String> divideMessages = smsManager.divideMessage(content);
        for (String div : divideMessages) {


            /**
             * destinationAddress  发送给谁 
             * scAddress  服务中心号码
             * 
             * text 要发送的内容
             */

            smsManager.sendTextMessage(number, null, div, null, null);
        }

    }


}

获取联系人页面

public class ContactActivity extends Activity {


    private List<Person> lists;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //加载布局
        setContentView(R.layout.activity_contact);

        //[1]找到控件
        ListView lv = (ListView) findViewById(R.id.lv);

        //[2]准备listview 要显示的数据  模拟点假数据 
        lists = new ArrayList<Person>();
        for (int i = 0; i < 20; i++) {
            Person p = new Person();
            p.setName("张三"+i);
            p.setPhone("11"+i);
            lists.add(p);
        }

        //[3]展示数据 
        lv.setAdapter(new MyAdapter());

        //[4]给listview 设置点击事件 
        lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {

                //[5]获取我点中条目的数据   数据在哪里面存着呢 就去哪里取
                String phone = lists.get(position).getPhone();

                //[5.0]把数据返回给调用者 
                Intent intent = new Intent();
                intent.putExtra("phone", phone);

                //把结果返回给调用者
                setResult(10, intent);

                //[5.1]关闭当前页面 
                finish();               
            }
        }); 
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }

    private class MyAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return lists.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            if (convertView == null) {
                view = View.inflate(getApplicationContext(), R.layout.contact_item, null);
            }else {
                view = convertView;

            }
            //[1]找到我们在item 中定义的控件   用来显示 数据 
            TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
            TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);
            //[2]展示数据 
            tv_name.setText(lists.get(position).getName());
            tv_phone.setText(lists.get(position).getPhone());
            return view;
        }

    }
}

获取短信模板页

public class SmsTemplateActivity extends Activity {


    String objects[] = {"我在吃饭,请稍后联系","我在开会,请稍后联系","我在上课,请稍后联系","我在打代码,请稍后联系","我在约会,请稍后联系"};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_smstemplate);

        //[1]找到lv
        ListView lv = (ListView) findViewById(R.id.lv);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.smstemplate_item, objects);

        //[2]显示数据
        lv.setAdapter(adapter);

        //[3]设置lv 的条目的点击事件 
        lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {

                //[4]取出点击条目的数据 
                String smsContent = objects[position];

                //[5]把smsContent 返回调用者 
                Intent intent = new Intent();
                intent.putExtra("smscontent", smsContent);
                setResult(20, intent);

                //[6]调用finish
                finish();   
            }
        });

    }
}

Activity生命周期

Activity 有三种状态:
- 1、当它在屏幕前台时,响应用户操作的Activity, 它是激活或运行状态
- 2、当它上面有另外一个Activity,使它失去了焦点但仍然对用户可见时, 它处于暂停状态。
- 3、当它完全被另一个Activity 覆盖时则处于停止状态。

当Activity 从一种状态转变到另一种状态时,会调用以下保护方法来通知这种变化:

方法名 说明
void onCreate() 设置布局以及进行初始化操作
void onStart() 可见, 但不可交互
void onRestart() 调用onStart()
void onResume() 可见, 可交互
void onPause() 部分可见, 不可交互
void onStop() 完全不可见
void onDestroy() 销毁


声明周期图

  • startActivity 开启一个Activity 时, 生命周期的过程是:
    onCreate ->onStart(可见不可交互) ->onResume(可见可交互)
  • 点击back 键关闭一个Activity 时, 生命周期的过程是:
    onPause(部分可见不可交互)->onStop(完全不可见)->onDestroy(销毁)
  • 当开启一个新的Activity(以对话框形式), 新的activity 把后面的activity 给盖住一部分时, 后面的activity 的生命周期执行的方法是:
    onPause(部分可见, 不可交互)
    Activity 以对话框的形式显示,需在activity 节点追加主题android:theme=”@android:style/Theme.Dialog”
  • 当把新开启的Activity(以对话框形式)给关闭时, 后面的activity 的生命周期执行的方法是:
    onResume(可见, 可交互)
  • 当开启一个新的activity 把后面的activity 完全盖住时, 生命周期的方法执行顺序是:
    onPause ->onStop(完全不可见)
  • 当把新开启的activity(完全盖住)给关闭时, 生命周期的方法执行顺序是:
    onRestart ->onStart ->onResume(可见, 可交互)

  • 实际工作中常用的方法以及应用场景有:
    onResume 可见, 可交互.。把动态刷新的操作启动。
    onPause 部分可见, 不可交互. 把动态刷新的一些操作, 给暂停了。
    onCreate 初始化一些大量的数据。
    onDestroy 把数据给释放掉, 节省内存。

横竖屏切换

横竖屏切换时,默认情况下会把activity 先销毁再创建,这个体验是非常差的
不让Activity 在横竖屏切换时销毁,只需要在清单文件声明Activity 时配置节点的几个属性即可
兼容所有版本:
android:configChanges="orientation|keyboardHidden|screenSize
禁止横竖屏:
screenOrientation=”” 指定屏幕固定方向,不会随着屏幕旋转而旋转
android:screenOrientation=”portrait” 始终竖屏
android:screenOrientation=”landscape” 始终横屏

Activity任务栈

  1. 程序打开时就创建了一个任务栈, 用于存储当前程序的activity,所有的activity 属于一个任务栈。
  2. 一个任务栈包含了一个activity 的集合, 去有序的选择哪一个activity 和用户进行交互:只有在任务栈栈顶的activity 才可以跟用户进行交互
  3. 任务栈可以移动到后台, 并且保留了每一个activity 的状态. 并且有序的给用户列出它们的任务, 而且还不丢失它们状态信息
  4. 退出应用程序时:当把所有的任务栈中所有的activity 清除出栈时,任务栈会被销毁,程序退出。

重复数据太多, 会导致内存溢出的问题(OOM)

Activity启动模式

为了解决任务栈产生的问题,Android 为Activity 设计了启动模式
可以在AndroidManifest.xml 配置的android:launchMode 属性为以下四种之一即可。

四种launchMode:
1.standard
默认模式
2.singleTop
如果任务栈的栈顶存在这个要开启的activity,不会重新的创建activity,而是复用已经存在的activity。保证栈顶如果存在,不会重复创建。
应用场景:浏览器的书签
3.singleTask
单一任务栈,在当前任务栈里面只能有一个实例存在,
当开启activity的时候,就去检查在任务栈里面是否有实例已经存在,
如果有实例存在就复用这个已经存在的activity,
并且把这个activity上面的所有的别的activity都清空,
复用这个已经存在的activity。保证整个任务栈里面只有一个实例存在
应用场景:浏览器的activity
4.singleInstance
activity会运行在自己的任务栈里面,并且这个任务栈里面只有一个实例存在
如果你要保证一个activity在整个手机操作系统里面只有一个实例存在,使用singleInstance
应用场景: 来电页面

猜你喜欢

转载自blog.csdn.net/opopopwqwqwq/article/details/79340452