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="//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="//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="//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(); } }運行效果