Android学习笔记(二)活动(Activity)

这篇博客详细介绍了Android中的Activity,包括基本使用如手动创建、加载布局、注册、隐藏标题栏、使用Toast和Menu,以及Intent的概念和类型,如何传递数据。同时,深入探讨了Activity的生命周期,包括返回栈、四种状态和生存期方法,并给出了启动模式的解析。最后,分享了一些实践技巧,如识别当前活动、退出应用的最佳实践和启动活动的建议写法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.活动(Activity)

2.1 概念

        活动是Android的基本组成单位,每个Activity都被定义为一个单独的类,且都继承自基类:android.app.Activity;它是一种包含用户界面的组件,主要用来与用户进行交互(通俗点讲,可以先理解为一个单独的屏幕、一个交互的窗口,但不完全是这样)。

2.2 基本使用


2.2.1 手动创建活动

        新建一个类FirstActivity,并继承自基类Activity,重写Activity的onCreate()方法(项目中的任何活动都要重写此方法)。
public class FirstActivity extends Activity {

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

2.2.2 创建加载布局

       Android应用讲究逻辑和视图分离,所以最好一个Activity对应一个XML布局文件。
        创建activity_first.xml文件(在res-->layout目录下),并添加一个按钮:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--
    android:id==>>给当前的元素定义一个唯一标识符,可在代码中调用。
    @+id/btn_1==>>需要引用一个id,则使用@id/id_name这种语法;需要定义一个id,则使用@+id/id_name这种语法,其他资源一致。
    android:layout_width==>>指定当前元素宽度,同理height为高度
    android:text==>>指定元素显示的文字内容,其实文字应该放在字符串文件中并在这里引用。
    -->

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        android:id="@+id/btn_1" />

</LinearLayout>
在代码中调用此视图显示到activity中:
setContentView(R.layout.activity_first);
这里我们使用自己的R文件,AndroidSDK还会提供一个android包下的R文件,不要弄错。

2.2.3 在Androidmanifest.xml中注册

所有的活动都要在AndroidManifest.xml中进行注册才能生效:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jastar.activitytest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!--
            1.所有活动都需通过activity标签来注册,且放在application标签中
            2.android:name:指定注册哪一个活动;.FirstActivity是缩写,因为包名在manifest标签中已经定义了
            3.android:label:活动标题栏的内容,显示在最顶部
            4.给主活动指定的label还会成为启动器(Launcher)中应用程序显示的名称
        -->
        <activity android:name=".FirstActivity" android:label="This is the firstActivity">
            <intent-filter>
                <!--让活动成为主活动(main入口)就要声明这两句话-->
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


2.2.4 隐藏标题栏

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //隐藏标题栏,一定要写在setContentView方法前面
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_first);
}


注意:
使用AS创建的activity隐藏标题栏时无效,是因为AS默认继承的是AppCompatActivity类,换成Activity类即可。

2.2.5 使用Toast悬浮提示

       Toast是Android系统提供的提示方式,可将信息展示给用户,并在一段时间后消失。
        可给按钮添加点击事件,并提示:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //隐藏标题栏
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_first);

        /**
         * 1.通过findViewById()来获得界面上的元素,返回View对象,并向下转型
         * 2.通过实现OnClicklistener接口的onClick()来给按钮添加点击事件
         */
        Button btn = (Button) findViewById(R.id.btn_1);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 别忘了调用.show()方法
                 * param1:Context上下文,由于活动本身就是,所以传入活动对象即可
                 * param2:提示内容
                 * param3:提示显示时长,还有LENGTH_LONG
                 */
                Toast.makeText(FirstActivity.this, "You click the button!", Toast.LENGTH_SHORT).show();
            }
        });
    }

2.2.6 使用menu菜单

(1)在res下新建menu文件夹
(2)在menu下新建一个名为main的菜单文件(在AS中直接new一个Menu resource file)
(3)AS创建之后默认是一个空的menu标签,需要添加菜单项代码:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/item_add"
        android:title="Add" />
    <item
        android:id="@+id/item_remove"
        android:title="Remove" />
</menu>
(4)在活动中重写onCreateOptionsMenu()使得菜单展示
    /**
     * 重写展示菜单的方法
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        /**
         * 通过此方式给当前活动创建菜单
         * param1:指定哪个资源文件创建菜单
         * param2:指定菜单项将添加到哪个菜单中,直接使用方法中传入的参数即可
         * return:true允许菜单展示,false则不显示
         */
        getMenuInflater().inflate(R.menu.main,menu);
        return true;
    }
(5)在活动中重写onOptionsItemSelected()响应菜单点击事件
    /**
     * 重写响应菜单点击事件的方法
     *
     * @param item
     * @return
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //item.getItemId()用来获取选中菜单的id
        switch (item.getItemId()) {
            case R.id.item_add:
                Toast.makeText(FirstActivity.this, "You click add menu!", Toast.LENGTH_SHORT).show();
                break;
            case R.id.item_remove:
                Toast.makeText(FirstActivity.this, "You click remove menu!", Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }

2.2.7 销毁活动

返回键可以销毁;当然代码也能:finish();即可

2.3 意图(Intent)

2.3.1 概念

        Intent 是 Android 程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent 一般可被用于启动活动、启动服务、以及发送广播等场景。
        Intent的用法大概分为两种:显式意图隐式意图

2.3.2 显式意图

        同样方法创建第二个Activity——SecondActivity,并在FirstActivity中按钮点击事件中编写如下代码:
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * param1:为当前活动上下文
                 * param2:要启动的活动
                 */
                Intent intent =new Intent(FirstActivity.this,SecondActivity.class);
                startActivity(intent);
            }
        });

2.3.3 隐式意图

        指定了一系列更为抽象的 action和 category等信息,然后交由系统去分析这个 Intent,并帮我们找出合适的活动去启动。
         隐式意图需要在activity标签下的intent-filter标签中指定action和category,只有action和category同时匹配的情况下(除去当category配置为默认 android:name="android.intent.category.DEFAULT" 时),该活动才能响应。如:
<activity android:name=".SecondActivity" >
    <intent-filter>
        <action android:name="com.example.activitytest.ACTION_START" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
java代码如下:
Intent intent=newIntent("com.example.activitytest.ACTION_START");
startActivity(intent);
每个 Intent 中只能指定一个 action,但却能指定多个 category。
intent.addCategory("...");

2.3.4 隐式意图更多用法

隐式意图不但能打开自己应用的activity,还能打开系统的activity,如浏览器、拨号等等。
    @Override
    public void onClick(View v) {
        /**
         * 1.Intent.ACTION_VIEW 这是系统内置动作,其常量值为android.intent.action.VIEW
         * 2.通过Uri.parse()方法将网址解析为Uri对象
         * 3.调用setData将Uri对象传递。
         */
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);

        //打电话
        //Intent intent=new Intent(Intent.ACTION_DIAL);
        //intent.setData(Uri.parse("tel:10086"));
        //startActivity(intent);
    }

2.3.5 向下一个Activity传递数据

(1)第一个activity:
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        //使用putExtra()方法传递数据
        intent.putExtra("data", "这是我传递的数据");
        startActivity(intent);
(2)第二个activity:
        //通过getIntent()方法获取启动当前activity的意图对象
        Intent intent = getIntent();
        //什么类型的数据就get类型Extra("");
        String data = intent.getStringExtra("data");
        Log.d("SecondActivity", data);

2.3.6 返回数据给上一个Activity

Activity中提供了一个startActivityForResult()方法,此方法期望在活动销毁后能够返还一个数据给上一个活动。
(1)在第一个activity中如下编写:
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        intent.putExtra("data", "这是我传递的数据");
        //startActivity(intent);
        /**
         * param1:仍然是意图对象
         * param2:请求码,用于在之后的回调中判断数据来源,只要是唯一值就可以了,这里传入1
         */
        startActivityForResult(intent, 1);
(2)第二个activity中重写onBackPressed()方法,此方法表示用户点击了返回键:
    @Override
    public void onBackPressed() {
        //声明意图,但此处的意图仅仅是为了传递数据,并不是要启动Activity
        Intent intent=new Intent();
        intent.putExtra("data_back","这是返回的数据~~~");
        /**
         * 通过setResult方法来返回数据,非常重要
         * param1:返回处理结果,常用的是RESULT_OK,RESULT_CANCELED
         * param2:意图对象,传递数据
         */
        setResult(RESULT_OK,intent);
        //销毁活动
        finish();
    }
(3)在第一个activity中重写回调方法onActivityResult()
    /**
     * 第二个活动处理完成后返回第一个活动的回调函数
     * @param requestCode 启动第二个活动时传入的请求码,即1
     * @param resultCode 第二个活动返回的处理结果
     * @param intent 携带着返回数据的intent
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        switch (requestCode){
            // 判断请求码是不是我们所传递的
            case 1:
                if (resultCode==RESULT_OK){
                    String dataBack= intent.getStringExtra("data_back");
                    Toast.makeText(FirstActivity.this, "返回:"+dataBack, Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }

2.4 生命周期

2.4.1 返回栈

        Android中的活动是层叠的,每启动一个活动,就会覆盖在原来的活动上面,然后点击Back键就会销毁最上面的。
        Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的集合,这个栈被称作返回栈(Back Stack)

2.4.2 状态

  • 运行:当活动处于返回栈的栈顶时,则这个活动是运行状态
  • 暂停:当一个活动不处于栈顶、但仍然可见时,这个活动处于暂停状态,
  • 停止:当一个活动不在处于栈顶时,而且完全不可见时,则进入了停止状态。当其他地方需要内存时,停止状态的活动极有可能被回收
  • 销毁:当一个活动从返回栈中移除后就变成了销毁状态。

2.4.3 生存期

  • onCreate():活动初次创建时调用,做初始化工作
  • onStart():对用户即将可见的时候调用
  • onResume():将要与用户交互的时候调用(此时活动一定处于栈顶,且运行状态)
  • onPause():准备去启动或者恢复另一个活动时调用
  • onStop():完全不可见时调用
  • onDestroy():被销毁之前调用,调用后则变为销毁状态
  • onRestart():活动由停止状态变为运行状态之前调用(重新启动)

三种生存期:
(1)完整生存期:onCreate()-->onDestroy()的过程
(2)可见生存期:onStart()-->onStop()的过程
(3)前台生存期:onResume()-->onPause()

2.4.4 活动被回收如何处理

        活动在停止状态是容易被系统回收的(比如系统内存不足情况下),如何解决活动被回收时临时数据得不到保存的问题?
        Activity 中提供了一个onSaveInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用。
    /**
     * Bundle类型的参数提供了一系列的方法用于保存数据
     * @param outState
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        /**
         * put系列方法,依次类推,如putInt....
         * param1:数据的键值
         * param2:数据
         */
        outState.putString("data_key","something you want to save.");
    }
        保存完成后可以在onCreate方法里面获取数据(因为活动被回收之后再运行此活动就会重新创建),onCreate方法也有一个Bundle类型的参数savedInstanceState:
        if(savedInstanceState!=null){
            String data=savedInstanceState.getString("data_key");
            //其他操作....
        }
还可以结合intent传递数据(把数据放在Bundle中,再把Bundle放到Intent中)。

2.5 启动模式

  • standard
活动默认的启动模式,在此模式下,每当启动一个新的活动,他就会在返回栈中入栈,并处于顶部,系统不会在乎这个活动在返回栈中是否已存在,每次启动都会创建一个活动的实例。
  • singleTop
启动活动时如果发现返回栈栈顶已经是该活动(注意是栈顶),则认为可直接使用它,不会再创建活动的实例。但不是在栈顶时,则还会创建实例。
  • singleTask
在整个应用程序的上下文中,只存在一个该活动的实例。当启动活动时,首先检查返回栈中是否已存在,若存在,则把该活动之上的活动统统移除出栈,如果没有发现就会创建一个新的实例。
  • singleInstance
该模式下的活动会启用一个新的返回栈来管理,这样做的意义就是可以和其他程序之间共享这个活动的实例(用以上三种模式的话,每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈入栈时必然是创建了新的实例,做不到共享的效果)。

2.6 实践技巧

2.6.1 识别当前是在哪一个活动

        新建一个BaseActivity继承Activity,然后重写onCreate()方法,让其他的Activity类继承BaseActivity类,在BaseActivity类的onCreate方法中打印:
Log.d("BaseActivity", getClass().getSimpleName());

2.6.2 随时退出应用

(1)新建一个活动管理类:
package com.jastar.activitylifecycletest;

import android.app.Activity;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by admin on 2016/9/29.
 */
public class ActivityCollector {

    //通过list来暂存活动
    public static List<Activity> activities = new ArrayList<Activity>();

    public static void addActivity(Activity activity) {
        activities.add(activity);
    }

    public static void removeActivity(Activity activity) {
        activities.remove(activity);
    }

    public static void finishAll() {
        for (Activity activity : activities) {
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }
}
(2)在BaseActivity中重写onCreate()和onDestroy()方法实现向list中添加和移除activity
ActivityCollector.addActivity(this);
ActivityCollector.removeActivity(this);
(3)在想退出应用的地方调用ActivityCollector.finishAll()即可。

2.6.3 启动活动的最佳写法

(1)常规的思路:
        在FirstActivity中创建意图,存放数据,然后启动SecondActivity——合理且完全没问题,但是不知道需要传递什么数据,需要哪些参数。
(2)更好的思路:
        在SecondActivity中添加下面的方法,然后在FirstActivity中调用即可——传递哪些数据参数一目了然,一行代码即可启动活动。
    public static void actionStart(Context context, String param1, String param2) {
        Intent intent = new Intent(context, SecondActivity.class);
        intent.putExtra("param1", param1);
        intent.putExtra("param2", param2);
        context.startActivity(intent);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值