介紹
我們在開發的時候,一定會遇到頁面跳轉,當沒有登錄的時候,先跳轉到登錄,登錄成功后再跳轉到目標頁。如下圖:
實現這種效果有四種方式:
a. 把數據傳遞到登錄頁面,登錄成功后,把數據在傳遞到目標頁。登錄頁面除了登錄功能還有傳遞數據的功能,但是由于要跳轉的頁面和登錄頁是多對一的關系,所以登錄頁面要用一個標記記錄目標頁,而且要傳遞數據的時候也要經過登錄頁。
b.利用startActivityForResult異步回調將登錄結果返回給源Activity,源Activity在onActivityResult進行下一步操作。
c.使用動態代理的技術實現。
d.參考插件化中啟動插件activity的方式,使用Hook技術修改系統startActivity的行為
本篇文章主要介紹第一種方案,第一種方案的特點是,簡單易上手不容易出錯,缺點是你自己要傳遞的數據被登錄頁面給竊取了,當要跳轉的頁面比較多的時候,登錄頁面就會變得臃腫龐大,登錄頁面多了一些額為的不屬于它的工作。
舉例介紹
這里舉一個簡單的例子:主頁兩個按鈕分別跳轉到我的收藏 我的產品兩個頁面,這兩個頁面都需要登錄。項目的目錄結構如下:
Constant 記錄一些常量
LoginActivity 登錄頁
MainActivity 主頁
MyFavoriteActivity 我的收藏
MyGoodsActivity 我的產品
不傳遞數據的時候
主頁的布局不在介紹,直接說明主頁按鈕的事件的處理:
public class MainActivity extends AppCompatActivity {
private Button myGoodsBtn, myFavoritesBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myGoodsBtn = findViewById(R.id.myGoodsBtn);
myFavoritesBtn = findViewById(R.id.myFavoriteBtn);
myGoodsBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lookMyGoods();
}
});
myFavoritesBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lookMyFavorite();
}
});
}
private void lookMyGoods() {
if (Constant.isLogin) {
MyGoodsActivity.launch(this);
}else {
LoginActivity.launch(this, Constant.REQUEST_CODE_GOODS);
}
}
private void lookMyFavorite() {
if (Constant.isLogin) {
MyFavoriteActivity.launch(this);
}else {
LoginActivity.launch(this, Constant.REQUEST_CODE_FAVORITE);
}
}
邏輯很簡單:沒登錄就跳轉到登錄頁,但是要傳遞一個標記過去。登錄的時候直接跳轉到目標頁。
我的收藏頁面
public class MyFavoriteActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_favorite);
}
public static void launch(Activity activity){
Intent intent = new Intent(activity, MyFavoriteActivity.class);
activity.startActivity(intent);
}
}
我的產品頁
public class MyGoodsActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_goods);
}
public static void launch(Activity activity){
Intent intent = new Intent(activity, MyGoodsActivity.class);
activity.startActivity(intent);
}
登錄頁
public class LoginActivity extends AppCompatActivity {
private EditText userNameEditTv, passwordEditTv;
private int nextForwardCode = -1;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
nextForwardCode = getIntent().getIntExtra(KEY_NEXT_FORWARD, -1);
userNameEditTv = findViewById(R.id.userNameEditTv);
passwordEditTv = findViewById(R.id.passwardEditT);
Button loginButton = findViewById(R.id.loginBtn);
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Constant.isLogin) {
Toast.makeText(LoginActivity.this, "親,您已經登錄了,請不要重復登錄!", Toast.LENGTH_LONG).show();
} else {
if (TextUtils.isEmpty(userNameEditTv.getText()) || TextUtils.isEmpty(passwordEditTv.getText())) {
Toast.makeText(LoginActivity.this, "親,請輸入合法的用戶名或者密碼!", Toast.LENGTH_LONG).show();
return;
}
Constant.isLogin = true;
Toast.makeText(LoginActivity.this, "親,登錄成功!", Toast.LENGTH_LONG).show();
handleLoginSuccess();
}
}
});
}
/**
* 不傳遞數據
*/
private void handleLoginSuccess() {
if (nextForwardCode == -1) {
return;
}
if (nextForwardCode == Constant.REQUEST_CODE_GOODS) {
//todo 查看我的商品
MyGoodsActivity.launch(this);
finish();
} else if (nextForwardCode == Constant.REQUEST_CODE_FAVORITE) {
//todo 查看我的收藏
MyFavoriteActivity.launch(this);
finish();
}
}
private static final String KEY_NEXT_FORWARD = "next_forward";
public static void launch(Activity activity, int code) {
Intent intent = new Intent(activity, LoginActivity.class);
intent.putExtra(KEY_NEXT_FORWARD, code);
activity.startActivity(intent);
}
}
登錄頁面主要就是根據傳遞過來的KEY_NEXT_FORWARD來分別跳轉到不同的目標頁。
這種頁面跳轉的實現起來較簡單,但是當傳遞數據的時候,就比較棘手了。
傳遞數據的時候
傳遞數據的時候要把數據傳遞給登錄頁,登錄頁要進行分發,所以登錄頁面又多了一分責任。
修改后的我的商品頁面:
public class MyGoodsActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_goods);
String data = getIntent().getStringExtra(KEY_DATA);
if (!TextUtils.isEmpty(data)) {
Toast.makeText(this, "我的產品--》data="+data,Toast.LENGTH_LONG).show();
}
Bundle bundle = getIntent().getBundleExtra(Constant.KEY_DATA);
if (bundle != null) {
String msg = bundle.getString(Constant.KEY_MSG);
if (!TextUtils.isEmpty(msg)) {
Toast.makeText(this, "我的產品--》msg="+msg,Toast.LENGTH_LONG).show();
}
}
}
public static void launch(Activity activity){
Intent intent = new Intent(activity, MyGoodsActivity.class);
activity.startActivity(intent);
}
private static final String KEY_DATA = "data";
public static void launchForResult(Activity activity, String data){
Intent intent = new Intent(activity, MyGoodsActivity.class);
intent.putExtra(KEY_DATA, data);
activity.startActivity(intent);
}
public static void launch(Activity activity, Bundle bundle){
Intent intent = new Intent(activity, MyGoodsActivity.class);
intent.putExtra(Constant.KEY_DATA, bundle);
activity.startActivity(intent);
}
}
修改后的收藏頁面:
public class MyFavoriteActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_favorite);
String data = getIntent().getStringExtra(KEY_DATA);
if (!TextUtils.isEmpty(data)) {
Toast.makeText(this, "我的收藏--》data="+data,Toast.LENGTH_LONG).show();
}
Bundle bundle = getIntent().getBundleExtra(Constant.KEY_DATA);
if (bundle != null) {
String msg = bundle.getString(Constant.KEY_MSG);
if (!TextUtils.isEmpty(msg)) {
Toast.makeText(this, "我的收藏--》msg="+msg,Toast.LENGTH_LONG).show();
}
}
}
public static void launch(Activity activity){
Intent intent = new Intent(activity, MyFavoriteActivity.class);
activity.startActivity(intent);
}
private static final String KEY_DATA = "data";
public static void launch(Activity activity, String data){
Intent intent = new Intent(activity, MyGoodsActivity.class);
intent.putExtra(KEY_DATA, data);
activity.startActivity(intent);
}
}
修改后的主頁:
public class MainActivity extends AppCompatActivity {
......
private void lookMyGoods() {
if (Constant.isLogin) {
// MyGoodsActivity.launch(this);
MyGoodsActivity.launch(this, "產品");
}else {
// LoginActivity.launch(this, Constant.REQUEST_CODE_GOODS);
Bundle bundle = new Bundle();
bundle.putString(Constant.KEY_MSG, "通過登錄傳遞的產品");
LoginActivity.launch(this, Constant.REQUEST_CODE_GOODS,bundle);
}
}
private void lookMyFavorite() {
if (Constant.isLogin) {
// MyFavoriteActivity.launch(this);
MyFavoriteActivity.launch(this, "收藏");
}else {
// LoginActivity.launch(this, Constant.REQUEST_CODE_FAVORITE);
Bundle bundle = new Bundle();
bundle.putString(Constant.KEY_MSG, "通過登錄傳遞的收藏");
LoginActivity.launch(this, Constant.REQUEST_CODE_FAVORITE,bundle);
}
}
}
修改后的登錄頁:
public class LoginActivity extends AppCompatActivity {
...
private Bundle bundle;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Constant.isLogin) {
Toast.makeText(LoginActivity.this, "親,您已經登錄了,請不要重復登錄!", Toast.LENGTH_LONG).show();
} else {
if (TextUtils.isEmpty(userNameEditTv.getText()) || TextUtils.isEmpty(passwordEditTv.getText())) {
Toast.makeText(LoginActivity.this, "親,請輸入合法的用戶名或者密碼!", Toast.LENGTH_LONG).show();
return;
}
Constant.isLogin = true;
Toast.makeText(LoginActivity.this, "親,登錄成功!", Toast.LENGTH_LONG).show();
// handleLoginSuccess();
handleLoginSuccess2();
}
}
});
}
...
/**
* 傳遞數據
*/
private void handleLoginSuccess2(){
if (bundle == null) {
return;
}
if (nextForwardCode == Constant.REQUEST_CODE_GOODS) {
//todo 查看我的商品
MyGoodsActivity.launch(this, bundle);
finish();
} else if (nextForwardCode == Constant.REQUEST_CODE_FAVORITE) {
//todo 查看我的收藏
MyGoodsActivity.launch(this, bundle);
finish();
}
}
.......
public static void launch(Activity activity, int code, Bundle bundle) {
Intent intent = new Intent(activity, LoginActivity.class);
intent.putExtra(KEY_NEXT_FORWARD, code);
intent.putExtra(Constant.KEY_DATA, bundle);
activity.startActivity(intent);
}
}
從handleLoginSuccess2方法可以看出,在項目中當很多要跳轉的頁面的時候,這個方法內部就要寫很多switch語句,冗余的代碼勢必增加日后項目的維護難度,而且登錄頁面承擔了一些額為的責任,這也違背了軟件設計原則的單一原則。
但是這種方式也有優點就是容易上手,如果是項目周期短,可以采用這種方案。
下一篇介紹第二種方案