SQLite存储方式详解

【Android游戏开发十三】(保存游戏数据 [下文])详解SQLite存储方式,并把SQLite的数据库文件存储在SD卡中!!!

分类:【 Android 游戏开发】 9574人阅读 评论(38) 收藏 举报

Himi 原创, 欢迎转载,转载请在明显处注明! 谢谢。

原文地址:http://blog.csdn.net/xiaominghimi/archive/2011/01/04/6114629.aspx

先介绍几个基本概念知识:

什么是SQLite:

SQLite是一款轻量级数据库,它的设计目的是嵌入式,而且它占用的资源非常少,在嵌入式设备中,只需要几百KB!!!!!

SQLite的特性:

  • 轻量级
    使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小。
  • 独立性
    SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的“安装”。
  • 隔离性
    SQLite 数据库中所有的信息(比如表、视图、触发器等)都包含在一个文件夹内,方便管理和维护。
  • 跨平台
    SQLite 目前支持大部分操作系统,不至电脑操作系统更在众多的手机系统也是能够运行,比如:Android。
  • 多语言接口
    SQLite 数据库支持多语言编程接口。
  • 安全性
    SQLite 数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但只能有一个可以写入数据.

优点:1.能存储较多的数据。

2.能将数据库文件存放到SD卡中!

什么是 SQLiteDatabase?

一个 SQLiteDatabase 的实例代表了一个SQLite 的数据库,通过SQLiteDatabase 实例的一些方法,我们可以执行SQL 语句,对数 据库进行增、删、查、改的操作。需要注意的是,数据库对于一个应用来说是私有的,并且在一个应用当中,数据库的名字也是惟一的。

什么是 SQLiteOpenHelper ?

根据这名字,我们可以看出这个类是一个辅助类。这个类主要生成一个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的 方法getWritableDatabase(),或者getReadableDatabase()方法的时候,如果当时没有数据,那么Android 系统就会自动生成一 个数 据库。SQLiteOpenHelper 是一个抽象类,我们通常需要继承它,并且实现里边的3 个函数,

什么是 ContentValues 类?

ContentValues 类和Hashmap/Hashtable 比较类似,它也是负责存储一些名值对,但是它存储的名值对当中的名是一个

String 类型,而值都是基本类型。

什么是 Cursor ?

Cursor 在Android 当中是一个非常有用的接口,通过Cursor 我们可以对从数据库查询出来的结果集进行随机的读写访问。

OK,基本知识就介绍到这里,下面开始上代码:还是按照我的一贯风格,代码中该解释的地方都已经在代码中及时注释和讲解了!

顺便来张项目截图:

先给出xml:

[xhtml:showcolumns] view plain copy
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"android:layout_width="fill_parent"
  4. android:layout_height="fill_parent">
  5. TextViewandroid:layout_width="fill_parent"
  6. android:layout_height="wrap_content"android:text="SQL练习!(如果你使用的SD卡存储数据方式,为了保证正常操作,请你先点击创建一张表然后再操作)"
  7. android:textSize="20sp"android:textColor="#ff0000"android:id="@+id/tv_title"/>
  8. Buttonandroid:id="@+id/sql_addOne"android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"android:text="插入一条记录"></Button>
  10. Buttonandroid:id="@+id/sql_check"android:layout_width="fill_parent"
  11. android:layout_height="wrap_content"android:text="查询数据库"Buttonandroid:id="@+id/sql_edit"android:layout_width="fill_parent"
  12. android:layout_height="wrap_content"android:text="修改一条记录"Buttonandroid:id="@+id/sql_deleteOne"android:layout_width="fill_parent"
  13. android:layout_height="wrap_content"android:text="删除一条记录"Buttonandroid:id="@+id/sql_deleteTable"android:layout_width="fill_parent"
  14. android:layout_height="wrap_content"android:text="删除数据表单"Buttonandroid:id="@+id/sql_newTable"android:layout_width="fill_parent"
  15. android:layout_height="wrap_content"android:text="新建数据表单"LinearLayout>

xml中定义了我们需要练习用到的几个操作按钮,这里不多解释了,下面看java源码:先看我们继承的SQLiteOpenHelper 类

[java:showcolumns] view plain copy
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
    packagecom.himi;
  1. importandroid.content.Context;
  2. importandroid.database.sqlite.SQLiteDatabase;
  3. importandroid.database.sqlite.SQLiteOpenHelper;
  4. importandroid.util.Log;
  5. /**
  6. *
  7. *@authorHimi
  8. *@解释此类我们只需要传建一个构造函数以及重写两个方法就OK啦、
  9. *
  10. */
  11. publicclassMySQLiteOpenHelperextendsSQLiteOpenHelper{
  12. finalstaticintVERSION=1;//版本号
  13. staticStringTABLE_NAME="himi";//表名
  14. staticStringID="id";//后面ContentProvider使用
  15. staticStringTEXT="text";
  16. finalStringDATABASE_NAME="Himi.db";
  17. publicMySQLiteOpenHelper(Contextcontext){
  18. //在Android中创建和打开一个数据库都可以使用openOrCreateDatabase方法来实现,
  19. //因为它会自动去检测是否存在这个数据库,如果存在则打开,不过不存在则创建一个数据库;
  20. //创建成功则返回一个SQLiteDatabase对象,否则抛出异常FileNotFoundException。
  21. //下面是来创建一个名为"DATABASE_NAME"的数据库,并返回一个SQLiteDatabase对象
  22. super(context,DATABASE_NAME,null,VERSION);
  23. }
  24. @Override
  25. //在数据库第一次生成的时候会调用这个方法,一般我们在这个方法里边生成数据库表;
  26. voidonCreate(SQLiteDatabasedb){
  27. Stringstr_sql="CREATETABLE"+TABLE_NAME+"("+ID
  28. +"INTEGERPRIMARYKEYAUTOINCREMENT,"+TEXT+"text);";
  29. //CREATETABLE创建一张表然后后面是我们的表名
  30. //然后表的列,第一个是id方便操作数据,int类型
  31. //PRIMARYKEY是指主键这是一个int型,用于唯一的标识一行;
  32. //AUTOINCREMENT表示数据库会为每条记录的key加一,确保记录的唯一性;
  33. //最后我加入一列文本String类型
  34. //----------注意:这里str_sql是sql语句,类似dos命令,要注意空格!
  35. db.execSQL(str_sql);
  36. //execSQL()方法是执行一句sql语句
  37. //虽然此句我们生成了一张数据库表和包含该表的sql.himi文件,
  38. //但是要注意不是方法是创建,是传入的一句str_sql这句sql语句表示创建!!
  39. voidonUpgrade(SQLiteDatabasedb,153); background-color:inherit; font-weight:bold">intoldVersion,153); background-color:inherit; font-weight:bold">intnewVersion){
  40. //一般默认情况下,当我们插入数据库就立即更新
  41. //当数据库需要升级的时候,Android系统会主动的调用这个方法。
  42. //一般我们在这个方法里边删除数据表,并建立新的数据表,
  43. //当然是否还需要做其他的操作,完全取决于游戏需求。
  44. Log.v("Himi","onUpgrade");
  45. }

我喜欢代码中立即附上解释,感觉这样代码比较让大家更容易理解和寻找,当然如果童鞋们不喜欢,可以告诉我,我改~嘿嘿~

下面看最重要的MainActivity中的代码:

copy
importjava.io.File;
  • importjava.io.IOException;
  • importandroid.app.Activity;
  • importandroid.content.ContentValues;
  • importandroid.database.Cursor;
  • importandroid.os.Bundle;
  • importandroid.view.View;
  • importandroid.view.Window;
  • importandroid.view.WindowManager;
  • importandroid.view.View.OnClickListener;
  • importandroid.widget.Button;
  • importandroid.widget.TextView;
  • //------------第三种保存方式--------《SQLite》---------
  • *@authorHimi
  • *@保存方式:SQLite轻量级数据库、
  • *@优点:可以将自己的数据存储到文件系统或者数据库当中,也可以将自己的数据存
  • *储到SQLite数据库当中,还可以存到SD卡中
  • *@注意1:数据库对于一个游戏(一个应用)来说是私有的,并且在一个游戏当中,
  • *数据库的名字也是唯一的。
  • *@注意2apk中创建的数据库外部的进程是没有权限去读/写的,
  • *我们需要把数据库文件创建到sdcard上可以解决类似问题.
  • *@注意3当你删除id靠前的数据或者全部删除数据的时候,SQLite不会自动排序,
  • *也就是说再添加数据的时候你不指定id那么SQLite默认还是在原有id最后添加一条新数据
  • *@注意4android中的SQLite语法大小写不敏感,也就是说不区分大小写;
  • classMainActivityextendsActivityimplementsOnClickListener{
  • privateButtonbtn_addOne,btn_deleteone,btn_check,btn_deleteTable,248); line-height:18px"> btn_edit,btn_newTable;
  • privateTextViewtv;
  • privateMySQLiteOpenHelpermyOpenHelper;//创建一个继承SQLiteOpenHelper类实例
  • privateSQLiteDatabasemysql;
  • //---------------以下两个成员变量是针对在SD卡中存储数据库文件使用
  • //privateFilepath=newFile("/sdcard/himi");//创建目录
  • //privateFilef=newFile("/sdcard/himi/himi.db");//创建文件
  • @Override
  • voidonCreate(BundlesavedInstanceState){
  • super.onCreate(savedInstanceState);
  • getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  • WindowManager.LayoutParams.FLAG_FULLSCREEN);
  • this.requestWindowFeature(Window.FEATURE_NO_TITLE);
  • setContentView(R.layout.main);
  • tv=(TextView)findViewById(R.id.tv_title);
  • btn_addOne=(Button)findViewById(R.id.sql_addOne);
  • btn_check=(Button)findViewById(R.id.sql_check);
  • btn_deleteone=(Button)findViewById(R.id.sql_deleteOne);
  • btn_deleteTable=(Button)findViewById(R.id.sql_deleteTable);
  • btn_newTable=(Button)findViewById(R.id.sql_newTable);
  • btn_edit=(Button)findViewById(R.id.sql_edit);
  • btn_edit.setOnClickListener(this);
  • btn_addOne.setOnClickListener(this);
  • btn_check.setOnClickListener( btn_deleteone.setOnClickListener( btn_deleteTable.setOnClickListener( btn_newTable.setOnClickListener( myOpenHelper=newMySQLiteOpenHelper(this);//实例一个数据库辅助器
  • //备注1----如果你使用的是将数据库的文件创建在SD卡中,那么创建数据库mysql如下操作:
  • //if(!path.exists()){//目录存在返回false
  • //path.mkdirs();//创建一个目录
  • //}
  • //if(!f.exists()){//文件存在返回false
  • //try{
  • //f.createNewFile();//创建文件
  • //}catch(IOExceptione){
  • ////TODOAuto-generatedcatchblock
  • //e.printStackTrace();
  • //}
  • }
  • voidonClick(Viewv){
  • try{
  • //备注2----如果你使用的是将数据库的文件创建在SD卡中,那么创建数据库mysql如下操作:
  • //mysql=SQLiteDatabase.openOrCreateDatabase(f,null);
  • //备注3---如果想把数据库文件默认放在系统中,那么创建数据库mysql如下操作:
  • mysql=myOpenHelper.getWritableDatabase();//实例数据库
  • if(v==btn_addOne){//添加数据
  • //----------------------读写句柄来插入---------
  • //ContentValues其实就是一个哈希表HashMap,key值是字段名称,
  • //Value值是字段的值。然后通过ContentValues的put方法就可以
  • //把数据放到ContentValues中,然后插入到表中去!
  • ContentValuescv=newContentValues();
  • cv.put(MySQLiteOpenHelper.TEXT,"测试新的数据");
  • mysql.insert(MySQLiteOpenHelper.TABLE_NAME,//inser()第一个参数标识需要插入操作的表名
  • //第二个参数:默认传null即可
  • //第三个是插入的数据
  • //----------------------SQL语句插入--------------
  • //StringINSERT_DATA=
  • //"INSERTINTOhimi(id,text)values(1,'通过SQL语句插入')";
  • //db.execSQL(INSERT_DATA);
  • tv.setText("添加数据成功!点击查看数据库查询");
  • }elseif(v==btn_deleteone){//删除数据
  • //----------------------读写句柄来删除
  • mysql.delete("himi",MySQLiteOpenHelper.ID+"=1",153); background-color:inherit; font-weight:bold">null);
  • //第一个参数需要操作的表名
  • //第二个参数为id+操作的下标如果这里我们传入null,表示全部删除
  • //第三个参数默认传null即可
  • //-----------------------SQL语句来删除
  • //StringDELETE_DATA="DELETEFROMhimiWHEREid=1";
  • //db.execSQL(DELETE_DATA);
  • tv.setText("删除数据成功!点击查看数据库查询");
  • if(v==btn_check){//遍历数据
  • //备注4------
  • Cursorcur=mysql.rawQuery("SELECT*FROM"
  • +MySQLiteOpenHelper.TABLE_NAME,153); background-color:inherit; font-weight:bold">null);
  • if(cur!=null){
  • Stringtemp="";
  • inti=0;
  • while(cur.moveToNext()){//直到返回false说明表中到了数据末尾
  • temp+=cur.getString(0);
  • //参数0指的是列的下标,这里的0指的是id列
  • 1);
  • //这里的0相对于当前应该是咱们的text列了
  • i++;
  • temp+="";//这里是我整理显示格式,呵呵~
  • if(i%3==0)
  • temp+="/n"; tv.setText(temp);
  • }if(v==btn_edit){//修改数据
  • //------------------------句柄方式来修改-------------
  • "修改后的数据");
  • mysql.update("himi",cv,"id"+"="+Integer.toString(3),0); background-color:inherit">//------------------------SQL语句来修改-------------
  • //StringUPDATA_DATA=
  • //"UPDATEhimiSETtext='通过SQL语句来修改数据'WHEREid=1";
  • //db.execSQL(UPDATA_DATA);
  • tv.setText("修改数据成功!点击查看数据库查询");
  • if(v==btn_deleteTable){//删除表
  • mysql.execSQL("DROPTABLEhimi");
  • tv.setText("删除表成功!点击查看数据库查询");
  • if(v==btn_newTable){//新建表
  • StringTABLE_NAME="himi";
  • StringID="id";
  • StringTEXT="text";
  • Stringstr_sql2="CREATETABLE"+TABLE_NAME+"("+ID
  • +"INTEGERPRIMARYKEYAUTOINCREMENT,"+TEXT
  • +"text);";
  • mysql.execSQL(str_sql2);
  • tv.setText("新建表成功!点击查看数据库查询");
  • //删除数据库:
  • //this.deleteDatabase("himi.db");
  • catch(Exceptione){
  • tv.setText("操作失败!");
  • finally{//如果try中异常,也要对数据库进行关闭
  • mysql.close();
  • }
  • 以上代码中我们实现了两种存储方式:

    一种存储默认系统路径/data-data-com.himi-databases下,另外一种则是保存在了/sdcard-himi下,生成数据库文件himi.db

    那么这里两种实现方式大概步骤和区别说下:

    -----------如果我们使用默认系统路径存储数据库文件:

    第一步:新建一个类继承SQLiteOpenHelper;写一个构造,重写两个函数!

    第二步:在新建的类中的onCreate(SQLiteDatabase db) 方法中创建一个表;

    第三步:在进行删除数据、添加数据等操作的之前我们要得到数据库读写句柄得到一个数据库实例;

    注意:继承写这个辅助类,是为了在我们没有数据库的时候自动为我们生成一个数据库,并且生成数据库文件,这里也同时创建了一张表,因为我们在onCreate里是在数据库中创建一张表的操作;这里还要注意在我们new 这个我们这个MySQLiteOpenHelper 类实例对象的时候并没有创建数据库哟~!而是在我们调用(备注3)MySQLiteOpenHelper ..getWritableDatabase() 这个方法得到数据库读写句柄的时候,android 会分析是否已经有了数据库,如果没有会默认为我们创建一个数据库并且在系统路径data-data-com.himi-databases下生成himi.db 文件!

    (如果我们使用sd卡存储数据库文件,就没有必要写这个类了,而是我们自己Open自己的文件得到一个数据库,西西,反而方便~ )

    -----------如果我们需要把数据库文件存储到SD卡中:

    第一步:确认模拟器存在SD卡,关于SD卡的两种创建方法见我的博文:【Android 2D游戏开发之十】

    第二步:(备注1)先创建SD卡目录和路径已经我们的数据库文件!这里不像上面默认路径中的那样,如果没有数据库会默认系统路径生成一个数据库和一个数据库文件!我们必须手动创建数据库文件!

    第三步:在进行删除数据、添加数据等操作的之前我们要得到数据库读写句柄得到一个数据库实例;(备注2)此时的创建也不是像系统默认创建,而是我们通过打开第一步创建好的文件得到数据库实例。这里仅仅是创建一个数据库!!!!

    第四步:在进行删除数据、添加数据等操作的之前我们还要创建一个表!

    第五步:在配置文件AndroidMainfest.xml 声明写入SD卡的权限,上一篇已经介绍权限了,不知道的自己去看下吧。

    有些童鞋不理解什么默认路径方式中就有表?那是因为我们在它默认给我们创建数据库的时候我们有创建表的操作,就是MySQLiteOpenHelper类中的onCreate()方法里的操作!所以我们如果要在进行删除数据、添加数据等操作的之前还要创建一个表,创建表的方法都是一样的。

    总结:不管哪种方式我们都要-创建数据库-创建表-然后进行操作!

    备注4:

    在Android中查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下:

    以下是方法和说明:

    move 以当前的位置为参考,将Cursor移动到指定的位置,成功返回true,失败返回false

    moveToPosition 将Cursor移动到指定的位置,成功返回true,失败返回false

    moveToNext 将Cursor向前移动一个位置,成功返回true,失败返回false

    moveToLast 将Cursor向后移动一个位置,成功返回true,失败返回 false。

    movetoFirst 将Cursor移动到第一行,成功返回true,失败返回false

    isBeforeFirst 返回Cursor是否指向第一项数据之前

    isAfterLast 返回Cursor是否指向最后一项数据之后

    isClosed 返回Cursor是否关闭

    isFirst 返回Cursor是否指向第一项数据

    isLast 返回Cursor是否指向最后一项数据

    isNull 返回指定位置的值是否为null

    getCount 返回总的数据项数

    getInt 返回当前行中指定的索引数据

    对于SQLite的很多童鞋有接触过,但是就不知道怎么存储在SD中,所以我也研究了下,这篇也写了把sd卡中的方式也提供给大家。

    OK 这元旦放假几天就光给大家写这个了,呵呵~凌晨2点了,咳咳~该睡觉了。(我一般凌成3点睡觉,早8点起来上班呵呵~习惯了~)

    (推荐大家订阅本博客,因为咱的更新速度可是很快的~娃哈哈)

    本篇源码:http://download.csdn.net/source/2959222

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 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="