public class IDCardUtil {
public static boolean isValidIdCard(String idCard) {
if (idCard == null) {
return false;
}
Pattern p = Pattern.compile("(\\d{17}[0-9a-zA-Z]|\\d{14}[0-9a-zA-Z])");
return p.matcher(idCard).matches();
}
public static String getBirthday(String idCard) {
if (idCard == null) {
return null;
}
Pattern p1 = Pattern.compile("\\d{6}(\\d{8}).*"); // 用于提取出生日字符串
Pattern p2 = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})");// 用于将生日字符串进行分解为年月日
Matcher matcher = p1.matcher(idCard);
if (matcher.find()) {
String birthday = matcher.group(1);
Matcher matcher2 = p2.matcher(birthday);
if (matcher2.find()) {
StringBuilder sb = new StringBuilder();
sb.append(matcher2.group(1));
sb.append('-');
sb.append(matcher2.group(2));
sb.append('-');
sb.append(matcher2.group(3));
return sb.toString();
}
}
return null;
}
}管理activity的生命周期
通过实现回调方法来管理activity的生命周期。一个activity的生命周期受与它关联的其它activity,task和back stack的影响。
一个activity存在3种状态:
- resumed(running)-activity运行在前台并且获得用户焦点。
- paused-另一个activity运行在前台并且获得用户焦点,但是当前activity仍然可见,paused状态下的activity仍然存活(保持同window manager的联系),但是当内存不足的时候可能会被系统kill掉。
- stopped-当前activity完全被另一个activity隐藏掉(用户不可见),并且运行在后台。stopped状态下的activity仍然存活(但是失去了与window manager的联系),但是当内存不足的时候可能会被系统kill掉。
当activity处于paused或者stopped状态的时候,系统可以通过调用它的finish方法或者直接kill掉activity。当activity被再次打开的时候,系统需要整个从头创建该activity。
实现生命周期回调
当一个activity的状态发生变化的时候,系统会通过调用各种回调方法来通知activity,你可以覆盖回调方法,在状态变化的时候做你想做的事情(必须先调用父类的回调方法,然后再追加你自己的实现)。
public class ExampleActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The activity is being created.
}
@Override
protected void onStart() {
super.onStart();
// The activity is about to become visible.
}
@Override
protected void onResume() {
super.onResume();
// The activity has become visible (it is now "resumed").
}
@Override
protected void onPause() {
super.onPause();
// Another activity is taking focus (this activity is about to be "paused").
}
@Override
protected void onStop() {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protected void onDestroy() {
super.onDestroy();
// The activity is about to be destroyed.
}
}
这些回调方法包括3个闭环:
- entire lifetime-从onCreate到onDestroy,比如在onCreate里面开始一个线程,然后在onDestroy里面结束该线程。
- visible lifetime-从onStart到onStop,比如在onStart里面注册一个BroadcastReceiver来监视UI的各种变化,然后在onStop里面取消注册(因为此时用户已经看不到该activity)。
- foreground lifetime-从onResume到onPause,onPause一般在屏幕休眠或者弹出对话框的时候被调用。因为foreground lifetime执行比较频繁,所以在onResume和onPause方法中的代码要力求简洁并且保证快速执行,以提高用户的使用体验。
保存activity的状态
activity处于paused或者stopped状态的时候,activity对象仍然被保存在内存中,所以当activity再次进入前台的时候,原来的状态信息仍然存在。但是,为了释放内存,系统销毁掉activity以后,activity的状态信息也不复存在,这时,用户再次进入activity的时候,原来的状态信息将不复存在。为了保存重要的状态信息,可以通过覆盖onSaveInstanceState方法来实现。
当activity处于容易被销毁的状态的情况下,比如:onStop之前或者onPause之前,会调用onSaveInstanceState方法,并传入一个Bundle对象,你可以把要保存的状态信息以key-value pair的方式存入Bundle对象,这样系统销毁activity之后,用户再次进入activity的时候,系统会把之前保存好的Bundle对象传给onCreate方法和onRestoreInstanceState方法,你可以从Bundle对象中取出之前保存的状态信息。
但是,并不能确保activity在销毁前一定会调用onSaveInstanceState方法,因为有些情况下不需要保存状态信息,比如用户明确点击后退按钮退出activity。
即使你不实现onSaveInstanceState,activity的缺省实现也会保存一部分状态信息,它会分别调用layout中的每个view的onSaveInstanceState方法,大部分widget都会保存自己的状态信息,比如EditText会保存用户输入的信息,CheckBox会保存check状态,唯一需要你做的是为每个想保存状态信息的widget提供一个唯一的android:id。
<TextView android:id="@+id/nameTextbox"/>
aapt工具会自动在R.java中生成一个唯一的整型id,在代码中可以像下面这样直接引用。
findViewById(R.id.nameTextbox);
虽然activity的缺省实现会保存UI的一些信息,但是你可能仍然需要覆盖它来保存一些其他的状态信息,为了保留UI的状态信息,在覆盖onSaveInstanceState和onRestoreInstanceState方法的时候要先调用父类的实现,然后在后面追加你自己的实现。
因为onSaveInstanceState不能保证100%调用,所以,你应该只保存一些临时的状态信息,而不能用来保存持久化的数据,持久化的数据应该在onPause方法中进行保存(比如插入数据库,写入文件等)。
测试你的应用恢复状态信息的能力的一个比较好的方法是,旋转你的设备。因为屏幕方向变化的时候,为了应用相应的资源文件,系统会销毁并重建activity。因为用户在使用应用的时候会经常旋转屏幕,所以确保你的activity在旋转屏幕的时候能够完整地恢复状态信息是十分重要的。
处理配置变更
一些设备可以在运行的时候改变设置,比如:屏幕的方向,可用的键盘,语言。此时,android会重新创建所有运行中的activity(onDestroy,然后onCreate)。这种机制为了帮助你的应用自动重新使用你提供的相应的资源,比如:不同的layout,不同的屏幕方向和大小。
协调activities
当一个activity启动了另一个activity,那么这两个activity都发生了状态的变化,第一个activity先onPause再onStop,另一个activity先onCreate,再onStart,onResume。
activity A启动activity B的过程如下:
如果你需要在activity A stop的时候把一些数据写入数据库,然后在activity B中需要使用这些写入的数据,那么你必须在activity A的onPause方法中写入数据库,而不是onStop方法。
//通过UITableViewDelegate方法可以实现删除 tableview中某一行
//滑动删除
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
[bookInforemoveObjectAtIndex:row];//bookInfo为当前table中显示的array
[tableView deleteRowsAtIndexPaths:[NSArrayarrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationLeft];
}
/*此时删除按钮为Delete,如果想显示为“删除” 中文的话,则需要实现
UITableViewDelegate中的- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath方法*/
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
return @"删除";
}
//或者,最简单的方式,将plist中的Localization native development region改为China即可
//这只是让默认的Delete按钮显示成了中文的删除按钮而已,如果想将这个删除按钮换成其他图片形式的,怎么办呢?
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *RootViewControllerCell = @"RootViewControllerCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:RootViewControllerCell];
if(cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:RootViewControllerCell]autorelease];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:@"delete.png"] forState:UIControlStateNormal];
[button setFrame:CGRectMake(280, 10, 30, 30)];
[button addTarget:self action:@selector(del:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:button];
}
cell.textLabel.text = [array objectAtIndex:[indexPath row]];
cell.tag = [indexPath row];
NSArray *subviews = [cell.contentView subviews];
for(id view in subviews)
{
if([view isKindOfClass:[UIButton class]])
{
[view setTag:[indexPath row]];
[cell.contentView bringSubviewToFront:view];
}
}
return cell;
}
-(void)del:(UIButton *)button
{
NSArray *visiblecells = [self.table visibleCells];
for(UITableViewCell *cell in visiblecells)
{
if(cell.tag == button.tag)
{
[array removeObjectAtIndex:[cell tag]];
[table reloadData];
break;
}
}
}