1、创建Activity
手动创建activity时,Android studio会帮我们自动在Android Manifest.xml中进行注册,比较人性化。

    如果程序中没有声明任何一个活动作为主活动,这个程序也可以正常安装,只是无法在启动其中看到或打开这个程序(一般作为第三方服务供其它应用在内部进行调用,如支付宝快捷支付服务)。

    在活动中获取布局文件中定义的元素,采用findViewById方式返回的是一个View对象,需要向下转型成相应元素类型。

    在活动中使用Menu:

    首先需要创建菜单文件(在res下新建Menu文件夹,在此文件夹中创建菜单资源文件如main):

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/add_item"
        android:title="Add"/>
    <item
        android:id="@+id/remove_item"
        android:title="Remove"/>
</menu>

然后在活动中重写如下方法(ctrl+O):

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main,menu);
        //getMenuInflater()方法能够得到MenuInflater对象,再调用它的inflate()方法即可给当前活动创建菜单
        //第一个参数指定创建菜单的资源文件,第二个参数菜单项添加的目标Menu对象
        return true;//允许菜单显示出来,false则无法显示
    }


要使菜单有用,还需定义菜单响应事件,重写如下方法:

public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.add_item:
                Toast.makeText(this,"You clicked Add",Toast.LENGTH_SHORT).show();
                break;
            case R.id.remove_item:
                Toast.makeText(this,"You clicked Remove",Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return  true;
    }

销毁活动有两种方法:按back键或在活动点击事件中调用finish()方法(效果一样)。

2、使用Intent跳转活动

使用显式Intent:

button1.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                //Toast.makeText(FirstActivity.this,"You clicked Button 1", Toast.LENGTH_SHORT).show();
               // finish();
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                startActivity(intent);
                //意图:在FirstActivity这个活动的基础上打开SecondActivity这个活动;
                // 然后通过startActivity()方法来执行这个Intent
            }
        });

使用隐式Intent:


    不明确指出想要启动哪个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent找出合适的活动(可以响应这个隐式Intent的活动)去启动。可通过如下方法指定活动能响应的Intent:

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

action和category要能同时匹配才能启动。

在想启动此活动的活动中需作如下修改:

Intent intent = new Intent("com.example.jojo.activitytest.ACTION_START");
                startActivity(intent);
android.intent.category.DEFAULT是一种默认的category,在调用startActivity()方法时会自动将这个category添加到intent中

每个intent中只能指定一个action,但可以指定多个category。

Intent传递数据有正向传递和反向传递两种方式,正向传递直接在intent上绑定数据即可,方向传递需使用startActivityForResult()方法来启动下一个活动(并通过onActivityResult()方法来接收传回的数据和结果码)

3、活动的生命周期

    Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动集合。

    每个活动在其生命周期中最多可能会有4种状态:运行状态(系统最不愿回收)、暂停状态(内存极低情况系统才考虑回收)、停止状态(会保存相应状态和成员变量,但当其他地方需要内存时,可能被回收)、销毁状态(系统最倾向于回收)


    生命周期中对应的七个回调函数:onCreate()、onStart()、onRestart()、onResume()、onPause()、onStop()、onDestroy()


    如果活动被回收,要保存临时数据和状态,可使用onSaveInstanceState()回调方法(保证在活动被回收之前一定会被调用)。此方法会携带一个Bundle类型参数(提供了一系列方法用于保存数据,如putString()/putInt(),每个保存方法需传入两个参数,即键/值对)。保存后恢复:onCreate()方法也有一个Bundle类型的参数(一般情况下为null,但如活动在被回收之前有通过onSaveInstanceState()保存数据,则此参数就会带有之前保存的全部数据,只需用相应方法取出即可)

4、活动的启动模式

可在AndroidManifest.xml中通过给<activity>标签指定android:launchMode属性来选择启动模式。

standard: 默认启动模式。每次启动都会创建该活动的一个新实例(不会在乎是否已在返回栈中存在),在返回栈中同一活动可能存在多个实例。

android studio 创建一个继承类 android studio创建一个新的activity_ide

singleTop: 在启动活动时如果发现返回栈的栈顶已经时该活动,则认为可直接使用它,不会船建新的实例。不过当未处于栈顶时,还是会创建新实例。

android studio 创建一个继承类 android studio创建一个新的activity_数据_02

singleTask: 让活动在整个应用程序上下文中只存在一个实例。每次启动活动时,系统首先会在返回栈中检查是否存在该活动实例,如存在则直接使用,并把此活动上的所有活动统统出栈,如没发现则创建新实例。

android studio 创建一个继承类 android studio创建一个新的activity_android_03

singleInstance: 会启用一个新的返回栈来管理这个活动(如果singleTask模式指定了不同的taskAffinity,也会启动一个新的返回栈)。如果程序中有一个活动是允许其他程序调用的,可以解决共享活动实例问题。由于每个应用程序都有自己的返回栈,同一个活动在不同返回栈中入栈时必然会创建新的实例,而此模式下,会有一个单独的返回栈来管理这个活动,不同应用程序访问此活动都共用同一个返回栈。

android studio 创建一个继承类 android studio创建一个新的activity_数据_04

5、活动最佳实践

    a、知晓当前是在哪个活动:

创建一个BaseActivity(Java Class,因不需在manifest中注册),然后需要让BaseActivity成为项目中所有活动的父类。修改其他活动的继承结构,替换成BaseActivity.


public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity",getClass().getSimpleName());//获取当前实例的类名并打印出来
    }
}

由于最终继承自AppCompatActivity,所有活动的功能不会受影响。

    b、 随时随地退出程序:

如果活动较多需连按多次Back键才能退出,按Home键只能挂起。可以用一个专门的集合类管理所有活动。

新建以下类作为活动管理器:


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中的代码:


public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity",getClass().getSimpleName());//获取当前实例的类名并打印出来
        ActivityCollector.addActivity(this);
    }

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

这样,在想退出程序的地方调用

ActivityCollector.finishAll() 方法就好了。

还可以在销毁所有活动的代码后再加上杀掉当前进程的代码,保证程序完全退出:

android.os.Process.killProcess(android.os.Process.myPid())

c、启动活动

当要启动的活动不是自己写的,但需传递参数的时候,可做如下处理,在被启动的活动中添加如下代码:

public class SecondActivity extends BaseActivity {

    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);
    }

这样就能清楚地知道启动此活动需要传递哪些数据,现在只需一行代码就可以启动此活动了。在启动点添加如下代码即可:



SecondActivity.actionStart(FirstActivity.this,"data1","data2");


给每个活动都添加类似启动方法,可节省被询问时间同时让启动更简单。