耶耶耶耶耶 发表于 2024-10-8 23:12:51

安卓Android ·移动应用开辟 创建第一个Android项目

可以先行看我的这篇 《安卓Android入门》
一、创建第一个Android项目

1.1 准备Android Studio

https://i-blog.csdnimg.cn/blog_migrate/03b69742cc5a4124004df1ddca1ce535.png
选择
https://i-blog.csdnimg.cn/blog_migrate/b33cc1641157f03ff7f45d11730eb76c.png
写信息
https://i-blog.csdnimg.cn/blog_migrate/e0092df011679eb77296a9cc1394b99e.png
等待构建Gradle
https://i-blog.csdnimg.cn/blog_migrate/56baf58affed85f4cace2ddea5b53c72.png
   可以选择我们的模仿器,甚至我们可以通过手机屏幕共享的方式,把手机的开辟者模式打开等操作,下载到本机手机之中,可以0隔断的感受,程序之美。
https://i-blog.csdnimg.cn/blog_migrate/ebd24e89cda872bed1c26215459d98f0.png
https://i-blog.csdnimg.cn/blog_migrate/8ab11191061a37c1fbbcf7ddaef2b82a.png
https://i-blog.csdnimg.cn/blog_migrate/87c13a5d84f2738e9c8d79751428738f.png
1.2 运行程序

https://i-blog.csdnimg.cn/blog_migrate/2ad2fa91d232eac734fd6631b80c088d.png
1.3 程序结构是什么

app下的结构

这种的结构化的项目简便明了,提高开辟效率和代码质量
https://i-blog.csdnimg.cn/blog_migrate/82af7bfa073c456f84324a3382dd7ab5.png
build - 编译时自动天生的文件
libs - 第三方jar包放在libs目次下
java - 放置所需Java
代码,自动天生了一个MainActivity 文件
1.3.2 res - 子目次(所有图片、布局、字符串等资源)

https://i-blog.csdnimg.cn/blog_migrate/21b675ed7778e3fa3c45917c60c13d79.png
调用方式:
[ 1 ] 通过Java
代码调用 ->
getResources().getDrawable(R.mipmap.ic_launcher);//调用mipmap文件夹中资源文件
getResources().getDrawable(R.drawable,icon); //调用以drawable开头的文件夹中的资源文件
[ 2 ] 通过XML布局调用
@mipmap/ic_launcher //调用mipmap文件夹中的资源文件
@drawable/icon //调用以 drawable开头的文件夹中的资源文件
   我们应该创建差别分辨率的目次,如drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等,并在制作程序时提供几个差别分辨率的版本,是为了适应差别设备的屏幕密度和分辨率
https://i-blog.csdnimg.cn/blog_migrate/c4fafac2a7d7184976812dd0dafc8c24.png
打开我们的子目次
https://i-blog.csdnimg.cn/blog_migrate/1c8ac21adc1727a98eb409362730f4a1.png
这内里就是我们配置的字符串,调用利用,不用全局在中出现相同的多次构建。在res/values/目次中的strings.xml文件中定义字符串
https://i-blog.csdnimg.cn/blog_migrate/323eb063d9e12e615dd042409c4f02cf.png
怎么构建
在XML中通过@string/app_name可以获得该字符串的引用。
https://i-blog.csdnimg.cn/blog_migrate/d9a35ad2824f2dde5fc6bedad31886f8.png
最终
https://i-blog.csdnimg.cn/blog_migrate/2dc5e7e9f567ce08787f5034313f774e.png
点击可以替换
https://i-blog.csdnimg.cn/blog_migrate/b2d64c6d850b07027e3dd36acdea3d2d.png
主题是包罗一种或多种的格式化属性聚集,可改变窗体的样式,对整个应用或某个Activity存在全局性影响。
在res/values目次下的styles.xml文件中
<resources>
        <!-- Base application theme.-->
        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
                <!-- Customize your theme here.-->
                <item name="colorPrimary">@color/colorPrimary
</item>
                <item name="colorPrimaryDark">@color/colorPrimary
Dark</item>
                <item name="colorAccent">@color/colorAccent</item>
        </style>
</resources>
在根元素中可以包罗多个标签,每个
标签中也可以包罗多个标签。 (1)在AndroidManifest.xml中设置主题的
<application
        ···
        android:theme ="@style/AppTheme">
</application>
(2)在Java
代码中设置主题的
setTheme(R.style.AppTheme);
通过改变主题可以改变整个窗体样式,但不能设置View控件的具体样式,因此创建一个样式来美化View控件,放在res/values目次下的styles.xml文件中
<resources>
        <style name="textViewSytle">
                <item name="android:layout_width">20dp</item>
                <item name="android:layout_height">20dp</item>
                <item name="android:background">#f54e39</item>
        </style>
</resources>
在布局文件的View控件中通过style属性调用
<TextView
        style="estyle/textViewSytle"/>
颜色资源通常定义在res/values/colors.xml文件中
<?xml version="1.0" encoding="utf-8"?>
<resources>
        <color name="colorPrimary">#3F51B5</color>
        <color name="colorPrimaryDark">#303F9F</color>
        <color name="colorAccent">#FF4081</color>
</resources>
1.通过Java
代码调用颜色资源文件
getResources().getColor(R.color,colorPrimary);
2.在XML布局文件中调用颜色资源文件
@color/colorPrimary
颜色值必须以“#”开头,“#”后面表现Alpha-Red-Green-Blue情势的内容。此中,Alpha值可以省略,如果省略,表现颜色默认是完全不透明的。
·#RGB:利用红、绿、蓝三原色的值定义颜色,此中,红、绿、蓝分别利用0~f的十六进制数值表现。
·#ARGB:利用透明度以及红、绿、蓝三原色来定义颜色,此中,透明度、红、绿、蓝分别利用0~f的十六进制数值表现。
尺寸资源通常定义在res/values/dimens.xml文件中
要手动创建dimens创建dimens.xml文件,
<resources>
        <dimen name="activity_horizontal_margin">16dp</dimen>
        <dimen name="activity_vertical_margin">16dp</dimen>
</resources>
<dimen></dimen>标签用于定义尺寸资源,此中name属性指定尺寸资源的名称。标签中心设置的是尺寸大小。在dimens.xml文件中只能有一个根元素,根元素可以包罗多个<dimen></dimen>标签。
1.通过Java
代码调用尺寸资源
getResources().getDimension(R,dimen.activity_horizontal_margin);
2.在XML布局文件中调用尺寸资源
@dimen/activity_horizontal_margin
   px (pixels, 像素):像素是屏幕上的一个点,是最基本的屏幕单元。
dp(density-independent pixels, 设备独立像素):
dp是与屏幕密度无关的单元。dp单元可以根据屏幕的密度自动调整大小,使得界面元素在差别分辨率的设备上保持大致相同的物理尺寸。
sp (scaled pixels, 比例像素):
sp主要用于设置字体大小,它会根据用户的字体大小首选项进行缩放。sp与dp类似,都能根据差别的屏幕密度进行适配,但sp还会根据用户设置的系统字体大小进行调整,因此更得当用作字体大小的单元。
in (inches, 英寸):英寸是一个标准的长度单元,常用于描述屏幕大小。
pt(points, 磅): 磅是一个屏幕物理长度单元,1磅等于1/72英寸。
mm (millimeters, 毫米):毫米也是一个屏幕物理长度单元。
AndroidManifest.xml 有四大组件,程序添加权限声明

https://i-blog.csdnimg.cn/blog_migrate/0f73b01ba6375e350f43356609368fc9.png
MainActivity
https://i-blog.csdnimg.cn/blog_migrate/a8e89f2b81c3c984f2aaf2a04980b9ec.png
res/layout 目次下的activity_main.xml
https://i-blog.csdnimg.cn/blog_migrate/33ab1e584985ca02847acde2e5056faf.png
Project下的结构

https://i-blog.csdnimg.cn/blog_migrate/cc735aded385d24e8c38ec7d91349790.png

[*] .gradle 文件夹:包罗Gradle构建系统天生的缓存文件和暂时文件。
[*] .idea 文件夹:包罗项目相关的IDE配置文件,如编译器设置、运行配置等。
[*] app 文件夹:是Android应用程序的主要代码和资源目次。
[*] - java 文件夹:包含Java
源代码文件。

- res 文件夹:包含应用程序所需的资源文件,如布局文件、图像文件、字符串等。

- AndroidManifest.xml 文件:包含应用程序的清单文件,定义了应用程序的基本信息、权限、组件、界面等。


[*] test 文件夹:包罗单元测试的源代码和资源文件。
[*] androidTest 文件夹:包罗Android测试的源代码和资源文件。
[*] build.gradle 文件:定义了应用程序的构建配置,包罗依赖项、版本号等。
[*] proguard-rules.pro 文件:定义了肴杂规则,用于在发布时压缩、优化和肴杂应用程序的代码。

[*] build 文件夹:包罗构建天生的输出文件,如APK文件、中心文件等。
[*] gradle 文件夹:包罗Gradle构建系统的配置文件和插件。

[*] wrapper 文件夹:包罗Gradle的包装器文件,用于自动下载和管理Gradle的版本。
[*] .gitignore 版本控制
[*]
[*] build.gradle 文件:定义了项目级别的构建配置,如Gradle版本、插件等。
[*] gradle.properties 文件:包罗Gradle属性的配置文件。
[*] gradlew 和 gradlew.bat 文件:Gradle的下令行构建脚本,可在下令行界面中利用。

[*] settings.gradle 文件:定义了项目的模块和构建立置。
这是Android Studio项目的基本目次结构,此中最重要的部门是app 文件夹,它包罗了应用程序的源代码和资源文件。其他文件夹和文件用于项目的构建和配置。
二、开辟android时,部门库下载异常慢

2.1 项目中更换下载仓库

maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/google/' }
maven { url 'https://maven.aliyun.com/repository/jcenter/' }
maven { url 'https://maven.aliyun.com/repository/central/' }
https://i-blog.csdnimg.cn/blog_migrate/40d748746ebd4e6221d22c5ca86bd726.png
2.2 离线模式配置 Gradle

   将 Gradle.zip 解压到 “C:\User\你的用户名.gradle\wrapper\dists” 下,最终路径为: “C:\User\你的用户名.gradle\wrapper\dists\gradle-7.4-bin” 和 “C:\User\你的用户名.gradle\wrapper\dists\gradle-8.0-bin”
三、Kotlin
代码(本篇Android项目不会涉及用kotlin创建文件,先先容后续再涉及)

https://i-blog.csdnimg.cn/blog_migrate/200546cbcdf2251a8946f7fbb7ce251e.png
https://i-blog.csdnimg.cn/blog_migrate/4b3fcd8b0cffca4c3793bee058430c7f.png
3.1 变量

利用val(value 的简写)声明一个变量时,该变量被视为不可变的,即在初始赋值之后无法重新赋值。这类似于Java
中的final变量。
利用var(variable 的简写)声明一个变量时,该变量被视为可变的,即在初始赋值之后仍旧可以重新赋值。这类似于Java
中的非final变量。
   Kotlin
中没有底子数据类型,只有封装的数字类型,你每定义的一个变量,着实 Kotlin
帮你封装了一个对象,这样可以包管不会出现空指针。
# 显式地声明了变量a为Int类型
val a: Int = 10
https://i-blog.csdnimg.cn/blog_migrate/0de4ca14afc7342c2225690e44bdbe06.png
3.2 函数

参数的声明格式是“参数名: 参数类型”,此中参数名也是可以随便定义的
fun main() {
    println(fun1(1, 2))
}
fun fun1(num1:Int,num2: Int):Int{
    return num1+num2
}

3.3 条件控制

3.3.1 if条件语句

var value = 0
if (num1 > num2) {
value = num1
} else {
value = num2
}
Kotlin
中的if语句相比于Java
有一个额外的功能,它是可以有返回值的
val result = if (条件表达式) {
    // 如果条件为真,则返回这里的值
} else {
    // 如果条件为假,则返回这里的值
}
例子
fun fun1(num1: Int, num2: Int): Int {
return if (num1 > num2) {
num1
} else {
num2
}
}
fun fun1(num1: Int, num2: Int) = if (num1 > num2) {
num1
} else {
num2
}
再次
val max = if (a > b) a else b
fun fun1(num1: Int, num2: Int)= if (num1 > num2) num1 else num2
3.3.2 when条件语句

这种直通式
匹配值 -> { 执行逻辑 }
when (条件表达式) {
    值1 -> {
      // 如果条件匹配值1,则执行这里的代码块
    }
    值2 -> {
      // 如果条件匹配值2,则执行这里的代码块
    }
    else -> {
      // 如果条件都不匹配,则执行这里的代码块
    }
}
is关键字就是类型匹配的核心,相当于Java
中的instanceof关键字。

when (num) {
is Int -> println("number is Int")
is Double -> println("number is Double")
else -> println("number not support")
}
3.4 for-in循环

kotlin的while和Java
中的while循环没有任何区别
fun main() {
    val range = 0..10
    for (i in range step 2) {
      println(i)
    }
}
利用step跳过区间内的元素

https://i-blog.csdnimg.cn/blog_migrate/fe2a59fbba81dcf335fee4252600ffdc.png
可以利用until关键字来创建一个左闭右开的区间,

https://i-blog.csdnimg.cn/blog_migrate/45ed7c27b09a0e9505b5587e1d79c606.png
downTo遍历降序区间

https://i-blog.csdnimg.cn/blog_migrate/c8a3453a0804f6e5ce98411bc2803469.png
3.5 面向对象编程

class Person {
    var name: String = ""
      var age=0

    fun show(){
      println("Name: $name, Age: $age")
      println(name +"is" + age + " years old.")

    }
}

fun main() {
    val p = Person()
    p.name = "Alice"
    p.age = 30
    p.show() // Output: Name: Alice, Age: 30
}
第一个打印语句利用了字符串模板(                                 n                         a                         m                         e                         和                              name和                  name和age),将属性name和age的值插入到输出语句中,打印出"Name: Alice, Age: 30"。
第二个打印语句利用了字符串拼接(name +“is” + age + " years old.“),将属性name、字符串"is”、属性age和字符串" years old.“拼接在一起,打印出"Alice is 30 years old.”。
3.5.1 继承

在Person类的前面加上open关键字就可以了
要让Student类继承Person类
在Java
中继承的关键字是extends,而在Kotlin
中是一个冒号
open class Person {
    var name: String = ""
      var age=0

    fun show(){
      println("Name: $name, Age: $age")
      println(name +"is" + age + " years old.")

    }
}
class Student :Person(){

    var grade:Int=0
    fun shows(){
      println("Name: $name, Age: $age, Grade: $grade")
         }

}
fun main() {
    val s=Student()
    s.name="Bob"
    s.age=20
    s.grade=3
    s.shows() //Output: Name: Bob, Age: 20, Grade: 3
}
同样的我们也可以继承于Java


https://i-blog.csdnimg.cn/blog_migrate/f24727738f55d66f21923827580e7482.png
java
public class cc {
    private String name;
    privateint age;

    public cc() {
    }

    public cc(String name, int age) {
      this.name = name;
      this.age = age;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public int getAge() {
      return age;
    }

    public void setAge(int age) {
      this.age = age;
    }
}

kotlin
class Student : cc() {

    var grade: Int = 0

    fun shows() {
      println("Name: $name, Age: $age, Grade: $grade")
    }

}

fun main() {

    val s = Student()
    s.name = "Bob"
    s.age = 20
    s.grade = 3
    s.shows() //Output: Name: Bob, Age: 20, Grade: 3
}

Open 继承

如果你希望在 Kotlin
中继承某个 Java
类,
        需要手动在 Kotlin
代码中为该类添加 open 修饰符,
        以明确表明该类是可继承的。
如果一个类不是专门为继承而设计的,
        那么就应该主动将它加上final声明,禁止它可以被继承。
在 Kotlin
中,默认情况下,所有类都是 final 的,即它们不能被继承。相比之下,Java
中的类默认是可以被继承的,除非利用了 final 关键字显式地克制继承。
当你在 Kotlin
中继承一个 Java
类时,Kotlin
并不会隐式地为 Java
类添加 open 修饰符。这是因为 Kotlin
不会假设 Java
类的设计者希望允许继承,因此需要在 Kotlin
中显式地利用 open 关键字来指示类是可继承的。
我们观察一下用Java
和Kotlin
分别创建的安卓项目的主活动

Kotlin
https://i-blog.csdnimg.cn/blog_migrate/7e2843d2d0daa9f19944f302d2dbd8bd.png
Java
https://i-blog.csdnimg.cn/blog_migrate/74fd6052c3966d2e6c70696c3214457d.png
四、活动(本篇以Java
代码,先行先容)

活动是安卓应用的主要组件之一,安卓中的活动(Activity)是指用户交互界面的一部分,它通常对应应用程序中的一个屏幕。
通过管理活动的生命周期(创建、启动、恢复、暂停、停止和销毁),我们作为开辟者可以控制活动的状态和行为。
活动之间可以通过意图(Intent)进行跳转和通信。
把各种控件和视图,按钮、文本框、图像等联系起来,启动其他活动或从其他活动返回,用户可以在差别的界面之间进行切换和交互。
总之,活动作为安卓应用程序的一个重要组件,负责用户界面的展示和交互处理,使得用户可以与应用程序进行互动。
4.1 创建活动

在com.example.hellowolrd包下 ->New ->Activity ->Empty Activity
https://i-blog.csdnimg.cn/blog_migrate/3fa741049b437bcb05e305a9d241e53c.png
我们的两个活动:
https://i-blog.csdnimg.cn/blog_migrate/b5b2a2fc9c8acd7668b24792ec17d487.png
4.1.1 Android Studio 会自动在AndroidManifest文件中注册

我们打开app/src/main/AndroidManifest.xml文件代码如下所示:
https://i-blog.csdnimg.cn/blog_migrate/46fabc3caa826a26dc4cd54b2c483f7b.png
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >

    <application
      android:allowBackup="true"
      android:dataExtractionRules="@xml/data_extraction_rules"
      android:fullBackupContent="@xml/backup_rules"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true"
      android:theme="@style/Theme.MyApplication"
      tools:targetApi="31" >
      
      <activity
            android:name=".OtherActivity"
            android:exported="false" />
            
      <activity
            android:name=".MainActivity"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
      </activity>
      
    </application>

</manifest>
4.1.2 活动中利用Toast

Toast会在屏幕上表现一段时间,用于在应用程序的界面上表现一条简短的消息,然后自动消散。
写法

// 要显示的消息文本
String message = "Hello, Toast!";
// 创建并显示Toast
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
当调用makeText()方法,并通过链式调用show()方法来创建并表现Toast。getApplicationContext()是一种获取当前活动上下文的方法,可以在活动中利用。
需要留意的是,Toast的 makeText()方法返回的是一个Toast对象,可以通过调用show()方法来表现。
在调用show()方法后,Toast会在屏幕上表现一段时间,然后自动消散。
   Java

https://i-blog.csdnimg.cn/blog_migrate/21c132dbb6ed86c23630f3566396b733.png
    Kotlin

https://i-blog.csdnimg.cn/blog_migrate/7b82af1d11739f0e044d497c100331ad.png
val button1: Button = findViewById(R.id.button12)
button1.setOnClickListener {
    Toast.makeText(this, "Yes", Toast.LENGTH_LONG).show() }
LENGTH_SHORT=0


   短时间的Toast

LENGTH_LONG = 1


   长时间的Toast

4.1.3 销毁活动

Activity类提供了一个finish()
延迟销毁
package com.example.myapplication;


import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class OtherActivity extends AppCompatActivity {

    private Button button1;
    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_other);
      button1 = findViewById(R.id.button1);

      button1.setOnClickListener(v -> {
            Toast.makeText(this, "TestOther", Toast.LENGTH_SHORT).show();
            handler.postDelayed(() -> finish(), 2000);
      });
    }
}


   finishmp4

4.2 Intent 跨越活动

4.2.1 表现的Intent

先创建一个新的活动,并在其绑定创建的layout文件之中简朴的放置一个按钮,目的是在跳转的时候直观的有显着的体验
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class OtherActivity extends AppCompatActivity {

    private Button button1;
    private Handler handler = new Handler();

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

      button1 = findViewById(R.id.button1);

      button1.setOnClickListener(v -> {
            Toast.makeText(this, "TestOther", Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(OtherActivity.this, SecondActivity.class);
            // 在延迟2秒后执行 finish() 和 startActivity()
            handler.postDelayed(() -> {
                finish();
                startActivity(intent);
            }, 2000);
      });
    }
}


   Intent跳转其他活动

4.2.2 隐式Intent

我们在当前文件在指定出来我们可以转向的动作名称
https://i-blog.csdnimg.cn/blog_migrate/7ec4fdfc418ec85132171931dbeee846.png
button1.setOnClickListener(v -> {
   Toast.makeText(this, "TestOther", Toast.LENGTH_SHORT).show();
   Intent intent = new Intent("x111");
   startActivity(intent);
      });

我们还可以跳转到其他地方,如网页(这和我们平时的app如出一辙)

button1.setOnClickListener(v-> {
   Intent intent =new Intent(Intent.ACTION_VIEW);
   intent.setData(Uri.parse("http://www.baidu.com"));
   startActivity(intent);
      });
点击按钮后,创建了一个意图(Intent)并设置了其动作(Action)为Intent.ACTION_VIEW,同时指定了要检察的数据是一个URL,即http://www.baidu.com。系统收到这个意图后,会识别出这是一个网页链接,并自动利用默认的Web欣赏器打开百度网站页面。同样地,如果intent指向的是一个电话号码大概一个本地文件(如图片、视频等),则相应程序(拨号器或媒体播放器等)会被唤起以处理这些数据。
https://i-blog.csdnimg.cn/blog_migrate/78f68ffb13095f6a8b124c9031b563a2.png
https://i-blog.csdnimg.cn/blog_migrate/5fee373a444aa7595a218862928d0c1d.png
4.2.3Action 和 Category

在Android中,Action 和 Category 是 Intent 的重要组成部分,
        它们用于定义和过滤应用程序间交互的行为意图(Intent)。
Action 描述了Intent的主要动作或目的。例如,发送一个电子邮件可以利用 ACTION_SEND 动作;打开网页可以利用 ACTION_VIEW 动作等。
Category 为Intent添加了额外的上下文信息,进一步描述了Intent的应用场景或意图所属的种别
https://i-blog.csdnimg.cn/blog_migrate/a12011590f6809ecf3156b7db0c11206.png
一个Intent不但需要定义一个动作(如ACTION_MAIN),还需要至少一个种别(如CATEGORY_LAUNCHER),这样才能正确地匹配到相应的组件并触发相应的行为。在AndroidManifest.xml文件中,开辟者会在 标签内为Activity声明它可以相应哪些动作和种别组合。
4.2.4 通报给下一个活动数据

(1)发送活动方

//传递给下一个活动数据
button1.setOnClickListener(v -> {
             String data = "你会魔法吗✧(≖ ◡ ≖✿)";
          Intent intent = new Intent(OtherActivity.this, SecondActivity.class);
          intent.putExtra("exdata", data);
          startActivity(intent);
});
(2)担当活动方

@Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_second);
      Intent intent =getIntent();
      String data =intent.getStringExtra("exdata");
      Log.d("Sec",data);
    }
(3)打开日志Logcat

https://i-blog.csdnimg.cn/blog_migrate/67f0a3ccb596873e47ad82d701fa1450.png
4.2.5 返回数据给上一个活动

https://i-blog.csdnimg.cn/blog_migrate/b3122761c6411960560464d2ad439f1e.png
(1)副活动中

@Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_second);
      Intent intent =getIntent();
      String data =intent.getStringExtra("exdata");
      Log.d("Sec",data);


      Button buttonxx=findViewById(R.id.buttonxx);
      buttonxx.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent =new Intent();
                intent.putExtra("resdata","hello_你会魔法吗✧(≖ ◡ ≖✿)");
                setResult(RESULT_OK,intent);
                finish();
            }
      });

    }
(2)主活动

//传递给下一个活动数据
button1.setOnClickListener(v -> {
    String data = "你会魔法吗✧(≖ ◡ ≖✿)";
    Intent intent = new Intent(OtherActivity.this, SecondActivity.class);
    intent.putExtra("exdata", data);
    startActivityForResult(intent,1);
});
留意 startActivityForResult方法重写
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 1 && resultCode == RESULT_OK) {
       String reData = data.getStringExtra("resdata");
       // 在这里处理接收到的数据 reData
       Log.d("OtherActivity", reData);
    }
}
4.3 安卓 Activity生命周期

返回栈(back stack)是Android系统用于管理Activity的堆栈结构。当您启动一个新的Activity时,它会被放置在返回栈的顶部,并成为当前正在运行的Activity。如果按下返回按钮或调用finish()方法关闭当前Activity,那么前一个Activity将从返回栈中弹出并恢复到前台。
   栈是一种后进先出(LIFO)的数据结构,用于管理活动(Activity)在Android应用程序中的顺序。当启动一个新活动时,它会被添加到返回栈的栈顶位置,并成为当前正在运行的活动。而当按下返回按钮或调用finish()方法销毁当前活动时,位于栈顶的活动将从栈中弹出,然后前一个入栈的活动将成为新的栈顶,并重新表现给用户。
4.3.1 概述

https://i-blog.csdnimg.cn/blog_migrate/7ecb9b76f0577f557aa89949e4f76506.png
   Android Activity生命周期的各个状态及其转换关系
https://i-blog.csdnimg.cn/blog_migrate/660c8fd8764e92115671e73be6fbcd25.png

[*] 创建阶段

[*]onCreate(Bundle savedInstanceState): 活动第一次被创建时调用,进行初始化工作。
[*]onStart(): 表现活动正在启动,即将变为可见状态。
[*]onResume(): 活动已开始与用户交互,并处于运行状态。

[*] 运行阶段

[*]在onResume()之后,Activity处于运行状态。

[*] 暂停阶段

[*]onPause(): 当有新的Activity启动并覆盖当前Activity或当前Activity不再位于前台时调用。

[*] 停止阶段

[*]onStop(): 当Activity完全不可见时调用。

[*] 恢复/重启阶段

[*]onRestart(): 如果Activity之前被停止而现在重新回到前台,会先调用此方法,然后经历onStart()和onResume()。

[*] 销毁阶段

[*]onDestroy(): 在Activity被系统决定彻底销毁前调用,用于释放资源。

[*] 其他回调方法:

[*]onSaveInstanceState(Bundle outState): 保存暂时性数据以备在Activity重修时恢复。
[*]onRestoreInstanceState(Bundle savedInstanceState): 用于还原之前保存的状态。

4.3.2 过程

   留意如果我们启动的时候不是这个想要看的内容,大概和主启动活动有关
    我们在https://i-blog.csdnimg.cn/blog_migrate/fbbd1546e50f72f02874823e4d203f78.png
修改
https://i-blog.csdnimg.cn/blog_migrate/33981e18976ee559dc756bd9048c1fed.png
(1)创建活动,并简朴的xml配个botton

https://i-blog.csdnimg.cn/blog_migrate/c1d28a13fefc9e997d9ec60cde8ea7fb.png
(2)主活动

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    public static final String TAG = "MainActivity";

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

      Button startNormalActivity = findViewById(R.id.ShowActivity);
      Button startDialogActivity = findViewById(R.id.ShowActivity2);

      startNormalActivity.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, ShowActivity.class);
            startActivity(intent);
      });

      startDialogActivity.setOnClickListener(v -> {
            Intent intent = new Intent(MainActivity.this, ShowActivity2.class);
            startActivity(intent);
      });
    }

    @Override
    protected void onStart() {
      super.onStart();
      Log.d(TAG, "onStart");
    }

    @Override
    protected void onResume() {
      super.onResume();
      Log.d(TAG, "onResume");
    }

    @Override
    protected void onPause() {
      super.onPause();
      Log.d(TAG, "onPause");
    }

    @Override
    protected void onStop() {
      super.onStop();
      Log.d(TAG, "onStop");
    }

    @Override
    protected void onDestroy() {
      super.onDestroy();
      Log.d(TAG, "onDestroy");
    }

    @Override
    protected void onRestart() {
      super.onRestart();
      Log.d(TAG, "onRestart");
    }
}


(3)启动假造机,看日志Logcat

我们需要点击任意一个按钮,并回退(返回键)
观察日志的内容
https://i-blog.csdnimg.cn/blog_migrate/c0a72bf55001d8ec0c8dfd2ebf01c951.png
4.2.4 在 Android 中,onRestart() 方法和 onDestroy() 方法的调用是由系统根据 Activity 的生命周期状态变化来决定的。

onRestart():
当用户从后台返回到前台时(即通过按“近来应用”按钮或HOME键离开Activity后再次回到该Activity),Activity 会经历 onPause() -> onStop() -> onRestart() 这样的生命周期变化。因此,如果你的日志中没有表现 onRestart(),大概是因为你直接启动了 Activity 而没有先将其推入后台,大概是在后台被系统回收掉了。
onDestroy():
onDestroy() 在 Activity 终止之前调用,通常发生在系统资源告急需要释放 Activity、应用程序自身调用了 finish() 方法大概是整个应用程序进程被终止等情况。
如果你的 Activity 是程序的主入口,并且你没有手动结束它大概系统没有强制结束它,那么在整个应用程序运行期间,onDestroy() 大概不会被调用。
如果你在测试时仅仅是在应用之间切换大概只是简朴地打开并检察 Activity,而没有做进一步的操作导致 Activity 销毁,则 onDestroy() 不会被调用。
对于 onRestart(),先让 Activity 进入后台(如点击 Home 按钮或打开其他应用),然后再重新启动这个 Activity,这时应该能看到日志输出。
对于 onDestroy(),可以通过模仿系统资源告急环境(例如利用开辟者选项中的“不保存活动”功能)大概在代码中显式调用 finish() 来销毁当前 Activity,从而触发 onDestroy() 日志记录
4.4 活动被回收了怎么办(GPT)

Android Activity 回收与恢复策略
在Android中,当系统资源告急时,Activity大概会因内存不足而被回收(destroy)。为应对这种情况并确保应用能够正确恢复用户界面和数据,可以采用以下几种方法:
4.4.1. 保存和恢复数据

在onSaveInstanceState(Bundle outState)方法中保存关键数据,以便在Activity重新创建时通过onCreate(Bundle savedInstanceState)或onRestoreInstanceState(Bundle savedInstanceState)恢复这些数据。
   @Override
   protected void onSaveInstanceState(Bundle outState) {
       super.onSaveInstanceState(outState);
       // 保存数据到Bundle
       outState.putInt("key", someImportantValue);
   }

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

       if (savedInstanceState != null) {
         // 恢复数据
         int importantValue = savedInstanceState.getInt("key");
         // 使用恢复的数据...
       }
   }
   
4.4.2. 利用ViewModel

借助Android架构组件中的ViewModel类,可以在配置更改或Activity生命周期变化时保持UI相关数据的长期性。纵然Activity被销毁,ViewModel中的数据也能保存下来。
   public class MyViewModel extends ViewModel {
       private MutableLiveData<Integer> someLiveData;

       public MutableLiveData<Integer> getSomeLiveData() {
         if (someLiveData == null) {
               someLiveData = new MutableLiveData<>();
               // 初始化数据...
         }
         return someLiveData;
       }
   }

   public class MainActivity extends AppCompatActivity {
       private MyViewModel viewModel;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         viewModel = new ViewModelProvider(this).get(MyViewModel.class);
         viewModel.getSomeLiveData().observe(this, value -> {
               // 更新UI...
         });
       }
   }
   
4.4.3. 长期化数据

对于需要恒久保存的重要数据,可将其长期化至数据库、SharedPreferences或其他文件存储中。
4.4.4. 处理返回结果

如果Activity是通过startActivityForResult启动的,则需在onActivityResult中处理结果,即便Activity在获取结果前被销毁过。
4.5 启动模式

安卓的启动模式主要有以下几种:

[*]standard(标准模式):默认的启动模式,每次启动都会创建一个新的实例。
[*]singleTop(单顶部模式):如果目标Activity已经在任务栈的顶部,则不会创建新的实例,而是调用目标Activity的onNewIntent()方法。
[*]singleTask(单任务模式):只能存在一个实例,如果该实例已经存在,则将其调至栈顶,并扫除其上方所有Activity。
[*]singleInstance(单独实例模式):类似于singleTask,但具有更高的隔离性,即该Activity只能与自己在一个任务栈中存在。
这些启动模式可以通过在AndroidManifest.xml文件中利用<activity>标签来指定 android: launchMode。每个Activity可以选择得当自身需求的启动模式。
4.5.1 standard (默认)

创建新实例、栈顶、默认的启动方式
standard(标准模式)是Android中默认的启动模式。在该模式下,每次启动Activity都会创建一个新的实例,并将其放入任务栈中。
当我们通过Intent启动一个Activity时,系统会创建该Activity的新实例,并将其放置在当前任务栈的顶部。
如果目标Activity已经存在于任务栈中,则系统会创建一个新的实例并将其放在之前实例之上。
在标准模式下,多个相同类型的Activity可以同时存在于同一任务栈中。
每个实例都是独立的,并且它们彼此没有直接影响。
   例如,假设我们有一个应用程序包罗两个Activity:Activity A和Activity B。
当我们从A启动B时,系统会创建一个新的B实例并将其放入任务栈顶部。
如果我们再次从A启动B,则会创建另一个B实例并放在之前实例之上。

   standard模式

   https://i-blog.csdnimg.cn/blog_migrate/c2f4cf631167d97ff859cfd036c14277.png

   每次的新实例

4.5.2 singleTop(对于当前非栈顶活动来说启动时会创建出一个新的实例)

singleTop是一种Activity启动模式,它指定一个Activity在栈顶时不会被重复创建,而是复用已存在的实例。如果要启动的Activity已经位于栈顶,则不会创建新的实例,而是调用其onNewIntent()方法进行更新。如果要启动的Activity不在栈顶,则会创建新的实例并将其放置在栈顶。
利用singleTop模式可以避免创建多个相同的Activity实例,提高了应用程序的性能和效率。这种模式得当用于处理独立且相互独立的任务或页面,比如检察文章、打开设置等。
在AndroidManifest.xml中可以通过设置launchMode属性为"singleTop"来指定该Activity的启动模式为singleTop。例如:
<activity android:name=".YourActivity"
    android:launchMode="singleTop">
</activity>
https://i-blog.csdnimg.cn/blog_migrate/1abb513a22d7fb4f67fec100529db046.png
需要留意的是,在利用singleTop模式时,如果有其他Activity位于目标Activity之上,并且这些中心层级的Activity也是利用了singleTop大概singleTask启动模式,则依然会创建新的实例。因此,在设计应用程序架构时需谨慎选择合适的启动模式以满足需求。
就是在这一个页面上,不会再次创建

   singleTop

4.5.3 singleTask

在Android中,singleTask是一种启动模式,它定义了一个Activity的任务栈只能有一个实例。当利用singleTask启动模式时,如果已经存在该Activity的实例,则系统会将该任务栈上位于该Activity之上的其他所有Activity扫除掉,并调用该Activity的onNewIntent()方法来通报新的意图。
具体来说,利用singleTask启动模式时,如果要启动一个Activity:

[*]如果当前任务栈中不存在该Activity的实例,则会创建一个新的实例,并将其入栈。
[*]如果当前任务栈中存在该Activity的实例,则会销毁该实例之上的所有其他Activity,并调用现有实例的onNewIntent()方法。
这种启动模式常用于作为应用程序的主界面大概入口页面,确保每次打开应用都会进入同一个特定界面。
   结构
https://i-blog.csdnimg.cn/blog_migrate/bc87bb683330104c49d683b396a1abc2.png
package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Log.d("FirstActivity", this.toString());
      setContentView(R.layout.activity_first);

      Button button =findViewById(R.id.button);
      button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent =new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
      });
    }

    @Override
    protected void onDestroy() {
      super.onDestroy();
      Log.d("fir","onfirDestroy");
    }

}

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Log.d("SecondActivity", this.toString());
      setContentView(R.layout.activity_second);

      Button button=findViewById(R.id.button2);
      button.setOnClickListener(v -> {
            Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
            startActivity(intent);
      });
    }

    @Override
    protected void onRestart() {
      super.onRestart();
      Log.d("sec","onRestart");
    }
}
在xml中
https://i-blog.csdnimg.cn/blog_migrate/633a3cca100cd591e4cd088e5edb3946.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 安卓Android ·移动应用开辟 创建第一个Android项目