Base Activity
我们已经多次用到了Activity,每次都是这么写的:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
全部都继承自Activity
这个基类。之所以这样写是因为,我们要用的Activity都有一些共同的内容,如:方法、属性。所有的Activity都包含onCreate(Bundle savedInstanceState)
等方法。但是,系统的都是基础设施。比如,我们现在遇到一个问题,应用中几乎所有的Activity都要用Toast
来提示信息,比如点击了某一个选项,某一个按钮需要用Toast来显示出来具体的内容。但是,这些在最基础的Activity里是没有的。所以,我们需要自己的BaseActiivty来提供这个功能给应用中的所有Activity使用。
比如,有一个注册Activity和一个登录Activity,如果用户名、密码输入错误都会弹出一个Toast提示。一般会分别给两个Activity添加弹出Toast的代码:
public class Day7LoginActivity extends AppCompatActivity {
EditText userNameEditText;
EditText passwordEditTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_day7_login);
userNameEditText = (EditText) findViewById(R.id.username_edittext);
passwordEditTest = (EditText) findViewById(R.id.password_edittext);
// 1
findViewById(R.id.login_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String un = userNameEditText.getText().toString();
String pwd = passwordEditTest.getText().toString();
if (un.isEmpty() || pwd.isEmpty()) {
Toast.makeText(Day7LoginActivity.this,
"Please enter user name or password.",
Toast.LENGTH_SHORT).show();
}
}
});
// 2
findViewById(R.id.register_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(Day7LoginActivity.this, Day7RegisterActivity.class);
startActivity(i);
}
});
}
}
- 点击登录按钮之后检查用户名、密码,如果有一个没有输入则提示用户需要输入。
- 点击注册按钮可以进入注册页面。
上面的是登录Activity的代码,现在看看注册Activity的:
public class Day7RegisterActivity extends AppCompatActivity {
EditText userNameEditText;
EditText passwordEditTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_day7_register);
userNameEditText = (EditText) findViewById(R.id.username_edittext);
passwordEditTest = (EditText) findViewById(R.id.password_edittext);
findViewById(R.id.register_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String un = userNameEditText.getText().toString();
String pwd = passwordEditTest.getText().toString();
if (un.isEmpty() || pwd.isEmpty()) {
Toast.makeText(Day7RegisterActivity.this,
"Please enter user name or password.",
Toast.LENGTH_SHORT).show();
}
}
});
}
}
用户点击注册之后,一样会检查用户名、密码的输入。如果有一个没有输入则弹出Toast提示用户需要输入用户名密码。
这两个Activity都会弹出Toast,我们可以把这两部分的功能合成为一个功能。所有的Activity需要弹出Toast的时候只需要调用这个方法。具体该怎么做呢?
创建一个Class,命名为BaseActivity。
这一次是新建一个Class(类),不是Activity。所以略有不同。
之所以这么做是因为BaseActivity除了类本身之外不需要布局。
你也可以新建一个Activity,之后删掉布局。
注意,在Superclass这个项目下输入的是AppCompatActivity
。这个是Google推荐的,你可以选择使用android.app.Activity
作为基类。
Superclass以下的内容保持不动,直接点击“OK”完事儿。
添加必要的方法
第一个需要添加的是onCreate(Bundle savedInstanceState)
方法:
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
接下来就是那个我们需要的显示Toast的方法了:
protected void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
方法showToast(String msg)
就是我们说的必要方法了。
继承BaseActivity。
这个方法只有继承了BaseActivity才能使用。所以让登录、注册的Activity都集成BaseActivity:
// 登录Activity
public class Day7LoginActivity extends BaseActivity { ... }
// 注册Activity
public class Day7RegisterActivity extends BaseActivity { ... }
继承了之后就可以使用这个方法了:
//Toast.makeText(Day7RegisterActivity.this,
// "Please enter user name or password.",
// Toast.LENGTH_SHORT).show();
showToast("Please enter user name or password.");
之前弹出Toast的代码都可以注释掉了。你可以看到这个小小的方法省去了很多的麻烦。这个例子还很简单,在实际的开发中会遇到更多使用BaseActivity省去大量复制粘贴代码的麻烦。复制粘贴式的代码复用只会造成代码量的暴涨,增加代码维护的难度!上述的方法不只是一个知识、建议,更是一个很好的开发实践。
在Activity之间传递数据
使用多个Activity就会有需要从一个Activity传递数据给另外一个。下面给出一个最常用的方法。
使用Intent传递数据
上文中,从一个Activity跳转到另外一个都会用到Intent
,如:
Intent i = new Intent(Day7LoginActivity.this, Day7RegisterActivity.class);
startActivity(i);
Intent
有一个方法putExtra(String key, Object value)
可以用来传递参数。我们现在要把登录时填写的用户名,显示在注册Activity里。这并没有什么实际的用户,仅仅是为了演示Activity之间是怎么传递数据的。
findViewById(R.id.register_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(Day7LoginActivity.this, Day7RegisterActivity.class);
// 添加要传递的数据
String un = userNameEditText.getText().toString();
i.putExtra("UN", un);
startActivity(i);
}
});
上面的代码演示了如何添加要传递的数据。很简单。然后看看是如何获取传递过来的数据的。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_day7_register);
userNameEditText = (EditText) findViewById(R.id.username_edittext);
passwordEditTest = (EditText) findViewById(R.id.password_edittext);
findViewById(R.id.register_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String un = userNameEditText.getText().toString();
String pwd = passwordEditTest.getText().toString();
if (un.isEmpty() || pwd.isEmpty()) {
//Toast.makeText(Day7RegisterActivity.this,
// "Please enter user name or password.",
// Toast.LENGTH_SHORT).show();
showToast("Please enter user name or password.");
}
}
});
// 1
Intent passedIntent = getIntent();
// 2
if(passedIntent != null){
// 3
String un = passedIntent.getStringExtra("UN");
userNameEditText.setText(un);
}
}
- 在Activity的
onCreate(Bundle savedInstanceState)
方法里,使用getIntent()
方法获得存放数据的Intent
。 - 获取了Intent之后需要检查一下这个
Intent
是不是为空的。因为有的时候回出乎意料。 - 存放数据的时候使用的Key就是UN,所以在取数据的时候也需要使用一样的Key,也就是UN。
最后取出数据之后,把这个字符串填到了注册Activity的EditText
里。运行一下可见效果。
总结
使用BaseActivity时一个很好的开发实践。在实际的开发过程中一定要尽量的保证完成某个功能的代码只有一份。
在Activity之间传递数据,使用最多的就是用Inent.putExtra(String key, Object value)
方法。Google为了使用方便提供了对应于某些类型的putXXX方法和与之相对的getXXXExtra方法。