欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android Activity 与 SubActivity 通信笔记

程序员文章站 2022-05-14 08:05:33
...

Goal

  • 主 Activity 界面上有一个“登录”按钮和一个用了显示信息的 TextView
  • 点击“登录”按钮后打开一个 SubActivity,SubActivity 上面有输入用户名和密码的控件
  • 在用户关闭(按返回键)这个 SubActivity 后,将用户输入的用户名和密码传递到主 Activity,并显示在主 Activity 的 TextView 中

Reference

AndroidManifest.xml 最全详解

Notes

  • AndroidManifest.xml 大概用来声明这个程序包含了什么东西,包括 activity(界面?)、service(后台服务)等;
  • R这个类是自动生成的,用于索引声明的各种类型的资源,如layoutstring等,即在 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,就要用后者
  • startActivityForResultstartActivity多出一个整型的参数,叫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 界面
    Android Activity 与 SubActivity 通信笔记
  • 子 activity 界面
    Android Activity 与 SubActivity 通信笔记
  • 返回主 activity 界面
    Android Activity 与 SubActivity 通信笔记