Android个人每天总结.doc(day02 文件&数据库)

来源:互联网 发布:淘宝宝贝设置价格区间 编辑:程序博客网 时间:2024/06/03 16:44

作者:韩亚飞_yue31313_韩梦飞沙 QQ:313134555


day02 文件&数据库

Ø Android的试调与测试

一、debug试调

基本与web试调一致,定义断点,然后运行,只不过以前在网页配合,现在要在手机上配合

二、Junit测试Android

(一)手动配置

1.       在应用下定义一个继承AndroidTestCase类的测试类,且里面的所有测试方法以test小写开头

public class Testextends AndroidTestCase{

   public voidtestCha(){

      ContactService service=newContactService(getContext());

      List<ContactPhone>list=service.getContact();

      System.out.println(list);

       }

2.       在AndroidManifest.xml加上以下配置

 

<?xml version="1.0"encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="read.phone"

    android:versionCode="1"

    android:versionName="1.0">

 

    <uses-sdkandroid:minSdkVersion="10"/>

 

    <uses-permissionandroid:name="android.permission.READ_CONTACTS"/>

 

    <instrumentation

        android:name="android.test.InstrumentationTestRunner"

        android:targetPackage="read.phone" />

 

    <application

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name">

        <uses-libraryandroid:name="android.test.runner"/>

        <activity    ......

</application>

(二)自动配置

在建应用时选择需要测试方法,那么就会自动生成一个关联的测试应用.

(三)Android-Junit的测试原理

就是会生成一个测试的apk,发送到手机上去,然后创建要执行对象,运行要执行的方法,不般,不要activity界面

三、logcat日志的管理

 

system.err.println();异常打印用的是这个方法

       提示信息级别

       catch异常:就是黄警告没catch就是红

       log类V() d() i() w() e()可以指定输出日志

       logcat界面的管理

 

Ø 文件操作

 

一、写入文件到SD卡

需要在清单文件中注册权限

       <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2.1版本以下的SDCard位置和2.2之后版本不同

  可以通过Environment.getExternalStorageDirectory()获取当前SDCard位置,兼容所有版本

获取SDCard状态--判断SD卡是否存在

通过Environment.getExternalStorageState()方法获取SDCard当前状态

常量 Environment.MEDIA_MOUNTED 为已安装

代码如下:

//获取sd卡路径

public void save2sd(String name, Stringcontent) throws IOException {

Filefile=Environment.getExternalStorageDirectory();

//组合文件路径

File fileName=new File(file, name);

//定义流

FileOutputStream fos=newFileOutputStream(fileName);

//写入到sd卡

fos.write(content.getBytes());

fos.close();

二、写入文件到rom

获取输出流,----写入--权限管理

通过Context.openFileOutput(String name, int mode)可以获取一个文件输出流

name为文件名,mode为文件模式,有4种模式

输出流指向路径为:/data/data/包名/files/

文件模式在Context中有定义常量,可以相加

0 私有 1可读 2 可写 3可读可写

MODE_PRIVATE                              私有

MODE_WORLD_READABLE           其他程序可读(不可写)

MODE_WORLD_WRITEABLE          其他程序可写(不可读)

模式可以组合使用,例如:MODE_WORLD_READABLE+ MODE_WORLD_WRITEABLE

MODE_APPEND                              追加

代码如下:

FileOutputStream fos=context.openFileOutput(name,Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);

      fos.write(content.getBytes());

        fos.close();

三、读取ROM中的文件

获取输入流---获取路径---输出

通过Context.openFileInput(Stringname)可以获取一个文件输入流

该输入流可以读取/data/data/包名/files/ 路径下的文件

获取当前程序Files文件路径

ContextWrapper.getFilesDir()

四、用XmlPullParser解析读取xml

获取XmlPullParser对象---关联资源文件得到输入流---解析器关联输入流并定义编码--获得Eventype事件方式--通过pullnext得到事件代码与事件方式代码来标识解析

(一)Xml.newPullParser() 获得解析器
(二)xmlPull.getEventType()获取事件方式
(三)parser.setInput(in, "UTF-8") 设置输入流以及编码
(四)parser.next() 获取下一个解析事件,得到一个事件代码
(五)XmlPullParser中定义了常量来标识各种解析事件--与事件方式比对

START_DOCUMENT、END_DOCUMENT、START_TAG 、END_TAG、TEXT

(六)代码事例如下:将xml读入集合

publicList<Person> pullXml() throws IOException, Exception {

              // 建立集合

              List<Person> list = newArrayList<Person>();

 

              // 获取资源文件

              InputStream in =PullXml.class.getClassLoader().getResourceAsStream(

                            "persons.xml");

 

              // 建立资源文件输入流

              // 获取pull对象

              XmlPullParser xmlPull =Xml.newPullParser();

              // 关联输入流

              xmlPull.setInput(in,"utf-8");

              Person p = null;

              // 获取事件方式,是一个int 这个游标不从上往下不断行next,pull在解析到一个类型的标签时,

              // 得到的事件方式值是不一样的,这样就可以根据不同的事件方式值,去判断进行什么样的处理.

              // 通过type.next得到int值只要不是一个end_Document,则一直next下去

              for (int type =xmlPull.getEventType(); type != XmlPullParser.END_DOCUMENT; type = xmlPull

                            .next()) {

                     // 只要读到开始标签,不管大还是小.就判断开始获取里面需要属性和内容.

                     if (type == XmlPullParser.START_TAG){

                            // 如果标签名是person,则建立一个Person对象,并且设制一个id

                            if("person".equals(xmlPull.getName())) {

                                   p = newPerson();

                                   p.setId(xmlPull.getAttributeValue(0));//表示取这个标签的第几个属性

                                   // 如果是name就给标签设制一个name属性

                            } else if("name".equals(xmlPull.getName())) {

                                   p.setName(xmlPull.nextText());

                                   // 如果是age就给标签设制一个age属性

                            } else if("age".equals(xmlPull.getName())) {

                                    p.setAge(Integer.parseInt(xmlPull.nextText()));

                            }

                     }

                     // 如果读到结束标签,且是person那么加入到集合中

                     if (type == XmlPullParser.END_TAG){

                            if("person".equals(xmlPull.getName())) {

                                   list.add(p);

                                   p = null;

                            }

                     }

              }

              return list;

       }

五、XmlSerializer写文件到xml

得到应用file文件路径---再定义输出流关联文件---得到序列化xml工具--关联输出流与写义解码-

---写入---用序列化工具类以下方法写放:

startDocument

startTag

attribute

text

endTag

endDocument

 

String path = "/data/data/xml.demo/wr.xml";

      OutputStream out=new FileOutputStream(path);

              //获取xml序列化工具

      XmlSerializerxmlSer=Xml.newSerializer();

      xmlSer.setOutput(out, "UTF-8");

              //用工具写入:两个参数后面的true表示不引用外部xml

      xmlSer.startDocument("UTF-8", true);

//写放标标签,有属性就写属性,有文本就写文本

      xmlSer.startTag(null, "persons");

      for (Person p:pullXml()) {

        xmlSer.startTag(null, "person");

        xmlSer.attribute(null, "id", p.getId());

       

        xmlSer.startTag(null, "name");

        xmlSer.text(p.getName());

         xmlSer.endTag(null, "name");

 

       

        xmlSer.startTag(null, "age");

        xmlSer.text(p.getAge()+"");

        xmlSer.endTag(null, "age");

 

        xmlSer.endTag(null, "person");

      }

     

      xmlSer.endTag(null, "persons");

      xmlSer.endDocument();

     

   }

}

偏好设制:SharedPreferences--类似于数据回显

获取对象---用setString("属性名",属性值)保存数据---获得Editor对象--用edit.putString("key值",没保存数据时的默认值).

不一定是String 可以是基本类型,如getInt setInt之类

(一)获取对象

Context.getSharedPreferences(Stringname,int mode)

在/data/data/<package>/shared_pref/目录下创建一个以name命名的xml文件,mode文件为模式

(二)保存数据--获得editor对象写入保存数据

调用edit()方法可以获取一个Editor对象,对数据进行存储,存储之后需要调用commit()保存到文件

(三)读取偏好数据,放入需要的标签

获得SharedPreferences之后调用getString()、getInt()等方法获取其中设置的值

Ÿ   获取SharedPreferences对象的另一种方式,

(四)在Activity中获取SharedPreferences不指定文件名

在Activity中可以调用getPreferences(int mode)方法获得一个SharedPreferences,文件名和Activity名一致

 

(五)代码事例:

public class SharedActivityextends Activity {

   private EditText eT2;

   private EditText eT1;

   privateSharedPreferences sp;

   public void onCreate(BundlesavedInstanceState) {

      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);

      eT1 = (EditText)findViewById(R.id.editText1);

      eT2 = (EditText)findViewById(R.id.editText2);

      sp = getSharedPreferences("config",MODE_PRIVATE);

              //读出数据到EditText中

      eT1.setText(sp.getString("phone","10086"));

      eT2.setText(sp.getString("content","haha"));

   }

   public void save(View view) {

        String phone = eT1.getText().toString();

        String content = eT2.getText().toString();

                     //把数据保存入SharedPreferences

                     //用对象得到编辑器

        Editor editor = sp.edit();

        editor.putString("phone", phone);

        editor.putString("content", content);

        editor.commit();

Toast.makeText(getApplicationContext(),"保存成功", 0).show();

Ø 数据库(SQLite)

(一)是什么?

Android平台中嵌入了一个关系型数据库SQLite

(二)有什么用?

 

(三)怎么用?

1.    创建数据库及表及更新表

Android操作系统使用SQLite数据库,使用有两种方法获得数据库对象:

1.获取已经存在的数据库

SQLiteDatabasedb=SQLiteDatabase.openDatabase("/sdcard/zhycheng.db3",null,SQLiteDatabase.OPEN_READONLY); 

最后是一个flag标记.表示,打开后是只读,还是能读写等.

 

第一个String参数是数据库在文件系统中的位置,第二个参数一般为null,第三个参数控制数据库打开的方式。

这样就获得了数据库对象。

2.自己创建数据库

新建一个类,继承SQLiteOpenHelper,添加未实现的方法

代码如下: 

import android.content.Context; 

import android.database.sqlite.SQLiteDatabase; 

import android.database.sqlite.SQLiteDatabase.CursorFactory; 

import android.database.sqlite.SQLiteOpenHelper; 

 

public class MyHelper extends SQLiteOpenHelper{ 

 

    public MyHelper(Contextcontext, String name) 

    { 

       this(context,name,1); 

    } 

    public MyHelper(Contextcontext, String name,int version) 

    { 

       this(context,name,null,version); 

    } 

    public MyHelper(Contextcontext, String name,//数据库的名字 

            CursorFactoryfactory, 

            int version){ 

        super(context, name,factory, version); 

    } 

 

    @Override 

    public voidonCreate(SQLiteDatabase db) { 

       db.execSQL("create table user(id int,name text)"); 

         

    } 

 

    @Override 

    public voidonUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 

    } 

获得的数据库位于/data/data/yourpackage/databases/zhycheng.db3

然后通过生成一个MyHelper类的对象,调用

MyHelper mh=new MyHelper(this,"zhycheng"); 

SQLiteDatabasedb=mh.getReadableDatabase(); 

SQLiteDatabasedb=mh.getWritableDatabase(); 

分别获得只读和可写的数据库。

获得数据库之后就可以进行数据库操作有以下两种方式操作数据库

使用代码创建数据库--定义一个类--因为数据库在用户设备.

Ÿ   定义类继承SQLiteOpenHelper

Ÿ   声明构造函数,4个参数

       这个类继承一个SQLiteOpenHelper抽象类,这个类没有无参构造,只有四个有参的构造方法

       所以调用父类有参构造

       四个参数是:(Context context, String name,SQLiteDatabase.CursorFactory factory, int version)

       context:环境对象,通过这个确认哪个应用的数据库 --通过外部传入

       name:数据库文件的名字.可以直接写

       factory:游标工厂.Sursor(结果集) 可以用null表示用默认工厂

       version:数据库版本号:从1开始

       重写一个建立数据库方法onCreate和一个更新数据库方法onUpgrade()

       创建数据库类对象

       getWritableDatabase()

Ÿ   重写onCreate()方法

Ÿ   重写upGrade()方法

public class DBFactoryextendsSQLiteOpenHelper {

   publicDBFactory(Context context) {

① 通过构造方法创建数据库

      super(context, "telephone.db", null, 1);

              telephone.db表示数据库名称

   }

② 创建表的代码定义在onCreate()方法中,数据库创建时就会生成表

  

public void onCreate(SQLiteDatabasedb) {

      db.execSQL("create table person(_id Integer primary keyautoincrement,name varchar(100),phone Long)");

 

   }

③ 把更新数据库代码放在onUpgrage()方法中

通过更改版本来执行更新,版本号只能增加,不能减少,手动来写.

   public void onUpgrade(SQLiteDatabasedb,int oldVersion, int newVersion) {

在构造方法中,把版本号改大一点,这个方法就会执行

   //比如在这里给数据库中增加一张表什么的.....

   }

}

2.    CRUD操作

:sql语句通用格式:

sql语句格式:

       insertinto 表名(属性名1,属性名2,....) values(?,?,?...) ---插入到哪里

       deletefrom 表名 where 属性---从哪里删除属性是什么的一行数据

       update表名 set 属性1,属性2..where 属性---通过什么改哪个表的什么属性

       slecte属性名1,属性名2... from 表名 where 属性--根据什么属性从哪里查数据

注:insert into user values(7,datetime(CURRENT_TIMESTAMP,'localtime'))   这个sql语句表示:

插入即可时间:datetime(CURRENT_TIMESTAMP,'localtime')这个就是即刻时间.

Ÿ   和JDBC访问数据库不同,操作SQLite数据库无需加载驱动,不用获取连接,直接可以使用,

获取SQLiteDatabase对象之后通过该对象直接可以执行SQL语句

SQLiteDatabase.execSQL()

SQLiteDatabase.rawQuery()

getReadableDatabase()和getWritableDatabase()的区别

查看源代码后我们发现getReadableDatabase()在通常情况下返回的就是getWritableDatabase()拿到的数据库

只有在抛出异常的时候才会以只读方式打开

数据库对象缓存

getWritableDatabase()方法最后会使用一个成员变量记住这个数据库对象,下次打开时判断是否重用

SQLiteDatabase封装了insert()、delete()、update()、query()四个方法也可以对数据库进行操作

这些方法封装了部分SQL语句,通过参数进行拼接

两种CURD方法区别代码事例:

public class DBDao {

   DBFactory helper;

 

   publicDBDao(Context context) {

      super();

      this.helper =new DBFactory(context);

   }

//db.execSQL("INSERT INTO person(name, balance)VALUES(?,?)", new Object[] { p.getName(), p.getBalance() });

   public void insert(Person p){

      SQLiteDatabase db=helper.getWritableDatabase();

      ContentValues cv=new ContentValues();

      cv.put("name",p.getName());

      cv.put("phone",p.getPhone());

第二个参数是一个自动生成的行号,也就是说,cv等于空时,依然会插入一个只有id和行.

      db.insert("person", "_id", cv);

      db.close();

   }

   public void delete(Integer id){

      SQLiteDatabase db=helper.getWritableDatabase();

//db.execSQL("delete from person where _id=?", newObject[]{id});

      db.delete("person", "_id=?",new String[]{id+""});

      db.close();

   }

   public void update(Person p){

      SQLiteDatabase db=helper.getReadableDatabase();

//db.execSQL("update person set name=?,phone=? where_id=?", new Object[]{p.getName(),p.getPhone(),p.getId()});

      ContentValues cv=new ContentValues();

      cv.put("name",p.getName());

      cv.put("name",p.getName());

      db.update("person", cv, "_id=?", new String[]{p.getId()+""});

      db.close();

   }

   public Personquery(Integer id){

      SQLiteDatabase db=helper.getReadableDatabase();

//Cursor c=db.rawQuery("select name,phone from person where_id=?", new String[]{id+""});

      Cursor c=db.query("person", new String[]{"name","phone"},"_id=?", new String[]{id+""},null, null,null);

      Person p=null;

      if (c.moveToNext()) {

        p= new Person(id,c.getString(c.getColumnIndex("name")),c.getLong(c.getColumnIndex("phone")));

      }

     

      db.close();

      return p;

   }

   publicList<Person> queryAll(){

      List<Person>list=newArrayList<Person>();

      SQLiteDatabase db=helper.getReadableDatabase();

//Cursor c=db.rawQuery("select _id,name,phone fromperson", null);

      Cursor c=db.query("person", new String[]{"_id","name","phone"},null,null,null,null,null);

      while(c.moveToNext()){

        Person p=newPerson(c.getInt(c.getColumnIndex("_id")),c.getString(c.getColumnIndex("name")),c.getLong(c.getColumnIndex("phone")));

        list.add(p);

      }

      db.close();

      return list;

   } 

   public CursorqueryAllCursor(){

      SQLiteDatabase db=helper.getReadableDatabase();

      Cursor c=db.rawQuery("select _id,name,phone from person",null);

      //db.close();这里不能关,因为cursor在传递,还要用

      return c;

   }

   publicList<Person> queryPage(int page,int pageSize){

      int offset=(page-1)*pageSize;

      List<Person>list=newArrayList<Person>();

      SQLiteDatabase db=helper.getReadableDatabase();

Cursor c=db.query("person"

,new String[]{"_id","name","phone"}

,null,null,null,null,null

,offset+","+pageSize);

while(c.moveToNext()){

Person p=new Person(c.getInt(c.getColumnIndex("_id"))

,c.getString(c.getColumnIndex("name"))

,c.getLong(c.getColumnIndex("phone")));

        list.add(p);

      }

      db.close();

      return list;

   } 

 

}

3.    事务管理--数据库的方法

在sql操作之前开启事物--完成后设制事物成功--[-再sql操作,--再设置事物成功--]--最后结束事务

在使用SQLite数据库时可以用SQLiteDatabase类中定义的相关方法控制事务

① 开启事务:beginTransaction()
② 设置事务成功标记:setTransactionSuccessful()
③ 结束事务:endTransaction()

endTransaction()需要放在finally中执行,否则事务只有到超时的时候才自动结束,会降低数据库并发效率

注:是把最后一次成功点之前的事物提交.也就是前面可以有多个事务,只会把成功的事务提交.

在安卓中不是每个应用都需要有数据库,看需求.

(四)什么时候用?

SQLite是Android内置的,而一个应用具体要不要添加数据库,就看具体数据需求,看数据量大不大.

(五)有什么特点?

1.    SQLite的自动主键列都用_id这个属性名.约定的,外健约束是不能改的

不然的话,查询的时候要重命名.

2.   SQLite数据库中一旦创建不能修改

如果一定要修改,需要重新创建表,拷贝数据

比较小巧,方便 存储数据不区分类型.可以乱来.声名一个数据类型,可以存其它类型

一个库,就是一个文件,文件里有多张表

web的数据库在服务器上,用户通过访问服务器得到数据

sql语句与mysql基本一样.

通过java代码来实现创建数据库和表,这点与其它数据库不一样.,因为数据库在用户设备.

3.    其他数据库不同的是SQLite存储数据时不区分类型

但_id属性除外

例如一个字段声明为Integer类型,我们也可以将一个字符串存入,一个字段声明为布尔型,我们也可以存入浮点数。

除非是主键被定义为Integer,这时只能存储64位整数

4.    创建数据库的表时可以不指定数据类型

,例如:

CREATE TABLE person(id INTEGER PRIMARY KEYAUTOINCREMENT, name VARCHAR(20))

CREATE TABLE person(id INTEGER PRIMARY KEYAUTOINCREMENT, name)

SQLite语句特点

支持大部分标准SQL语句,增删改查语句都是通用的,分页查询语句和MySQL相同

SELECT * FROM person LIMIT 20 OFFSET 10

SELECT * FROM person LIMIT 10,20

 

5.   数据库的创建与更新特点

       数据库不存在,就会执行创建数据库方法

       数据库存在,且版本没有变化,则直接打开

       版本变化,则执行onUpgrade方法更新数据库


0 0
原创粉丝点击