Core Data

我们点击“Create a new Xcode project”来开始我们的Core Data程序工程吧!

屏幕快照 2009-09-01 下午12.06.52

在这里,XCode已经给我们准备好了一个几乎可以直接去用的程序模板,直接选择“基于导航的应用程序”,然后记得点选“Use Core Data for storage”

屏幕快照 2009-09-01 下午12.14.03

建立好的程序名为XCDtest01,我们尝试编译运行,看看得到的程序是什么样的:

屏幕快照 2009-09-01 下午12.16.47

基本上来说,这个程序把什么都给我们弄好了,一个程序,在点击添加按钮之后添加现在的时间标签,如果点击“Edit”编辑按钮,就进入编辑模式,可以删除任意条信息。

如果点开xcdatamodel文件,我们可以看到,其中的实体为Event,有一个参数,名为“时间标签”。也就是说,如果我们想对这个列表视图中的数据作更改,只需要适当更改这个实体的参数,并配置- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 代理条目就可以显示适当的内容了。

屏幕快照 2009-09-01 下午12.20.19

这个预置程序与我们之前讨论的程序不同的,在于这个程序中并没有配置一个可变数组(NSMutableArray)来作数据副本,以达到高速存储的目的。因为Core Data在向磁盘和内存操作,NSMutableArray是内存操作,速度上比较有优势。但是我们有的这个小程序太小了,再者苹果有可能认为那种方法是非标准的。所以在这里才没有那么作

NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = [[managedObject valueForKey:@"timeStamp"] description];

在这个程序的cell配置代理里面,仅仅是从“获取操作控制器”中得到了“被管理对象”,然后再读取其中的内容到cell的text中。

希望大家也使用这个模板,自己创建一个Core Data程序,然后简单的理解一下代码。下次我们聊只使用基于Window的程序模板+Core Data来创建程序
CoreData实例分析学习(1)转自 http://c.gzl.name/archives/393

屏幕快照 2009-08-26 下午04.05.29

Core Data是个好东西,在数据储存操作上速度快,容易操作,是一种类似关系数据库的东西。但是有些不那么好学,那到底Core Data是怎么操作的呢?怎么用呢?怎么来编程呢?我们一起来学习吧,接下来使用苹果提供的实例程序Locations来作分析:

>程序介绍:

右侧是改程序的截图,基本上来说就是通过使用Core Location来得到当时的位置,然后在点击“+”的时候记录下当时的经纬度。通过UITableViewController的功能来添加,编辑,删除等功能。整体程序使用Core Data来储存数据,实体(Entity)为一个位置,包括以下参数:1,时间(收集数据的时间)2,纬度,3,经度

首先我们看看该程序的AppDelegate.h

@interface LocationsAppDelegate : NSObject  

{    

  UIWindow *window;    

  UINavigationController *navigationController; //导航栏       

 //以下定义了Core Data的三个决定性组建,等后面m文件里面再多介绍     

 NSPersistentStoreCoordinator *persistentStoreCoordinator;    

 NSManagedObjectModel *managedObjectModel;    

 NSManagedObjectContext *managedObjectContext; 

}   

@property (nonatomic,retain) IBOutlet UIWindow *window; 

@property (nonatomic,retain) UINavigationController *navigationController;   

- (IBAction)saveAction:sender; //这个没找到作用...根本就没用到IB   

//还记得吧,nonatomic是因为这个程序是单线程 

@property (nonatomic,retain,readonly) NSManagedObjectModel *managedObjectModel; 

@property (nonatomic,readonly) NSManagedObjectContext *managedObjectContext; 

@property (nonatomic,readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator; 

@property (nonatomic,readonly) NSString *applicationDocumentsDirectory; //程序文档目录是主要为了给NSPersistentStoreCoordinator找个存SQLite文件的地方 

@end

从上面的我们能看出来,该程序是通过一个根Core Data数据管理来管理整个程序的CoreData数据的,接下来看m文件也会对此作更多的理解。

#import "LocationsAppDelegate.h" 

#import "RootViewController.h" 

@implementation LocationsAppDelegate 

@synthesize window; 

@synthesize navigationController;   

- (void)applicationDidFinishLaunching:(UIApplication *)application 

{  

 //初始化根视图控制器,它是一个列表视图控制器  

 RootViewController *rootViewController = [[RootViewController alloc]              

 initWithStyle:UITableViewStylePlain];    

 //通过下面的自定义getter得到CoreData的“被管理对象内容器”   

 NSManagedObjectContext *context = [self managedObjectContext];  

 if (!context)

  {   

  // 如果getter出错,在这里来排错 

  } 

 rootViewController.managedObjectContext = context;  //rootViewController有一个本地“被管理对象内容器”,在这里赋值过去    

 UINavigationController *aNavigationController = [[UINavigationController alloc]              initWithRootViewController:rootViewController];  

 self.navigationController = aNavigationController;  //初始化导航栏,根视图为rootViewController,并指定该导航栏为程序导航栏  

 [window addSubview:[navigationController view]];  

 [window makeKeyAndVisible];    

 //由于导航栏retain了根视图,所以在这里可以release掉它了  

 [rootViewController release];  

 //由于self已经retain了导航栏,所以导航栏可以release  

 [aNavigationController release]; }   

 //applicationWillTerminate: 在程序结束前,Core Data会保存任何对其的更改 

- (void)applicationWillTerminate:(UIApplication *)application

 {      

  NSError *error;     

 if (managedObjectContext != nil) 

 {         

  if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])

   {    // Handle the error.         }    

  }

 }   

//在得到点击事件后,保存更改 

- (IBAction)saveAction:(id)sender

 {       

 NSError *error;    

 if (![[self managedObjectContext] save:&error])

 {   // Handle error     } 

}  

//自定义的managedObjectContext的getter,它其实是真正在使用的时候的被操作对象 

- (NSManagedObjectContext *) managedObjectContext

{       

 //如果已经有这个对象,就直接返回,否则继续     

  if (managedObjectContext != nil) 

  { return managedObjectContext; }       

 NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];     

 if (coordinator != nil)

  {         

  managedObjectContext = [[NSManagedObjectContext alloc] init];         

  [managedObjectContext setPersistentStoreCoordinator: coordinator];        

  //这里可以看到,“内容管理器”和“数据一致性存储器”的关系,        

  //managedObjectContext需要得到这个“数据一致性存储器”     

 }     

 return managedObjectContext; 

}   

//自定义的CoreData数据模板的getter,数据模板其实就是一个描述实体与实体的关系,类似于关系型数据库的关系描述文件 

- (NSManagedObjectModel *)managedObjectModel 

{       

 if (managedObjectModel != nil) 

 { return managedObjectModel; }     

 managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];     

 //从本地所有xcdatamodel文件得到这个CoreData数据模板     

 return managedObjectModel; 

}   

//自定义“数据一致性存储器” persistentStoreCoordinator的getter 

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 

{       

 if (persistentStoreCoordinator != nil) 

 { return persistentStoreCoordinator; }       

 //定义一个本地地址到NSURL,用来存储那个SQLite文件     

 NSURL *storeUrl = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory]                             stringByAppendingPathComponent: @"Locations.sqlite"]];    

 NSError *error;     

 persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]             

 initWithManagedObjectModel: [self managedObjectModel]];     

 //从这里可以看出,其实persistentStoreCoordinator需要的不过是一个     

 //存储数据的位置,它是负责管理CoreData如何储存数据的     

 if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType  configuration:nil URL:storeUrl options:nil error:&error]) 

 { // Handle the error.}           

 return persistentStoreCoordinator; 

}   

//返回该程序的档案目录,用来简单使用 

- (NSString *)applicationDocumentsDirectory 

{       

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);     

 NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;     

 return basePath;

}   

- (void)dealloc 

{       

 //释放内存     

 [managedObjectContext release];     

 [managedObjectModel release];     

 [persistentStoreCoordinator release];    

 [navigationController release];  

 [window release];  

 [super dealloc]; 

} @end

从上面的程序主代理文件可以看出,CoreData的简单使用不过是通过三个组建。

NSManagedObjectModel来描述实体与实体的关系,也就是类似于表和表的关系。
NSManagedObjectContext来得到被储存内容的文件管理器,对数据作直接操作
NSPersistentStoreCoordinator来管理数据的储存位置,储存方法(SQLite)

你对Core Data理解更多了么?

补一下“实体”的概念,实体也就是Entity,在打开xcdatamodel文件的时候,我们可以看到

屏幕快照 2009-08-26 下午05.08.29

在这里,这个实体叫“Event”,而实体的参数有“创建日期”,“纬度”,“经度”。也就是说,其实这个实体被使用后,我们可以这样理解,实体就是表名,而参数就是列名,然后整个实体就是一张表。当这个Model描述多个实体的关系的时候,就像是一个关系型数据库一样,虽然苹果说“不是!”
CoreData实例分析学习(2)转自 http://c.gzl.name/archives/412

在我们分析了程序主代理文件(AppDelegate)之后,我们先来看看一对自动生成的文件Event.h/.m

@interface Event : NSManagedObject  

{

} 

@property (nonatomic,retain) NSDate *creationDate; 

@property (nonatomic,retain) NSNumber *latitude; 

@property (nonatomic,retain) NSNumber *longitude; 

@end



#import "Event.h" 

@implementation Event 

@dynamic creationDate; 

@dynamic latitude; 

@dynamic longitude; 

@end

从上面我们能看出来,一个实体Event也就会被生成一个NSManagedObject(被管理对象),然后任何accessor和getter都是被动态生成的,我们其实完全不用操任何的心,只需要在xcdatamodel文件里面配置后,点击添加文件,添加NSManagedObject文件,就会看到自动感知的类对象,然后生成就可以了。

下面是根视图控制器,是一个列表视图(UITableViewController)

#import <CoreLocation/CoreLocation.h> 

@interface RootViewController : UITableViewController <CLLocationManagerDelegate> 

{  

 //看到是UITableViewController的子类,由于需要使用Core Location,  

 //所以在后面履行其protocal     

 NSMutableArray *eventsArray;  

 NSManagedObjectContext *managedObjectContext;  //这个被管理对象内容器就是我们真正对Core Data数据的操作对象     

 CLLocationManager *locationManager;  //用来得到地理位置的Core Location对象     

 UIBarButtonItem *addButton; //右上角的添加键 

} 

@property (nonatomic,retain) NSMutableArray *eventsArray; 

@property (nonatomic,retain) NSManagedObjectContext *managedObjectContext; 

@property (nonatomic,retain) CLLocationManager *locationManager; 

@property (nonatomic,retain) UIBarButtonItem *addButton; 


- (void)addEvent; 

@end


#import "RootViewController.h" 

#import "LocationsAppDelegate.h" 

#import "Event.h" 

@implementation RootViewController 

@synthesize eventsArray,managedObjectContext,addButton,locationManager;   

- (void)viewDidLoad 

{     

 [super viewDidLoad];     

 self.title = @"Locations"; //设置列表视图的标题     

 self.navigationItem.leftBarButtonItem = self.editButtonItem; //导航栏左边的编辑按钮       

 addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd    target:self action:@selector(addEvent)]; //初始化添加按钮,  

 addButton.enabled = NO; //在Core Location初始化之前将其关闭     

 self.navigationItem.rightBarButtonItem = addButton;     //把这个添加按钮添加到导航栏右侧    

 // 启动CLocation  

 [[self locationManager] startUpdatingLocation];           

 //初始化一个“获取请求”到我们的实体“Event”  

 NSFetchRequest *request = [[NSFetchRequest alloc] init];  

 NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];  

 [request setEntity:entity];    

 // 将时间以建立时间排序,最新的在最上  

 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];  

 NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor,nil];  

 [request setSortDescriptors:sortDescriptors];  

 [sortDescriptor release];  

 [sortDescriptors release];    

 // 执行“获取”操作,得到一个“可变数组”的拷贝  

 NSError *error = nil;  

 NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request      error:&error] mutableCopy];  

 if (mutableFetchResults == nil) 

 { //如果结果为空,在这作错误响应 }    

 // 将得到的本地数组赋值到本类的全局数组,然后清理无用的对象  

 [self setEventsArray:mutableFetchResults];  

 [mutableFetchResults release];  

 [request release]; 

}   


- (void)viewDidUnload 

{  

 // 当视图被卸载后,将以下指针置空  

 self.eventsArray = nil;  

 self.locationManager = nil;  

 self.addButton = nil; 

}   

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 

{  // 只有一个章节     return 1; }   

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 

{  

 // 在数组里面有多少个对象,在列表视图就有多少行     

 return [eventsArray count]; 

}   

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    

 // 一个“日期格式化器”(凑合明白就好...)用来以特定的格式创建得到的日期     

 static NSDateFormatter *dateFormatter = nil;  

 if (dateFormatter == nil) 

 {   

  dateFormatter = [[NSDateFormatter alloc] init];   

  [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];   

  [dateFormatter setDateStyle:NSDateFormatterMediumStyle];  

 }    

 static NSNumberFormatter *numberFormatter = nil;  

 if (numberFormatter == nil) 

 {   

  numberFormatter = [[NSNumberFormatter alloc] init];   

  [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];   

  [numberFormatter setMaximumFractionDigits:3];  

 }       

 

 static NSString *CellIdentifier = @"Cell";       

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];     

 if (cell == nil) 

 {         

  cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];   

  UITableViewCellStyleSubtitle;     

 }    

 // 从数组中得到这个Event对象  

 Event *event = (Event *)[eventsArray objectAtIndex:indexPath.row];    

 cell.textLabel.text = [dateFormatter stringFromDate:[event creationDate]];    

 NSString *string = [NSString stringWithFormat:@"%@,%@",[numberFormatter stringFromNumber:[event latitude]],[numberFormatter stringFromNumber:[event longitude]]];     

 cell.detailTextLabel.text = string;    

 return cell; 

}   

- (void)tableView:(UITableView *)tableView   commitEditingStyle:(UITableViewCellEditingStyle)editingStyle   forRowAtIndexPath:(NSIndexPath *)indexPath  

{       

 if (editingStyle == UITableViewCellEditingStyleDelete) 

 { // 删除被惯例对象在索引路径(index path)   

  NSManagedObject *eventToDelete = [eventsArray objectAtIndex:indexPath.row];   

  [managedObjectContext deleteObject:eventToDelete];    

  // 更新数组和列表视图         

  [eventsArray removeObjectAtIndex:indexPath.row];         

  [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];     

  // 提交更改到Core Data   

  NSError *error;   

  if (![managedObjectContext save:&error]) 

  {    // Handle the error.   }     

 } 

}   

- (void)addEvent 

{  

 //如果得不到位置,就返回.  

 CLLocation *location = [locationManager location];  

 if (!location) 

 {   return; }     

 //建立一个Event实体对象  

 Event *event = (Event *)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:managedObjectContext];    

 //得到经纬度,然后赋值到event对象去  

 CLLocationCoordinate2D coordinate = [location coordinate];  

 [event setLatitude:[NSNumber numberWithDouble:coordinate.latitude]];  

 [event setLongitude:[NSNumber numberWithDouble:coordinate.longitude]];    

 // 实例里面并没有使用CL的时间标签,因为在模拟器中会是一样的  

 // [event setCreationDate:[location timestamp]];  

 [event setCreationDate:[NSDate date]];   

 //所以现在使用的是现在的时间,而不是得到位置的时候的时间    

 // 保存更改  

 NSError *error;  

 if (![managedObjectContext save:&error]) 

 {   // Handle the error.  }    

 // 将新Event放到最上面,所以添加到0的位置  

 // 然后滚动列表视图到最上面,如果没有那么多的数据是看不出来区别的  

 [eventsArray insertObject:event atIndex:0];  

 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];  

 [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];  

 [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES]; 

}   

- (CLLocationManager *)locationManager 

{  

 //自定义的CLocation的getter,方便初始化     

 if (locationManager != nil) 

 {   return locationManager;  }  

 //初始化CL对象,然后设置精准度,然后将代理对象设为本地  

 locationManager = [[CLLocationManager alloc] init];  

 [locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];  

 [locationManager setDelegate:self];    return locationManager; 

} 

//CLocation的一个代理方法,如果成功就开启右侧添加按钮 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation   fromLocation:(CLLocation *)oldLocation 

{     

 addButton.enabled = YES; 

} 

//CLocation的一个代理方法,如果失败了就关闭(disable)右侧添加按钮 

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 

{     

 addButton.enabled = NO; 

}   

- (void)dealloc 

{  

 //释放对象  

 [managedObjectContext release];  

 [eventsArray release];     

 [locationManager release];     

 [addButton release];     

 [super dealloc]; 

} 

@end

从上面的源代码,我们可以看出,
1,在这里数据并不是每次都由NSManagedContext对象得到,而是由一个数组得出。
2,数组是一个可变数组,由第一次载入的视图的时候从NSManagedContext中得到
3,从NSManagedContext对象中得到数据需要使用NSFetchRequest来初始化一个“获取”
4,每次获得新的数据的时候,同时保存到数组和NSManagedContext中,添加后需要对更改进行提交

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


SQLite架构简单,又有Json计算能力,有时会承担Json文件/RESTful的计算功能,但SQLite不能直接解析Json文件/RESTful,需要用Java代码硬写,或借助第三方类库,最后再拼成insert语句插入数据表,代码非常繁琐,这里就不展示了。参考前面的代码可知,入库的过程比较麻烦,不能只用SQL,还要借助Java或命令行。SPL是现代的数据计算语言,属于简化的面向对象的语言风格,有对象的概念,可以用点号访问属性并进行多步骤计算,但没有继承重载这些内容,不算彻底的面向对象语言。...
使用Python操作内置数据库SQLite以及MySQL数据库。
破解微信数据库密码,用python导出微信聊天记录
(Unity)SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。SQLite 源代码不受版权限制。本教程将告诉您如何使用 SQLite 编程,并让你迅速上手。.................................
安卓开发,利用SQLite实现登陆注册功能
相比大多数数据库而言,具有等优势,广泛应用于、等领域。
有时候,一个项目只有一个数据库,比如只有SQLite,或者MySQL数据库,那么我们只需要使用一个固定的数据库即可。但是一个项目如果写好了,有多个用户使用,但是多个用户使用不同的数据库,这个时候,我们就需要把软件设计成可以连接多个数据库的模式,用什么数据库,就配置什么数据库即可。4.Users实体类,这个实体类要和数据库一样的,形成一一对应的关系。11.Sqlite数据库,需要在代码里面创建数据库,建立表,再建立数据。8.我们开启MySQL数据库,然后进行调试,看程序的结果。2.安装SqlSugar。
基于Android的背单词软件,功能强大完整。
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统。说白了就是使用起来轻便简单,
Android的简单购物车案例
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库...
Qt设计较为美观好看的登录注册界面(包含SQLite数据库以及TCP通信的应用)
SQLite是用C语言开发的跨平台小型数据库,可嵌入其他开发语言,也可在单机执行。SPL是用Java开发的跨平台的数据计算语言,可嵌入Java,可在单机执行,可以数据计算服务的形式被远程调用。两者的代码都是解释执行的。...
新建库.openDATA_BASE;新建表createtableLIST_NAME(DATA);语法:NAME关键字...<用逗号分割>删除表droptableNAME;查看表.schema查看表信息新建数据insertintoLIST_NAMEvalues();语法:CLASS,PARAMETER...,CLASS是类别,PARAMETER是参数<用逗号分割新建的
importsqlite3classDemo01:def__init__(self):self.conn=sqlite3.connect("sql_demo_001.db")self.cursor1=self.conn.cursor()self.cursor1.execute("select*fromtable_001wherename=?andid=?",('ssss&#0
 在客户端配置文件<configuration>节点下,添加:<connectionStrings>      <add name="localdb" connectionString="Data Source=config/local.db;Version=3;UseUTF16Encoding=True;" providerName="System.Data.SQLite.SQLiteFactory"/&g
提到锁就不得不说到死锁的问题,而SQLite也可能出现死锁。下面举个例子:连接1:BEGIN(UNLOCKED)连接1:SELECT...(SHARED)连接1:INSERT...(RESERVED)连接2:BEGIN(UNLOCKED)连接2:SELECT...(SHARED)连接1:COMMIT(PENDING,尝试获取EXCLUSIVE锁,但还有SHARED锁未释放,返回SQLITE_BUSY)连接2:INSERT...
SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,甚至在iOS和Android的App中都可以集成。Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接使用。在使用SQLite前,我们先要搞清楚几个概念:表
设计思想————首先要确定有几个页面、和每个页面的大致布局由于是入门,我也是学习了不是很长的时间,所以项目比较low。。。。第一个页面,也就是打开APP的首页面:今天这个博客,先实现添加功能!:首先对主界面进行布局:其中activity_main.xml的代码为<?xmlversion="1.0"encoding="