android 團隊開發技巧1 - activity 啟動

weixin_34402408發表於2016-08-17

標籤(空格分隔): android團隊開發技巧 android


前景

記得一開始寫安卓的時候,我都是像很多人一樣,直接 new 一個 intent ,然後給用 intent.putExtra 方法來傳遞引數給 下一個 activity。如下程式碼:

public class OneActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, TwoActivity.class);
        intent.putExtra("serverId", 20);
        startActivity(intent);
    }
}

public class TwoActivity extends Activity {
    private ObjectBean mData;//資料來源,實現到介面
    private String mTitle;
    private int mServerId;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mServerId = getIntent().getIntExtra("serverId", 0);
        //載入伺服器資料,虛擬碼,主要看邏輯
        requestRemoteData(mServerId, new Listener(){
            public void onComplete(RemoteBean bean){
                mData = bean.data;
                mTitle = bean.title;
                setDataToUi();
            }
        });
    }
    
    private void setDataToUi(){
        //把 mData 和 mTitle 資料都設定到 ui 上面
        //.....
    }
}

問題

看上面程式碼的確沒什麼問題,但是當專案越來越大,需求越來越複雜,接手人數越來越多的時候,就會出現一堆的問題。
現在需求來了,加入 TwoActivity 的資料有可能不來自網路了,來自本地,但介面幾乎一樣的。面對這樣的需求,有人會開一個 activity,但是如果當 activity 的邏輯極其複雜的時候,這樣維護2分程式碼,成本會非常大。所以當頁面差別非常小的時候應該採用同一個 activity。於是面對上面的需求,我們會增加一個引數,標誌這個是載入本地資料還是伺服器資料。程式碼:

public class OneActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, TwoActivity.class);
        intent.putExtra("serverId", 20);
        intent.putExtra("launchMode", 0);
        startActivity(intent);
    }
}

public class ThreeActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(this, TwoActivity.class);
        intent.putExtra("title", "歡迎光臨");
        intent.putExtra("data", mData);
        intent.putExtra("launchMode", 1);
        startActivity(intent);
    }
}

public class TwoActivity extends Activity {
    private ObjectBean mData;//資料來源,實現到介面
    private String mTitle;
    private int mServerId;
    private int mLaunchMode = 0;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mServerId = getIntent().getIntExtra("serverId", 0);
        mData = getIntent().getSerializableExtra("data");
        mTitle = getIntent().getStringExtra("title");
        mLaunchMode = getIntent().getIntExtra("launchModel", 0);
        if(mLaunchMode == 0){
            //載入伺服器資料,虛擬碼,主要看邏輯
            requestRemoteData(mServerId, new Listener(){
                public void onComplete(RemoteBean bean){
                    mData = bean.data;
                    mTitle = bean.title;
                    setDataToUi();
                }
            });
        } else {
            setDataToUi();
        }
        
    }
    
    private void setDataToUi(){
        //把 mData 和 mTitle 資料都設定到 ui 上面
        //.....
    }
}

這樣子就實現,同一個頁面不同邏輯的需求了,可以看到引入了 mLaunchMode 標誌變數來標誌他的業務邏輯。的確比用多個activity 方便了。但是問題來了,這樣子別人怎麼知道放什麼到 intent 裡面?假如 TwoActivity 是我寫的,OneActivity, ThreeActivity 是另外一個同事寫得, 他可能放serverId, datatitle, launchMode的組合種情況,這樣他需要啟動我的頁面就要來詢問我要傳什麼引數到我的頁面了,這樣子大大增加加了溝通成本。

解決問題

為了解決這樣的問題,我們在目標 activity 增加啟動該頁面的靜態方法,這樣子同事之間再也不會不知道啟動別人的頁面要傳什麼引數了,程式碼如下:

public class OneActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TwoActivity.launch(this, 20);
    }
}

public class ThreeActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TwoActivity.launch(this, "歡迎光臨", mData);
    }
}

public class TwoActivity extends Activity {
    public static final String EXTRA_SERVER_ID = "EXTRA_SERVER_ID";
    public static final String EXTRA_TITLE = "EXTRA_TITLE";
    public static final String EXTRA_DATA = "EXTRA_DATA";
    public static final String EXTRA_LAUCH_MODE = "EXTRA_LAUCH_MODE";
    
    public static void launch(Activity context, int serverId){
        Intent intent = new Intent(context, TwoActivity.class);
        intent.putExtra(EXTRA_SERVER_ID, serverId);
        intent.putExtra(EXTRA_LAUCH_MODE, 0);
        startActivity(intent);
    }
    
    public static void launch(Activity context, String title, ObjectBean data){
         Intent intent = new Intent(this, TwoActivity.class);
        intent.putExtra(EXTRA_TITLE, title);
        intent.putExtra(EXTRA_DATA, data);
        intent.putExtra(EXTRA_LAUCH_MODE, 1);
        startActivity(intent);
    }

    private ObjectBean mData;//資料來源,實現到介面
    private String mTitle;
    private int mServerId;
    private int mLaunchMode = 0;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mServerId = getIntent().getIntExtra(EXTRA_SERVER_ID, 0);
        mData = (ObjectBean) getIntent().getSerializableExtra(EXTRA_DATA);
        mTitle = getIntent().getStringExtra(EXTRA_TITLE);
        mLaunchMode = getIntent().getIntExtra(EXTRA_LAUCH_MODE, 0);
        if(mLaunchMode == 0){
            //載入伺服器資料,虛擬碼,主要看邏輯
            requestRemoteData(mServerId, new Listener(){
                public void onComplete(RemoteBean bean){
                    mData = bean.data;
                    mTitle = bean.title;
                    setDataToUi();
                }
            });
        } else {
            setDataToUi();
        }
        
    }
    
    private void setDataToUi(){
        //把 mData 和 mTitle 資料都設定到 ui 上面
        //.....
    }
}

看到上面做了這樣的更改,以後同事互相啟用對方的頁面變得非常簡單,你只要打 launch 你就知道目標頁面的各種啟用方式。而且也不會因為傳引數的時候引數名寫錯,目標頁面收不到,等問題,減少很多 bug 的出現。

相關文章