Android学习之活动的最佳实践
•问题的起源
先来模拟一个场景:打开一个 App,最先映入眼帘的是主活动(MainActivity),在该活动中给用户提供了一个 Button,
用户点击该 Button 实现由 MainActivity 跳转到 FirstActivity,在 FirstActivity 中,又提供了一个 Button,
用户点击后,同样是实现页面跳转功能,只不过这次是从 FirstActivity 跳转到 SecondActivity;
现在用户想回到主界面,点击 Back 键,界面由 SecondActivity 跳转到 FirstActivity,再点击一下,界面跳转到 MainActivity,
再点击一下界面才能回到主界面,当然,直接点击 home 键也是可以的(这不是本节的重点,你就假设该用户的 home 键被扣掉了),
那么,如何才能够实现在 SecondActivity 界面通过点击一下 Back 键,就能够返回到主界面呢?
•准备工作
新建一个项目,至于命名的话,随便啦~~~
新建两个活动,分别命名为 FirstActivity 和 SecondActivity;
首先看看 SecondActivity 中的代码;
activity_second.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Second Activity" android:textSize="20sp" /> </RelativeLayout>SecondActivity.java
public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); } }接下来瞅瞅 FirstActivity 中的代码;
activity_first.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="First Activity" android:textSize="20sp" /> <Button android:id="@+id/btn_first" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="跳转到 Second Activity" android:textAllCaps="false" /> </RelativeLayout>FirstActivity.java
public class FirstActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first); Button btn = findViewById(R.id.btn_first); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(FirstActivity.this,SecondActivity.class)); } }); } }最后,让我们来看看主活动中的代码;
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Main Activity" android:textSize="20sp" /> <Button android:id="@+id/btn_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="跳转到 First Activity" android:textAllCaps="false" /> </RelativeLayout>MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = findViewById(R.id.btn_main); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this,FirstActivity.class)); } }); } }运行效果
仿照问题描述,我们来测试一下;
•知识支持
假设父类 Person 中有一个 onCreate() 方法,子类 Boy 继承自 Person 类并重写了 onCreate() 方法;
在子类的 onCreate() 方法中通过 super.onCreate() 语句调用了父类的 onCreate() 方法,
那么,在这种情况下,父类的 onCreate() 方法中的 this 指向的是其子类 Boy;
public class Person { public void onCreate() { System.out.println(this.toString()); } public static void main(String[] args) { Boy boy = new Boy(); boy.onCreate(); } } class Boy extends Person{ public void onCreate() { super.onCreate(); } }上述代码的运行效果为:
具体用法请移步【this 关键字的使用】;
•解决需求
新建一个 ActivityCollector 类作为活动管理器;
ActivityCollector.java
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(); } } } }在该类中,通过 List 来暂存活动,并提供了 addActivity() 和 removeActivity() 方法用于向 List 中添加和移除一个活动;
还提供了 finishAll() 方法用于将 List 中暂存的活动全部销毁;
新建一个 BaseActivity;
BaseActivity.java
public class BaseActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityCollector.addActivity(this); } @Override protected void onDestroy() { super.onDestroy(); ActivityCollector.removeActivity(this); } }在 BaseActivity 的 onCreate() 方法中调用了 ActivityCollector.addActivity(this) ,表明将当前正在创建的活动添加到 List 里;
在 onDestroy() 方法中调用了 ActivityCollector.removeActivity(this) ,表明将一个马上要销毁的活动从 List 中移除;
修改 MainActivity.java,FirstActivity.java,SecondActivity.java 的继承关系,使其均继承自 BaseActivity;
还记得活动中的 onCreate() 的方法中的第一行代码是啥吗?
没错,就是它: super.onCreate(savedInstanceState); ;
不管是 MainActivity 还是 FirstActivity 和 SecondActivity,一定都会调用 super.onCreate(savedInstanceState); ;
由于他们都是继承自 BaseActivity,所以,创建 MainActivity 时一定会先调用 BaseActivity 中的 onCreate() 方法;
还记得知识支持里讲的 this 关键字的作用吗?
在 BaseActivity 中的 onCreate() 方法中,通过 this 关键字将 MainActivity 加入到 List 中,创建按 FirstActivity 和 SecondActivity 时,同理;
这样的话,就将开启的活动全部加入到 List 中了;
从此以后,不管你想在什么地方退出程序,只需要调用 ActivityCollector.finishAll() 方法就可以了;
修改 SecondActivity.java 中的代码;
SecondActivity.java
public class SecondActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); } @Override protected void onDestroy() { super.onDestroy(); ActivityCollector.finishAll(); } }运行效果