您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦。
本文亮点:详细介绍Activity的创建以及如何传递参数和接收返回参数
Android系列文章都在Android专栏中,欢迎小伙伴关注。
https://gitee.com/jayxiang31/android-studio-projects/tree/master/activity_test
https://gitee.com/jayxiang31/android-studio-projects/tree/master/Android_Activity
上一篇文章[❤️【Android精进之路-04】Android核心组件Activity,必须掌握的知识点(Activity是什么,生命周期是怎样的)❤️]介绍了Activity的基本概念以及生命周期,但是没有说到如何创建Activity,Activity之间如何传值。SO,本文将重点讲解Activity的创建以及如何Activity之间如何传递参数。
源代码地址:https://gitee.com/jayxiang31/android-studio-projects.git
https://gitee.com/jayxiang31/android-studio-projects.git
利用Android Studio可以直接创建一个自定义的Activity,创建的方式是:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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=".TestActivity"> </androidx.constraintlayout.widget.ConstraintLayout>
<manifest ... > <application ... > <activity android:name = ".TestActivity" /> ... </application ... > ... </manifest >
如果Activity是主Activity的话则其注册会多两行配置。
<manifest ... > <application ... > <activity android:name=".MainActivity" android:exported="true" android:label="@string/title_activity_main" android:theme="@style/Theme.Activity_test.NoActionBar"> <intent-filter> <!-- 表示该Activity作为主Activity出现 --> <action android:name="android.intent.action.MAIN" /> <!-- 表示该Activity会被显示在最上层的启动列表中 --> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ... </application ... > ... </manifest >
<action android:name="android.intent.action.MAIN" />
表示该Activity作为主Activity出现。<category android:name="android.intent.category.LAUNCHER" />
表示该Activity会被显示在最上层的启动列表中。
说完了如何创建自定义Activity之后,接下来让我们来看一下Activity如何绑定自定义视图。重写onCreate方法,在该方法中通过setContentView方法来设置需要绑定的视图。这里新建了一个名为my_layout.xml的视图。然后通过 R.layout.my_layout 来获取它。这里的R类是基于外部资源生成的类,在编译项目时被创建,其包含了所有的 rest/目录下的资源ID,如果布局文件,资源文件,图片。res目录下保存的文件大多数都会被编译,并且被赋予资源ID,这些ID被保存在R.java文件中,这样我们就可以在程序中通过ID来访问res类的资源。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_layout); }
Android应用程序中除了主Activity由应用程序启动以外,其他的Activity都是由用户操作启动。所以如何启动另一个Activity。启动Activity的方法是:startActivity(new Intent(MainActivity.this, AnotherAty.class));
这个方法一般是放在一个按钮的监听事件中调用。
<Button android:id="@+id/btnStartAnotherAty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="启动另一个Activity" tools:layout_editor_absoluteX="116dp" tools:layout_editor_absoluteY="257dp" tools:ignore="MissingConstraints" />
这里定义了一个名为btnStartAnotherAty的Button按钮。用于用户点击时启动另一个Activity。
3. 在MainActivity中给按钮添加点击监听事件启动AnotherAty。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_layout); findViewById(R.id.btnStartAnotherAty).setOnClickListener(view -> { //启动目标Activity startActivity(new Intent(MainActivity.this, AnotherAty.class)); }); }
这里findViewById(R.id.btnStartAnotherAty) 方法非常重要,他表示根据ID找到名为btnStartAnotherAty按钮,接着调用setOnClickListener 方法绑定一个按钮点击的监听事件,下面介绍的Activity之间传值也是要写在该事件里。
如果想从Activity跳转到一个网页的话也是可以的,只需要像下面这样就可以实现:
startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse("https://feige.blog.csdn.net/")));
上面的代码演示了从当前Activity跳转到[码农飞哥]这个页面中。
运行结果是:
关闭Activity用finish()方法,关闭之前启动的其他Activity可以用finishActivity() 方法。
虽然Android系统提供了finish()方法关闭Activity,但是不建议开发人员调用这个方法强制关闭Activity。因为Android系统维护了Activity完整的生命周期。并且提供了完备的资源回收机制和资源重建机制,可以动态地回收和重建 Activity。
Activity传递数据本质上还是向Intent中存放数据。有三种不同的方式:
第一种方式是直接将数据设置到Intent中,
intent.putExtra("name", "码农飞哥,你好");
第二种方式是向Intent中设置一个值对象,
intent.putExtra("user", new User("码农飞哥", 30));
第三种方式是向Intent中设置一个Bundle对象。
Bundle bundle = new Bundle(); bundle.putString("name", "码农飞哥,Bundle"); bundle.putInt("age", 30); intent.putExtras(bundle);
下面就详细看一下吧!
传递简单数据可以直接向Intent中设值,一般而言只需要传递少量的基本类型的数据可以直接通过intent的putExtra方法进行设置传值。
Intent intent = new Intent(MainActivity.this, TheAty.class); //1.传简单数据 intent.putExtra("name", "码农飞哥,你好"); startActivity(intent);
这里传递了一个名为name的String的数据。
2. 被启动目标Activity接收值的操作
Intent intent = getIntent(); intent.getStringExtra("name")
这里接收值调用的方法根据值的类型不同,需要调用不同的方法,即如果传入的值是String类型在调用getStringExtra类型,如果是int类型则调用getIntExtra方法。
运行结果是:
当传入的数据比较多,类型比较复杂时,则不太适合直接使用intent直接设置传递了。这是可以将需要传递的值封装到一个对象Bean中。比如下面定义了一个User对象,该对象里面有name和age两个属性。这里需要注意的是传递的值对象必须要实现java.io.Serializable接口使之可以被序列化。否则,该对象不能被设值到intent中
public class User implements Serializable { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } ······省略get,set方法······ }
如果是使用Serializable接口进行序列化的话,也可以使用Android系统提供的Parcelable接口来实现序列化,这个接口相较于Serializable接口性能更好。
public class User2 implements Parcelable { private String name; private int age; protected User2(Parcel in) { name = in.readString(); age = in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); } @Override public int describeContents() { return 0; } public static final Creator<User2> CREATOR = new Creator<User2>() { @Override public User2 createFromParcel(Parcel in) { return new User2(in); } @Override public User2[] newArray(int size) { return new User2[size]; } }; }
Intent intent = new Intent(MainActivity.this, TheAty.class); //2. 传递值对象 intent.putExtra("user", new User("码农飞哥", 30)); startActivity(intent);
Intent intent = getIntent(); User user = (User) intent.getSerializableExtra("user");
如果使用的是Serializable序列话的话,则调用getSerializableExtra方法。如果是Parcelable序列化的话,则调用getParcelableExtra方法。
第三种传值的方式就是传递数据包Bundle。Bundle数据包设置方式类似于Map也是传入键值对,不同数据类型需要调用不同的put方法
Intent intent = new Intent(MainActivity.this, TheAty.class); Bundle bundle = new Bundle(); bundle.putString("name", "码农飞哥,Bundle"); bundle.putInt("age", 30); intent.putExtras(bundle); startActivity(intent);
这里调用putExtras方法将Bundle对象放入Intent中。当然也可以调用putExtra方法设置Bundle对象。使用putExtra的方式是:intent.putExtra("data",bundle)
需要指定一个键。
2. 被启动目标Activity接收值的操作
Intent intent = getIntent(); Bundle data = intent.getExtras(); String.format("name=%s,age=%s,name1=%s", data.getString("name"), data.getInt("age"), data.getString("name1", "不存在的默认值"))
如果设值使用的是putExtras方法,那么在取值时则需要使用getExtras()方法。如果设值使用的intent.putExtra("data",bundle)
,则取值需要使用intent.getExtra("data")
。
另外,从Bundle中取值是也是根据数据类型的不同调用不同的方法,String类型则调用getString()
,int类型则调用getInt()
方法。如果张冠李戴的话则获取不到指定的值。如果指定name对应的值不存在,可以设置默认值,就是上面data.getString("name1", "不存在的默认值")
这样,名为name1的值不存在时,则显示设置的默认值不存在的默认值
。
前面介绍的都是源Activity向目标Activity传递数据,那么源Activity怎么接收被启动Activity的返回结果呢?这里也是可以实现的。
<TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="呈现结果" />
private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //定义一个textView接收返回的值 textView = findViewById(R.id.textView); findViewById(R.id.btnStartAty).setOnClickListener(view -> { Intent intent = new Intent(MainActivity.this, TheAty.class); startActivityForResult(intent, 0); }); }
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); textView.setText("另一个Activity返回的数据是:" + data.getStringExtra("data")); }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_the_aty); editText = findViewById(R.id.editText); //定义一个名为sendBackDataBtn的按钮用于跳回源Activity。 findViewById(R.id.sendBackDataBtn).setOnClickListener(view -> { Intent resultIntent = new Intent(); resultIntent.putExtra("data", editText.getText().toString()); setResult(1, resultIntent); //结束当前的Activity finish(); }); }
运行结果:
本文详细介绍了Activity的创建以及传值操作,希望对读者朋友们有所帮助。
全网同名【码农飞哥】。不积跬步,无以至千里,享受分享的快乐
我是码农飞哥,再次感谢您读完本文。