Android Activity 与 SubActivity 通信笔记
程序员文章站
2022-05-14 08:05:33
...
Goal
- 主 Activity 界面上有一个“登录”按钮和一个用了显示信息的 TextView
- 点击“登录”按钮后打开一个 SubActivity,SubActivity 上面有输入用户名和密码的控件
- 在用户关闭(按返回键)这个 SubActivity 后,将用户输入的用户名和密码传递到主 Activity,并显示在主 Activity 的 TextView 中
Reference
Notes
- AndroidManifest.xml 大概用来声明这个程序包含了什么东西,包括 activity(界面?)、service(后台服务)等;
-
R
这个类是自动生成的,用于索引声明的各种类型的资源,如layout
、string
等,即在 android studio 的工程树里res
目录里的东西; -
Intent
这个类就是专业传消息,可以用于启动 activity 、子 activity 返回数据、发广播、程序间传递信息;除了用Uri
类装信息外,还可以用函数putExtra(String key, String value)
加装若干键-值对形式的附加数据;用Uri
装的数据用getData()
获取;
Code
AndroidManifest.xml
- 注册(声明)程序组件的文件
- 用到两个 activity,这两个 activity 都要在
AndroidManifest.xml
中注册(就是声明的意思吧,先声明后调用),即在<application>
标签里加入两个相应的<activity>
的子标签 - 其中
@string/app_name
表明其引用(可能@
表示引用,类似在 QQ 上 @ 个人)了string
中一个叫做app_name
的资源,相对应地,在res
目录中的values
子目录中的strings.xml
文件中就应有一行形如<string name="app_name">某某某</string>
的内容;@style/AppTheme
类似
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.tompany.tom.biscuit">
<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/AppTheme"> <!-- 资源引用 -->
<!-- 主 Activity -->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 子 Activity -->
<activity android:name=".LoginActivity"
android:label="@string/login_ac_name">
</activity>
</application>
</manifest>
MainActivity.java
- 该 activity 中通过
btn.setOnClickListener(View.OnClickListener)
设置按钮的监听器(Listener),设置当按下按钮后的反应 - 在此之前要先找到这个
btn
,通过findViewById(int)
;而在此之前,就要使这个 button 有个 id 才能通过R
这个类索引到,这是在与这个 activity 对应的界面配置文件(activity_main.xml
)中设置的事,后面给出 - 启动子 activity 有两个可选函数:
startActivity(Intent)
和startActivityForResult(Intent, int)
;前者打开一个独立的子 activity,不会返回数据给主 activity;而这里要实现子 activity 将输入的帐号和密码都传回给主 activity,就要用后者 -
startActivityForResult
比startActivity
多出一个整型的参数,叫request code
,大概作用是一个标记不同子 activity 的编号,因为主 activity 其实可以实现按不同的按钮呼出不同的子 activity,但只用惟一的一个函数onActivityResult
接收返回值,那么问题来了:这个返回值到底是哪个子 activity 传来的?我要对其做什么处理?这时就要用到request code
来辨别到底这个返回值是哪个子 activity 传来的 - 如上所述,
onActivityResult(int, int, Intent)
就是那个统一(也是惟一的)接收子 activity 返回值的函数,第 1 个参数就是上述的request code
;第 2 个参数是result code
,大概是告诉主 activity 说子 activity 的执行过程 O 不 OK(吧?);第 3 个参数就是子 activity 传回来的返回值
package org.tompany.tom.biscuit;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
static final String TAG = "LIFE_CYCLE";
// 标记 LoginActivity 这个子 activity 的整型编码
static final int LOGIN_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "(1) onCreate(Bundle)");
// 通过 R 索引 login_btn
Button btn = (Button)findViewById(R.id.login_btn);
// 设置监听器
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(MainActivity.this, LoginActivity.class);
// 启动子 activity
startActivityForResult(i, LOGIN_CODE);
}
});
}
@Override
// 接收子 activity 的返回值
public void onActivityResult(int reqC, int resC, Intent dt) {
super.onActivityResult(reqC, resC, dt);
switch(reqC) {
case LOGIN_CODE: // 如果是 LoginActivity 传回来的
TextView tv = (TextView)findViewById(R.id.show_txt);
tv.setText(dt.getDataString());
break;
}
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "(2) onStart()");
}
@Override
protected void onRestoreInstanceState(Bundle st) {
super.onRestoreInstanceState(st);
Log.i(TAG, "(3) onRestoreInstanceState(Bundle)");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "(4) onREsume()");
}
@Override
protected void onSaveInstanceState(Bundle st) {
super.onPause();
Log.i(TAG, "(5) onSaveInstanceState(Bundle)");
}
@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "(6) onRestart()");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "(7) onPause()");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "(8) onStop()");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "(9) onDestroy()");
}
}
activity_main.xml
- 这是与
MainActivity.java
对应的页面文件,在res
目录的layout
子目录下,界面里用到什么组件都要在这注册,类似于AndroidManifest.xml
那样的作用,只不过是用来声明图形组件 - 界面都会根据这种 xml 文件自动生成,可以直接改 xml 的内容,也可以用可视化的拖组件的方法
-
@+id/show_txt
类似之前的@string/某
,也是一种资源引用,有个+
号,因为这个组件是第一次出现,之前没有这个 id 资源,要新加进去,+
号大概就是添加的意思,加了之后就可以在代码中用R
这个类去索引它
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.tompany.tom.biscuit.MainActivity">
<!-- 新增一个 TextView 组件 -->
<TextView android:id="@+id/show_txt"
android:text="@string/show_txt_ini"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="27dip" />
<!-- MainActivity.java 中引用的 login_btn
这个 id 就是这里引进的 -->
<Button android:id="@+id/login_btn"
android:text="@string/login_btn_txt"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/show_txt"
android:layout_marginTop="10dip"
android:layout_marginLeft="7dip" />
</RelativeLayout>
LoginActivity.java
- 子 activity 的代码
-
onBackPressed()
在按返回键的时候执行 -
setResult(int, Intent)
是设置返回值,第 1 个参数是result code
,表明执行过程是否顺利;第 2 个是传回给主 activity 的返回值
package org.tompany.tom.biscuit;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.EditText;
public class LoginActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}
@Override
// 按返回键
public void onBackPressed() {
// 索引输入帐号、密码的组件
EditText ac = (EditText)findViewById(R.id.account),
psw = (EditText)findViewById(R.id.psw);
// 获得输入的字符串
String acstr = ac.getText().toString(),
pswstr = psw.getText().toString();
// 将内容用 Uri 装起
Uri res = Uri.parse("Account: " + acstr + "\n" + "Password: " + pswstr);
Intent dt = new Intent(null, res);
// 在这里设置返回值
// 系统会调用 MainActivity 的 onActivityResult
// 不用传 request code,可能也是由系统自动传的
setResult(RESULT_OK, dt);
super.onBackPressed();
}
}
activity_login.xml
- 子 activity 的界面文件,与
activity_main.xml
类似
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 第一行帐号 -->
<TableRow
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp">
<TextView
android:text="Account"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<EditText android:id="@+id/account"
android:layout_marginLeft="20dp"
android:layout_height="wrap_content"
android:layout_width="200dp"/>
</TableRow>
<!-- 第二行密码 -->
<TableRow
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp">
<TextView
android:text="Password"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<EditText android:id="@+id/psw"
android:layout_marginLeft="20dp"
android:layout_height="wrap_content"
android:layout_width="200dp"/>
</TableRow>
</TableLayout>
strings.xml
-
res/values
下的字符串资源文件
<resources>
<!-- 程序的名字 -->
<string name="app_name">biscuit</string>
<string name="login_ac_name">mint</string>
<!-- login_btn 上的文字 -->
<string name="login_btn_txt">Login</string>
<!-- 显示区的初始内容 -->
<string name="show_txt_ini">(NOTHING HERE)</string>
</resources>
Rendering
- 初入主 activity 界面
- 子 activity 界面
- 返回主 activity 界面
推荐阅读
-
android手机端与PC端使用adb forword通信
-
Flutter学习笔记(30)--Android原生与Flutter混编
-
Android学习笔记--使用剪切板在Activity中传值示例代码
-
Android学习笔记--Activity中使用Intent传值示例代码
-
Android实现Activity之间通信的方法
-
Android中Fragment的加载方式与数据通信详解
-
Android基础之Fragment与Activity交互详解
-
16.Android-activity生命周期与启动模式
-
Android提高之Android手机与BLE终端通信
-
Android的activity学习笔记