Android 四大组件之Activity总结
Android四大组件:Activity(活动)
、Service(服务)
、Broadcast Receiver(广播接收器)
、Content Provider(内容提供器)
。
- Activity(活动)
Activity活动是所有Android应用的界面显示,凡是应用中能看到的内容,都是放在活动中。 - Service(服务)
Service服务无法看到,但是它会一直在后台默默地运行。 - Broadcast Receiver(广播接收器)
Broadcast Receiver广播接收器运行应用接收来自各处的广播消息,比如:电话、短信等。我们应用也可以自己定义广播消息对外广播发送。 - Content Provider(内容提供器)
Content Provider内容提供器为应用之间共享数据提供了可能。比如访问系统电话簿中的联系人,就需要通过内容提供器来实现。
本文是对Activity(活动)
的总结。
活动的创建
创建活动Activity的类。例如:
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
创建活动的布局(视图)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="This is a activity!" /> </LinearLayout>
在
AndroidManifest.xml
中进行注册。<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jyoryo.app.android.study"> <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 android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
其中标签activity
,就是申明注册Activity。android:name
,用来指定具体注册的活动。比如上面实例中.MainActivity
,标识活动的类名com.jyoryo.app.android.study.MainActivity
。由于标签manifest
中已经通过package
申明了包名,因此注册活动时,包名这一部分就可以省略了。
活动中常见用法
活动中使用Toast
Toast
是Android中非常友好的一直提醒方式,类似Html中的alert
,可以将一些提示信息展示给用户。Toast
的使用也是非常简单:
Toast.makeText(MainActivity.this, "Notify Message", Toast.LENGTH_SHORT).show();
活动中使用Menu
创建
menu
资源文件。
在main/res/menu目录下创建menu
资源文件。<?xml version="1.0" encoding="utf-8"?> <menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/item_add" android:title="Add" /> <item android:id="@+id/item_modify" android:title="Modify" /> <item android:id="@+id/item_remove" android:title="Remove" /> </menu>
在活动中重写
onCreateOptionsMenu(Menu menu)
方法,引入具体的Menu。@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; }
如果方法返回
true
,表示允许显示创建的菜单;返回false
,则表示创建的菜单不显示。在活动中重写
onOptionsItemSelected(MenuItem item)
方法来定义菜单的相应事件。@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.add_item: Toast.makeText(this, "Click Item Add", Toast.LENGTH_SHORT).show(); break; case R.id.remove_item: Toast.makeText(this, "Click Item Remove", Toast.LENGTH_SHORT).show(); break; default:break; } return true; }
活动之间的调用
显示Intent打开活动
// 显示Intent
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
其中FirstActivity.this
是当前活动,SecondActivity
是即将进入的活动。
隐式Intent打开活动
通过隐式Intent启动活动,并不用直接声明要启动的活动,而是通过一系列action
和category
等信息,由系统分析这个隐式的Intent
并找到合适的活动来启动。
在
AndroidManifest.xml
中的<activity>
标签配置<intent-filter>
内容,来指定可以响应的信息。<activity android:name=".SecondActivity"> <intent-filter> <action android:name="com.jyoryo.app.android.study.ACTION_START" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
在上面定义的活动
SecondActivity
可以相应com.jyoryo.app.android.study.ACTION_START
这个action
,而category
标签用来定义附加信息,精确指明当前活动可以响应可能带有category
的Intent
。只有action
和category
中的内容同时匹配Intent
中指定的action
和category
,这个活动才能响应这个Intent
。
通过隐式Intent启动其他程序的活动
通过隐式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
中的putExtra
方法,将想要传递的数据暂存在Intent
中:
String data = "HelloWorld";
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("extra_data", data);
startActivity(intent);
下一个活动通过Intent
获取上个活动传递的数据:
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity", "Activity Transfer Data from Intent. Data:" + data);
返回数据给上一个活动
返回数据给上一个活动,主要是通过:
- 在上一个活动中在启动下一个活动时调用
startActivityForResult
方法,期望活动销毁时返回一个结果给上一个活动; - 然后通过在上一个活动中重写方法
onActivityResult
获取下一活动即将被销毁时返回给上一活动的数据。
期待启动的下一个活动在活动销毁时返回数据给上一个活动
// -----------------FirstActivity------------------
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);
下一活动销毁前返回数据:
// -----------------SecondActivity------------------
Intent intent = new Intent();
intent.putExtra("data_return", "Return FirstActivity");
setResult(RESULT_OK, intent);
// 销毁活动
finish();
上一活动取到返回的数据
// -----------------FirstActivity------------------
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
// super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if(RESULT_OK == resultCode) {
String returnData = data.getStringExtra("data_return");
Log.d("FirstActivity", "onActivityResult---ReturnData:" + returnData);
}
break ;
default:
}
}
如果活动SecondActivity
并不是通过我们定义方法销毁,而是通过Back键回到FirstActivity
,这样的话,数据没有办法进行返回。解决办法:在上一个活动SecondActivity
重写方法onBackPressed
// -----------------SecondActivity------------------
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("data_return", "Return FirstActivity");
setResult(RESULT_OK, intent);
// 销毁活动
finish();
}
活动的生命周期
活动的生命周期:
onCreate()
:每个活动都会有的方法,在活动第一次被创建的时候调用;onStart()
:这个活动在活动由不可见变为可见的时候调用;onResume()
:这个方法在活动准备好和用户进行交互的时候调用,此时的活动一定位于返回栈的栈顶,并且处于运行状态;onPause()
:这个方法在系统准备去启动或者恢复另一个活动的时候调用。 我们通常会在这个方法中将一些消耗 CPU 的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用;onStop()
:这个方法在活动完全不可见的时候调用。它和 onPause()方法的主要区别在于,如果启动的新活动是一个对话框式的活动,那么 onPause()方法会得到执行,而 onStop()方法并不会执行;onDestroy()
:这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态;onRestart()
:这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。
以上七个方法中除了 onRestart()方法,其他都是两两相对的,从而又可以将活动分为三种生存期。
活动使用技巧
统一管理所有的活动
通过构建自定义的活动基类BaseActivity
和活动统一管理类ActivityCollector
来集中控制程序中的所有活动。创建的活动都继承BaseActivity
。
BaseActivity
/**
* 活动的基类
*/
public abstract class BaseActivity extends AppCompatActivity {
private static final String TAG = "BaseActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 显示当前是在哪个Activity
Log.d(TAG, getClass().getSimpleName());
// 将活动添加至活动管理器
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 从活动管理器中移除活动
ActivityCollector.removeActivity(this);
}
}
ActivityCollector
/**
* 活动管理器
* <li>用于统一管理继承BaseActivity的活动</li>
*/
public class ActivityCollector {
public static List<Activity> activities = new ArrayList<>();
/**
* 向活动管理器添加活动
* @param activity
*/
public static void addActivity(Activity activity) {
activities.add(activity);
}
/**
* 从活动管理器中移除活动
* @param activity
*/
public static void removeActivity(Activity activity) {
activities.remove(activity);
}
/**
* 移除所有活动
*/
public static void finishAll() {
for (Activity activity : activities) {
if(!activity.isFinishing()) {
activity.finish();
}
}
// 删掉当前进程,保存程序完全退出
android.os.Process.killProcess(android.os.Process.myPid());
}
}
如果需要退出程序,就可以直接调用ActivityCollector.finishAll()
。
启动活动的方法
public class MyActivity extends BaseActivity {
/**
* 启动活动
* @param context
* @param data1
* @param data2
*/
public static void actionStart(Context context, String data1, String data2) {
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra("param1", data1);
intent.putExtra("param2", data2);
context.startActivity(intent);
}
}
上面的实例需要的额外参数data1
和data2
,是该活动的启动时需要的非常重要的属性。具体的参数数量和数据类型,需要根据实际的业务进行调整。
后面通过Intent
启动这个活动就可以这样写:
MyActivity.actionStart(YourActivity.this, "data1", "data2");
参考文章:
- 《Android第一行代码(第2版)》