Android四大组件:Activity(活动)Service(服务)Broadcast Receiver(广播接收器)Content Provider(内容提供器)

  • Activity(活动)
    Activity活动是所有Android应用的界面显示,凡是应用中能看到的内容,都是放在活动中。
  • Service(服务)
    Service服务无法看到,但是它会一直在后台默默地运行。
  • Broadcast Receiver(广播接收器)
    Broadcast Receiver广播接收器运行应用接收来自各处的广播消息,比如:电话、短信等。我们应用也可以自己定义广播消息对外广播发送。
  • Content Provider(内容提供器)
    Content Provider内容提供器为应用之间共享数据提供了可能。比如访问系统电话簿中的联系人,就需要通过内容提供器来实现。

本文是对Activity(活动)的总结。

活动的创建

  1. 创建活动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);
       }
    }
  2. 创建活动的布局(视图)

    <?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>
  3. 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

  1. 创建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>
  2. 在活动中重写onCreateOptionsMenu(Menu menu)方法,引入具体的Menu。

       @Override
       public boolean onCreateOptionsMenu(Menu menu) {
           getMenuInflater().inflate(R.menu.main, menu);
           return true;
       }

    如果方法返回true,表示允许显示创建的菜单;返回false,则表示创建的菜单不显示。

  3. 在活动中重写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启动活动,并不用直接声明要启动的活动,而是通过一系列actioncategory等信息,由系统分析这个隐式的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标签用来定义附加信息,精确指明当前活动可以响应可能带有categoryIntent。只有actioncategory中的内容同时匹配Intent中指定的actioncategory,这个活动才能响应这个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);
    }
}

上面的实例需要的额外参数data1data2,是该活动的启动时需要的非常重要的属性。具体的参数数量和数据类型,需要根据实际的业务进行调整。
后面通过Intent启动这个活动就可以这样写:

MyActivity.actionStart(YourActivity.this, "data1", "data2");

参考文章:

  • 《Android第一行代码(第2版)》

标签: android

添加新评论