Android系统四大组件:
活动(Activity):用于显示各种内容的一个界面
服务(Service):用于后台执行任务
广播接收器(Broadcast Receiver):规定应用程序所能接收的广播和向外发送广播
内容提供器(Content Provider):用于应用程序间共享数据

四大组件需要在AndroidManifest.xml里注册,如Acitivity的注册

<activity android:name=".XXXActivity">
        <intent-filter>
                   <action android:name="android.intent.action.MAIN" /><--项目的主活动-->
                  <catepory android:name="android.intent.category.LANCHER" /><--程序启动后进入的活动-->
         </intent-filter>
</activity>

Android的设计是逻辑和视图分离,即Activity中不直接写界面,而是在布局文件中,然后在活动中引入布局文件(setContentView(R.layout.xxx))
一般一个活动对应一个布局文件,创建新活动时会自动创建对应的布局文件,也会重写onCreate方法。
获取布局文件中的各种控件实例,findViewById(R.id.xxx),如

Button button = (Button) findViewById(R.id.button)

在活动中使用Menu
res目录下新建menu文件夹,再新建menu文件,如main.xml,包括2个菜单项

<menu xmlns:android:="http://scemas.android.com/apk/res/android">
    <item
            android:id="@+id/add_item"
            android:title="Add" />
   <item
            android:id="@+id/remove_item"
            android:title="Remove" />
</menu>

在活动中重写onCreateOptionsMenu方法

public boolean onCreateOptionsMenu(Menu menu){
      getMenuInflater().inflate(R.menu.main, menu);//先得到MenuInflater对象,再调用inflate方法给当前活动通过菜单资源文件创建指定菜单
      return true;//true 允许创建的菜单显示; false不允许显示
}

给各菜单项添加功能,如点击后弹出消息,需要定义菜单响应事件

public boolean onOptionsItemSelected(MenuItem item){
       switch (item.getItemId() {
       case R.id.add_item:
            Toast.make(this, "Click Add MenuItem", Toast.LENGTH_SHORT).show();
            break;
       ......
       }
       return true;
 }

活动可以通过finish方法销毁

活动之间的跳转:Intent Intent可以在不同活动中跳转,还可以携带数据。Intent可用于启动活动,启动服务,发送广播等
显示Intent:Intent (Context packageContext, Class<?> cls) 启动活动的context和目标活动的Class对象

    Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
    startActivity(intent);

隐式Intent:Intent ("com.example.activitytest.ACTION_START") 启动某个活动,且标签指定的就是 Intent中的action参数

<activity android:name=".SecondActivity">
        <intent-filter>
            <action android:name="com.example.activitytest.ACTION_START" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

在FirstActivity中添加如下代码,启动SecondActivity

Intent intent = new Intent("com.example.activitytest.ACTION_START");
startActivity(intent);

当category不是默认的时候,需要给 intent也指定与SecondActivity中的category相同的category

<category android:name="com.example.activitytest.MY_CATEGORY" />

自定义的category。即只有action和category同时匹配的时候,那个活动才能响应intent

Intent intent = new Intent("com.example.activitytest.ACTION_START");    
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);

隐式Intent不仅可以启动程序内部的活动,还可以启动其它程序的活动,如启动系统浏览器

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);

拨号界面

Intent intent = new Intent(Intetnt.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);

aciont是Inent.ACTION_VIEW和Inent.ACTION_DIAL,系统内置的动作,再将一个字符串解析为Uri对象,并传递给intent。 当一个活动配置了标签,在intent.setData时也必须有指定的参数. 向下一个活动传递数据 给Intent对象传递简单类型数据,如String、Boolean、Int等,调用Intent对象的putExtra方法,如下代码示例

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("string_data","accfcx");
startActivity(intent);

在另一个活动中取出数据

Intent intent = getIntent();
String data = intent.getStringExtra("string_data");

将数据传给传给上一个活动 FirstActivity中,添加代码如下,其中1是请求码

ntent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(intent,1);

SecondActivity中,创建一个Intent对象,携带数据,然后会在FirstAcitivity中获得,代码如下

Intent intent = new Intent();
intent.putExtra("data_return","来自SecondActivity的数据");
setResult(RESULT_OK, intent);
finish();

SecondActivity销毁后(如点击了按钮或者按下Back键),会回调FirstActivity中的onActivityResult方法,重写此方法。当按下Back键,需要重写SecondActivity的onBackPressed方法并添加如下代码

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case 1:
            if (resultCode == RESULT_OK){
                String returnData = data.getStringExtra("data_return");
            }
            break;
        default:
    }
}

请求码是用来区别启动的不同活动,当此方法被调用时,检查请求码是来自哪一个活动,即每启动一个活动都分配一个唯一的请求码

活动的生命周期
onCreate:活动第一次被创建的时候调用
onStart:在活动由不可见到可见的时候调用
onResume:在恢复或者启动一个活动时调用
onPause:启动或者恢复另一个活动时调用,如启动了一个对话框
onStop:活动完全不可见时调用,如启动了一个新活动
onDestroy:活动销毁前调用
onRestart:活动由停止状态变为运行状态前调用

当前活动C分别启动了2个活动,一个普通的活动N,另一个是对话框活动D。
程序启动后,依次调用 onCreate、onStart、onResume
此时启动普通活动N,C调用onPause和onStop方法,再回到C时,又会调用onRestart、onStart、onResume方法
再启动对话框活动D,C调用onPause方法,回到C时,调用onResume方法
退出C时,调用onPause、onStop、onDestroy方法

活动被回收时,会调用onSaveInstanceState方法,可以用来保存临时数据,在onCreate中取出保存的数据

活动的启动模式
活动有4种启动模式,standard、singleTop、singleTask和singleInstance standard:每启动一个活动,都会在返回栈中入栈,不管是否已经存在 singleTop:当已经处于栈顶时,再启动相同活动,都不会入栈 singleTask:保证整个栈只存在唯一一个活动实例,即使不在栈顶,则把此活动之上的所有活动出栈 singleInstance:启用新的返回栈管理活动,可以实现和其它程序共享此活动

使用一个BaseActivity和ActivityCollector实现对所有的活动进行管理

public class BaseActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityCollector.addActivity(this);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    ActivityCollector.removeActivity(this);
}

}

 public class ActivityCollector {
    public static List<Activity> activities = new ArrayList<>();
    public static void addActivity(Activity activity){
        activities.add(activity);
    }
    public static void removeActivity(Activity activity){
        activities.remove(activity);
    }
    public static void finishAll(){
        for (Activity activity : activities){
            if (!activity.isFinishing())
                activity.finish();
        }
    }
}

在每一个新创建的活动都继承BaseActivity类,会自动添加到ActivityCollector中,也能够调用它的的finishAll方法销毁所有活动
一个启动活动的技巧,在第一个活动中调用要启动的活动的静态方法,把数据传递进去。方法内部会创建intent对象并启动活动