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

運行效果

  

 

Tags: