IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android第一行代码 探究活动 -> 正文阅读

[移动开发]Android第一行代码 探究活动

Android Activity

活动(Activity)是一种可以包含用户界面的组件,主要用于和用户进行交互。一个应用程序中可以包含零到多个活动。

  1. 创建Activity

    项目中所有的活动都要重写onCreate()方法

public class FirstActivity extends AppCompatActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
	}
}

默认调用父类的onCreate(savedInstanceState);方法,后面需要增加自己的逻辑代码。

  1. 创建和加载布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button 1 " />

</LinearLayout>
  1. 在AndroidManifest文件中注册
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.firstactivity">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.FirstActivity">
        <activity android:name=".FirstActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"></action>
                <category android:name="android.intent.category.LAUNCHER"></category>
            </intent-filter>
        </activity>
    </application>
</manifest>

activity 要放在 application 标签内

? android:name="" 指定活动

? 配置主活动(即点击应用程序图标时首先打开的这个活动)

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

Toast提醒

Toast是Android系统提供的一种提醒方式,在程序中可以使用它将一些短小的信息通知给用户,并在一段时间后消失,不会占用任何屏空间。

Toast通过makeText()创建一个Toast对象,然后调用show()显示

makeText()方法需要三个参数。

1. Context  即Toast要求的上下文
2. msg  Toast显示的文本内容
3. length   显示时长,有两个内置产量可以选择Toast.LENGTH_SHORT   Toast.LENGTH.LONG

Menu菜单

要定义Menu,我们首先需要在res文件夹下新建menu文件夹,它将用于存储与Menu相关的所有XML文件。

我们可以使用<menu><item><group>三种XML元素定义Menu,下面简单介绍一下它们:

  • <menu>是菜单项的容器。<menu>元素必须是该文件的根节点,并且能够包含一个或多个<item><group>元素。
  • <item>是菜单项,用于定义MenuItem,可以嵌套<menu>元素,以便创建子菜单。
  • <group><item>元素的不可见容器(可选)。可以使用它对菜单项进行分组,使一组菜单项共享可用性和可见性等属性。

其中,<item>是我们主要需要关注的元素,它的常见属性如下:

  • android:id:菜单项(MenuItem)的唯一标识
  • android:icon:菜单项的图标(可选)
  • android:title:菜单项的标题(必选)
  • android:showAsAction:指定菜单项的显示方式。常用的有ifRoom、never、always、withText,多个属性值之间可以使用|隔开。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
 
    <item android:id="@+id/option_normal_1"
        android:icon="@mipmap/ic_vpn_key_white_24dp"
        android:title="普通菜单1"
        app:showAsAction="ifRoom"/>
 
    <item android:id="@+id/option_normal_2"
        android:icon="@mipmap/ic_email_white_24dp"
        android:title="普通菜单2"
        app:showAsAction="always"/>
 
    <item android:id="@+id/option_normal_3"
        android:icon="@mipmap/ic_vpn_key_white_24dp"
        android:title="普通菜单3"
        app:showAsAction="withText|always"/>
 
    <item android:id="@+id/option_normal_4"
        android:title="普通菜单4"
        app:showAsAction="never"/>
</menu>

我们需要知道,菜单栏中的菜单项会分为两个部分。一部分可以直接在菜单栏中看见,我们可以称之为常驻菜单;另一部分会被集中收纳到溢出菜单中(就是菜单栏右侧的小点状图标)。一般情况下,常驻菜单项以图标形式显示(需要定义icon属性),而溢出菜单项则以文字形式显示(通过title属性定义)。showAsAction的差异如下所示:

  • always:菜单项永远不会被收纳到溢出菜单中,因此在菜单项过多的情况下可能超出菜单栏的显示范围。
  • ifRoom:在空间足够时,菜单项会显示在菜单栏中,否则收纳入溢出菜单中。
  • withText:无论菜单项是否定义了icon属性,都只会显示它的标题,而不会显示图标。使用这种方式的菜单项默认会被收纳入溢出菜单中。
  • never:菜单项永远只会出现在溢出菜单中。
  • 未写:默认出现在溢出菜单中。

接下来还需要在Java代码中进行加载

重写onCreateOptionsMenu方法,在这个方法中完成加载Menu资源的操作

@Override
public boolean onCreateOptionsMenu(Menu menu) {
	//获取MenuInflater
    MenuInflater inflater=getMenuInflater();
	//加载Menu资源
    inflater.inflate(R.menu.option_menu_normal,menu);
    //这个方法必须返回true,否则Menu将不会显示。
    return true;
}
 
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()){
        case R.id.option_normal_1:
            
            return true;
        case R.id.option_normal_2:
            
            return true;
        case R.id.option_normal_3:
            
            return true;
        case R.id.option_normal_4:
            
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

onOptionsItemSelected方法中,我们实现了菜单项的点击监听。可以看见,这里是通过MenuItemid进行区分的,对应着XML文件中<item>id属性。每次处理完点击事件后,记得要返回true,对系统而言这次点击事情才算是真正结束了。此外,在default分支下,推荐调用父类的默认实现,即super.onOptionsItemSelected(item),避免在多个Activity使用公有父类的情况下菜单项点击事件无法触发。

包含多级子菜单的选项菜单

我们在前面提到过,<item>是可以嵌套<menu>的,而<menu>又是<item>的容器。因此,我们可以在应用中实现具有层级结构的子菜单。下面给出一个实际的例子:

XML代码:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/option_sub_file"
        android:title="文件"
        app:showAsAction="ifRoom">
        <menu>
            <item android:id="@+id/file_new"
                android:title="新建"/>
            <item android:id="@+id/file_save"
                android:title="保存"/>
            <item android:id="@+id/file_more"
                android:title="更多">
                <menu>
                    <item android:id="@+id/file_more_1"
                        android:title="更多1"/>
                    <item android:id="@+id/file_more_2"
                        android:title="更多2"/>
                    <item android:id="@+id/file_more_more"
                        android:title="更多更多">
                        <menu>
                            <item android:id="@+id/file_more_more_1"
                                android:title="更多更多1"/>
                            <item android:id="@+id/file_more_more_2"
                                android:title="更多更多2"/>
                        </menu>
                    </item>
                </menu>
            </item>
        </menu>
    </item>
</menu>

上面的代码实现了一个三级子菜单结构。理论上来说,子菜单的层级是没有限制的。但是在实际应用中,由于移动设备的显示特点,建议菜单层级不要超过两层,否则会给用户的操作带来诸多不便。

使用Intnet在活动之间穿梭

  1. 使用显式Intent

Intnet intnet = new Intnet(this,Activity.class);

传入当前类作为上下文,Activity.class作为目标活动。

  1. 使用隐式Intnet

在AndroidManifest.xml中的目标活动中添加参数

<intent-filter>
    <action android:name="com.example.firstactivity.ACTION_START"></action>
    <category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>

Intnet intnet = new Intnet("com.example.firstactivity.ACTION_START");

Intnet中可以指定action,可以指定多个category

action 和 category 同时匹配时才能响应Intnet

未指定category 默认指定 android.intent.category.DEFAULT

<intent-filter>
    <action android:name="com.example.firstactivity.ACTION_START"></action>
    <category android:name="android.intent.category.DEFAULT"></category>
	<category android:name="com.example.firstactivity.MY_CATEGORY"></category>
</intent-filter>
Intent intent = new Intent("com.example.firstactivity.ACTION_START");
intent.addCategory("com.example.firstactivity.MY_CATEGORY");
  1. 其他隐式Intnet
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
//intent.setData(Uri.parse("tel:15079059049"));
startActivity(intent);

Intnet传递数据

Intnet intnet = new Intnet(this,Activity.class);
intnet.putExtra("key","value");
...
startActivity(intnet);

接收数据

Intnet intnet = getIntnet();
String value = intnet.getStringExtra("key");

字符串 getStringExtra() 整型getIntExtra() 布尔型 getBooleanExtra() …

返回数据给上一个活动

Intnet intnet = new Intnet(this,Activity.class);
startActivityForResult(intnet,1);

使用startActivityForResult启动下一个活动

Intent intent = new Intent();
intent.putExtra("data_return","Hello FirstActivity");
setResult(1,intent);
finish();

上述代码可放在 onackPressed() 方法中 ,也可放入点击事件中。

当该活动结束返回上一个活动并传递数据。

接收数据 重写onActivityResult()方法

@Override
protected void onActivityResult(int requestCode, int resultCode,Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode){
        case 1:
            if (requestCode == 1){
                String returnData = data.getStringExtra("data_return");
                Log.d("FirstActivity", returnData);
            }
            break;
        default:
            Log.d("FirstActivity", "fail");
    }
}

Activity生命周期

? 返回栈

启动活动,入栈。

按下Back或者调用finish(),出栈。

? 活动状态

4种状态

  1. 运行状态
  2. 暂停状态
  3. 停止状态
  4. 销毁状态

Activity的生存期

Activity类中定义了7个回调方法,覆盖了Activity生命周期的每一个环节。

  • onCeate() Activity被创建时调用

  • onStart() Activity由不可见变为可见的时候调用

  • onResume() Activity准备好和用户进行交互的时候调用,此时的Activity位于栈顶,且处于运行状态

  • onPause() 系统准备区启动或者恢复另一个Activity的时候调用

  • onStop() Activity完全不可见的时候调用

  • onDestory() Activity被销毁之前调用,之后Activity的状态变为销毁状态

  • onRestart() Activity由停止状态变为运行状态之前调用

三种生存期

  • 完整生存期 onCreate()方法和onDestory()方法之间所经历的。
  • 可见生存期 onStart()方法和onStop()方法之间所经历的。
  • 前台生存期 onResume()方法和onPause()方法之间所经历的。

数据回收

? 在Activity生命周期中,进入了停止状态,有可能被系统回收。

? 举个栗子:应用中有一个 Activity A ,用户在 Activity A 的基础上启动了 Activity B ,Activity A进入停止状态,此时由于系统资源不足,Activity A 被回收了,但用户按下 Back 返回 Activity A 时,会显示 Activity A ,但这时执行的不是onRestart()方法,而是执行 Activity A 的onCreate()方法,两个Activity A 其实是不同的,第一个Activity A 可能包含某些重要的数据,此时怎么办呢。

? 其实 Activity 中提供 onSaveInstanceState() 回调方法,此方法可以保证在Activity被回收之前一定会被调用,onSaveInstanceState() 有一个 Bundle 类型的参数, Bundle 提供了一系列的方法用于保存数据,如putString() 保存字符串,putInt() 保存整型数据 … ,保存时两个参数,一个是键,一个是想要保存的值。
此时已经将数据保存下来了,恢复的话也很简单,只是我们没有注意到而已,Activity 中的 onCreate()方法中就包含一个 Bundle 类型的参数,我们可以在 onCreate() 方法中判断是否为空,不为空的话就可以通过对应的取值方法获得数据。

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("key", "value");
    outState.putInt("int", 1);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.first_layout);
    if (savedInstanceState != null) {
        String str = savedInstanceState.getString("key");
        int num = savedInstanceState.getInt("int");
        Log.d(TAG, "onCreate: str: " + str);
        Log.d(TAG, "onCreate: num: " + num);
    }
}

Activity的启动模式

Activity 启动模式一共4种,standard、singleTop、singleTask、singleInstance,在AndropidManifest.xml 中通过 <activity> 标签指定 android:launchMode 属性来选择启动模式。

standard(默认)模式

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.first_layout);
    
    Log.d(TAG, "onCreate: "+ this.toString());
    
    Button button = findViewById(R.id.button_1);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
            startActivity(intent);
        }
    });
}
FirstActivity: onCreate: com.example.firstactivity.FirstActivity@9f9406d
FirstActivity: onCreate: com.example.firstactivity.FirstActivity@2c4413c
FirstActivity: onCreate: com.example.firstactivity.FirstActivity@43a5264

? 每次点击按钮就会创建一个新的FirstActivity并入栈,此时需要连续3次Back才能退出程序。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hs3qEWEE-1627977975407)(https://z3.ax1x.com/2021/08/03/fiCFVf.png)]

singleTop模式

<activity android:name=".FirstActivity" android:launchMode="singleTop">
    <intent-filter>
    	<action android:name="android.intent.action.MAIN"></action>
        <category android:name="android.intent.category.LAUNCHER"></category>
    </intent-filter>
</activity>
FirstActivity: onCreate: com.example.firstactivity.FirstActivity@4c7c0f0

Activity 在栈顶时并不会再创建新的实例,但当 Activity 不在栈顶时还是会创建新的实例。

//FirstActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.first_layout);
    
    Log.d(TAG, "onCreate: "+ this.toString());
    
    Button button = findViewById(R.id.button_1);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
            startActivity(intent);
        }
    });
}
//SecondActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.first_layout);
    
    Log.d(TAG, "onCreate: "+ this.toString());
    
    Button button = findViewById(R.id.button_1);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
            startActivity(intent);
        }
    });
}
FirstActivity: onCreate: com.example.firstactivity.FirstActivity@a00982
FirstActivity: onCreate: com.example.firstactivity.FirstActivity@10b1108
FirstActivity: onCreate: com.example.firstactivity.FirstActivity@18484be

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7O4BTvBt-1627977975408)(https://z3.ax1x.com/2021/08/03/fiibbq.png)]

singleTask模式

使用singlTop模式可以解决重复创建栈顶Activity的问题,但当Activity不处于栈顶时还是会创建多个实例。

singleTask模式则会向前搜索,若存在该 Activity ,依次出栈使该 Activity 处于栈顶从而启动 Activity 。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ooITjd3q-1627977975409)(https://z3.ax1x.com/2021/08/03/fiA58O.png)]

singleInstance模式

最复杂的一种启动模式,指定为singleInstance模式的Activity会启用一个新的返回栈来管理这个活动。

Log.d(TAG, " Task id is "+ getTaskId());

通过日志打印返回栈id发现 singleInstance 模式的SecondActivity处于不同的返回栈中。

FirstActivity:  Task id is 27
SecondActivity:  Task id is 28
ThirdActivity:  Task id is 27

ThirdActivity 点击 Back 返回时直接返回到了 FirstActivity ,再按 Back 返回才回到 SecondActivity 说明但主返回栈为空时才会显示另一个栈顶的 Activity。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tl1wInRZ-1627977975410)(https://z3.ax1x.com/2021/08/03/fiejmQ.png)]

直接退出程序

当Activity较多时需要多次点击Back,而Home键只是将程序挂起,并没有退出程序。

此时可以创建一个专门控制Activity的类来管理。

public class ActivityCollector {
    public static List<Activity> activityList = new ArrayList<>();

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

    public static void removeActvity(Activity activity){
        activityList.remove(activity);
    }

    public static void finishAll(){
        for (Activity activity:activityList) {
            if(!activity.isFinishing()){
                activity.finish();
                this.removeActvity(activity);
            }
        }
    }
}

在每个 Activity 的 onCreate()方法中调用 addActivity() ,在 onDestory() 方法中调用 removeActvity(),

但需要直接退出程序时,可以在某些按钮的点击事件上添加 finishAll() 方法

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-04 11:19:40  更:2021-08-04 11:21:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 12:32:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码