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(); } }執行效果
&n