Android基础——Intent
Intent
- Intent是什么?
- 显式Intent
- 隐式Intent
- Intent扩展使用
- Intent传递数据
- Intent传递数据2
- Intent传递对象
- Serializable
- Parcelable
Intent是什么?
Intent用于Android程序中各组件(Activity、BroadcastReceive、Service)的交互,并且可以在组件之间传递数据,分为显式Intent和隐式Intent。
显式Intent
通过Intent(Context packageContext, Class<?> cls)构造函数创建Intent实例,第一个参数为当前Context,第二个参数为要启动的目标类。如当需要启动OtherActivity时:
Intent intent=new Intent(MainActivity.this,OtherActivity.class); startActivity(intent);隐式Intent
不直接指明启动的目标,而是根据action和category找出合适的目标。可通过Mainfest.xml配置各组件的<intent-filter>,只有当<action>和<category>同时匹配时,才能响应对应的Intent。如在OtherActivity中配置:
<intent-filter> <action android:name="testAction"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="testCategory"/> </intent-filter>当需要使用隐式Intent启动OtherActivity时:
Intent intent=new Intent("testAction"); intent.addCategory("testCategory"); startActivity(intent);Tips:
- 不要忘记在<intent-filter>标签中配置android.intent.category.DEFAULT的category ,因为在调用startActivity()方法时会自动将这个category添加到Intent中,否则将报错android.content.ActivityNotFoundException: No Activity found to handle Intent
Intent扩展使用
在<intent-fliter>标签中配置<data>标签可以指定当前Intent可以响应数据类型。
- android:scheme:指定数据协议,如http、file、content,未指定时默认为file或content
- android:host:指定数据主机名,如www.baidu.com
- android:port:指定数据端口,如80
- android:path:指定端口后的路径
- android:pathPattern:同上,但可以加上通配符*
- android:pathPrefix:指定路径的前缀
- android:mineType:允许使用通配符进行指定
如通过显式Intent调用浏览器:
Intent intent=new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com")); startActivity(intent);调用拨号界面
Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:10086")); startActivity(intent);Intent传递数据
Intent通过intent.putExtra(String,XXX)方法以键值对的方式传递数据,其中XXX可代表基本数据类型、数组等。如传递数据到OtherActivity:
Intent intent=new Intent(MainActivity.this,OhterActivity.class); intent.putExtra("testdata","data"); startActivity(intent);获取数据通过intent.getXXXExtra(String)方法,其中XXX可代表基本数据类型、数组等。如从OtherActivity中取出数据:
Intent intent = getIntent(); String testData = intent.getStringExtra("testdata"); Log.d("MainActivity", testData);Tips:
- 在启动OtherActivity时如果需要传递数据,但OtherActivity并不是由你开发,不知道需要什么数据,此时你只能通过查看源码或询问同事,难免麻烦。通过将startActivity()和需要的数据再次封装就可解决上述问题:
public static void OtherActivityStart(Context context, String data1, String data2) { Intent intent = new Intent(context, OhterActivity.class); intent.putExtra("param1", data1); intent.putExtra("param2", data2); context.startActivity(intent); }通过startActivityForResult(Intent,int),第一个参数是启动目标活动的Intent,第二个参数是请求码,用于在回调中判断数据来源。如通过startActivityForResult启动OhterActivity:
Intent intent=new Intent(MainActivity.this,OhterActivity.class); startActivityForResult(intent,1);在OhterActivity通过setResult方法将数据返回(若想通过Back键返回,则将代码放置在onBackPressed方法中),第一个参数是返回的处理结果(RESULT_OK、RESULT_CANCELED),第二个参数是带有数据的Intent:
Intent intent=new Intent(); intent.putExtra("returnData","data"); setResult(RESULT_OK,intent); finish();OhterActivity销毁后,会回调上一个活动(MainActivity)的onActivityResult()方法,故我们需要重写该方法,通过判断请求码(数据来源)和处理结果从而获得数据进行相应操作:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode){ case 1: if(resultCode==RESULT_OK){ Log.d("MainActivity", data.getStringExtra("returnData")); } break; default: } }Intent传递数据2
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/drawerContainer"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/open_input"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="打开输入页并接收结果"/><TextViewandroid:id="@+id/text"android:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout>使用ActivityResultLauncher启动Activity并设置监听
publicclassMainActivityextendsAppCompatActivity{privatestaticfinalStringTAG=MainActivity.class.getSimpleName();// 用成员变量注册 launcher:registerForActivityResult 在 activity 创建完成前即可安全调用,// 且必须无条件注册,以便进程/activity 重建后回调仍能正确接收结果。privatefinalActivityResultLauncher<Intent>inputLauncher=registerForActivityResult(newActivityResultContracts.StartActivityForResult(),result->{if(result.getResultCode()==RESULT_OK&&result.getData()!=null){Stringvalue=result.getData().getStringExtra(InputActivity.KEY_RESULT);((TextView)findViewById(R.id.text)).setText(value);Log.d(TAG,"received result: "+value);}});@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);EdgeToEdge.enable(this);Log.d(TAG,"onCreate");setContentView(R.layout.activity_demo);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.drawerContainer),(v,insets)->{Insetsbars=insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(bars.left,bars.top,bars.right,bars.bottom);returninsets;});findViewById(R.id.open_input).setOnClickListener(v->inputLauncher.launch(newIntent(this,InputActivity.class)));}}<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/inputContainer"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><EditTextandroid:id="@+id/input"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="请输入内容"/><Buttonandroid:id="@+id/confirm"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="确认并返回"/></LinearLayout>setResult设置Activity返回结果
public class InputActivity extends AppCompatActivity { private static final String TAG = InputActivity.class.getSimpleName(); // 结果 Intent 中携带文本的 key,调用方按同一 key 取值 public static final String KEY_RESULT = "key_result"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_input); Log.d(TAG, "onCreate"); EditText input = findViewById(R.id.input); Button confirm = findViewById(R.id.confirm); confirm.setOnClickListener(v -> { Intent data = new Intent(); data.putExtra(KEY_RESULT, input.getText().toString()); setResult(RESULT_OK, data); finish(); }); } }Intent传递对象
Serializable
类通过实现Serializable接口,可以将对象转换成可存储或可传输的状态。
创建类Person:
public class Person implements Serializable { private String name; private int 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; } }当需要传递时:
Person person = new Person(); person.setName("tom"); person.setAge(20); Intent intent=new Intent(MainActivity.this,OhterActivity.class); intent.putExtra("person",person); startActivity(intent);取出时:
Person person = (Person) getIntent().getSerializableExtra("person");Parcelable
Parcelable通过将对象分解成Intent所支持的数据:
public class Person implements Parcelable { private String name; private int 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; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); } protected Person(Parcel in) { name = in.readString(); age = in.readInt(); } public static final Creator<Person> CREATOR = new Creator<Person>() { @Override public Person createFromParcel(Parcel in) { return new Person(in); } @Override public Person[] newArray(int size) { return new Person[size]; } }; }当需要传递时:
Person person = new Person(); person.setName("tom"); person.setAge(20); Intent intent=new Intent(MainActivity.this,OhterActivity.class); intent.putExtra("person",person); startActivity(intent);取出时:
Person person = (Person) getIntent().getParcelableExtra("person");