今日重点内容是Adnroid的数据存储和访问。Android的数据存储有五种:文件

SharedPreferences、SQLite数据库、内容提供者(Content provider)、网络。今天老黎讲解Android的单元测试、文件存储和访问以及解析XML文件。

一、Android的单元测试

昨天进行的只是简单的开发,但从今天起的开发内容比较重要。所以首先应该学习Android的单元测试。在Android工程中添加单元测试的方法:

1.向androidManifest.xml加入:

<uses-library android:name="android.test.runner" />,它必须位于<application>元素体内。<application>的子元素。

<instrumentation android:name="android.test.InstrumentationTestRunner"

android:targetPackage="cn.itcast.action" android:label="Tests for My App" />

</application> <application>元素并列<application>元素的兄弟元素。这里的targetPackage必须是我们创建工程时指定的包名。

2.单元测试类

我们的单元测试类,必须继承自AndroidTestCase类。

3.单元测试方法

单元测试方法必须以test开头

4.方法抛出异常

方法要throws Throwable异常,ThrowableException的父类,单元测试框架捕获Throwable

5.调用测试

outline面板或方法名上右键,Run AS Android Junit Test

6.打印信息

android中不能使用System.out.println()打印信息,但我们可以使用Android为我们提供的Log类来打印信息。可以使用Log.i打开info信息、使用Log.e打印error信息、使用Log.d打印调试信息...

7.查看打印的信息

因为我们安装了ADT插件,所以选择菜单windows->Show View->Other...->Android->LogCat,打开 LogCat面板。在这个面板中我们可以看到Android输出的所有信息。

但我们只想查看我们自己输出的信息怎么办呢?面板的右上角有个+号,使用它可以创建一个过滤器。比如我们输入一个info信息调用Log.i(tag,”Hello Android!”),tag是信息的标签,一般使用类名。创建过滤器,将Filter Name和by Log Tag都设置为我的们的tag ,OK。它为我们创建了一个新的以tag名称的分页,在这个分页中我们可以查看过滤出来的信息。

LogCat面板中还有VDIWE五个选择按钮,从右向左依次包含。比如我们选择D,那么下面的面板将只显示DIW这三类信息。

二、Android的文件存储和访问

Android的文件读写与JavaSE的文件读写相同,都是使用IO流。而且Android使用的正是JavaSEIO流,下面我们通过一个练习来学习Android的文件读写。

1.创建一个Android工程

Project name:FileRW

BuildTarget:Android2.1

Application name:文件读写

Package name:com.changcheng.File

Create Activity:FileRW

Min SDK Version:7

2.编辑strings.xml文件内容:

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

<resources>

<string name="hello">Hello World, FileRW!</string>

<string name="app_name">文件读写</string>

<string name="file_name">文件名</string>

<string name="file_content">文件内容</string>

<string name="button_file_save">保存</string>

<string name="button_file_read">读取</string>

<string name="file_save_success">保存文件成功</string>

<string name="file_save_failed">保存文件失败</string>

<string name="file_read_failed">读取文件失败</string>

</resources>

3.编辑main.xml文件内容:

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

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

android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent">

<!-- 文件名 -->

<TextView android:layout_width="fill_parent"

android:layout_height="wrap_content" android:text="@string/file_name" />

<EditText android:layout_width="fill_parent"

android:layout_height="wrap_content" android:id="@+id/et_file_name" />

<!-- 文件内容 -->

<TextView android:layout_width="fill_parent"

android:layout_height="wrap_content" android:text="@string/file_content" />

<EditText android:layout_width="fill_parent"

android:layout_height="wrap_content" android:minLines="3"

android:id="@+id/et_file_content" />

<!-- 保存和读取按钮,采用相对布局 -->

<RelativeLayout android:layout_width="fill_parent"

android:layout_height="wrap_content">

<!-- 保存按钮 -->

<Button android:layout_width="wrap_content"

android:layout_height="wrap_content" android:text="@string/button_file_save"

android:id="@+id/bt_save" />

<!-- 读取按钮 -->

<Button android:layout_width="wrap_content"

android:layout_height="wrap_content" android:layout_toRightOf="@id/bt_save"

android:text="@string/button_file_read" android:id="@+id/bt_read" />

</RelativeLayout>

</LinearLayout>

4.添加java代码

Android建议采用MVC开发模式,所以我们在Android应用开发中最好使用MVC设计模式。MVC设计模式使三层分离,从而很好的解耦,何乐而不为。

首先我们向工程中添加一个FileService.java

package com.changcheng.file.service;

import java.io.ByteArrayOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import android.content.Context;

public class FileService {

Context context;

public FileService(Context context) {

this.context = context;

}

/**

* 保存文件

*

* @param fileName

* @param fileContent

* @throws Exception

*/

public void save(String fileName, String fileContent) throws Exception {

// Activity的父类的父类就是contextcontext与其他框架中的context相同为我们以供了一些核心操作工具。

FileOutputStream fileOutputStream = this.context.openFileOutput(

fileName, Context.MODE_PRIVATE);

fileOutputStream.write(fileContent.getBytes());

}

/**

* 读取文件

*

* @param fileName

* @return

* @throws Exception

*/

public String read(String fileName) throws Exception {

FileInputStream fileInputStream = this.context.openFileInput(fileName);

ByteArrayOutputStream byteArray = new ByteArrayOutputStream();

byte[] buffer = new byte[1024];

int len = 0;

while ((len = fileInputStream.read(buffer)) > 0) {

byteArray.write(buffer, 0, len);

};

return byteArray.toString();

}

}

文件读写的操作模式:

Context.MODE_PRIVATE:新内容覆盖原内容

Context.MODE_APPEND:新内容追加到原内容后

Context.MODE_WORLD_READABLE:允许其他应用程序读取

Context.MODE_WORLD_WRITEABLE:允许其他应用程序写入,会覆盖原数据。

可以使用+连接这些权限。

然后再向工程中添加FileButtonOnClickEvent.java

package com.changcheng.file.event;

import com.changcheng.file.R;

import com.changcheng.file.service.FileService;

import android.app.Activity;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.Toast;

/**

* 按钮事件类

* @author Administrator

*

*/

public class FileButtonOnClickEvent implements OnClickListener {

// 通过activity获取其他控件

private Activity activity;

// 通过FileService读写文件

private FileService fileService;

// 打印信息用的标签

private static final String TAG = "FileButtonOnClickEvent";

public FileButtonOnClickEvent(Activity activity) {

this.fileService = new FileService(activity);

this.activity = activity;

}

@Override

public void onClick(View v) {

Button button = (Button) v;

switch (button.getId()) {

case R.id.bt_save:

// 获取文件名

EditText etFileNameS = (EditText) this.activity

.findViewById(R.id.et_file_name);

String fileNameS = etFileNameS.getText().toString();

// 获取文件内容

EditText etFileConS = (EditText) this.activity

.findViewById(R.id.et_file_content);

String fileContentS = etFileConS.getText().toString();

// 保存

try {

this.fileService.save(fileNameS, fileContentS);

// 在窗口中显示一个特效信息框

Toast.makeText(this.activity, R.string.file_save_success,

Toast.LENGTH_LONG).show();

Log.i(TAG, "save file success!");

} catch (Exception e) {

Toast.makeText(this.activity, R.string.file_save_failed,

Toast.LENGTH_LONG).show();

Log.e(TAG, e.toString());

}

break;

case R.id.bt_read:

// 获取文件名

EditText etFileNameR = (EditText) this.activity

.findViewById(R.id.et_file_name);

String fileNameR = etFileNameR.getText().toString();

// 读取文件

try {

String fielContentR = this.fileService.read(fileNameR);

EditText etFileConR = (EditText) this.activity

.findViewById(R.id.et_file_content);

etFileConR.setText(fielContentR);

Log.i(TAG, "read file success!");

} catch (Exception e) {

Toast.makeText(this.activity, R.string.file_read_failed,

Toast.LENGTH_LONG).show();

Log.e(TAG, e.toString());

}

break;

default:

break;

}

}

}

最后编辑FileRW.java

package com.changcheng.file;

import com.changcheng.file.event.FileButtonOnClickEvent;

import android.app.Activity;

import android.os.Bundle;

import android.widget.Button;

public class FileRW extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

// 获取所有按钮

Button buttonRead = (Button) this.findViewById(R.id.bt_read);

Button buttonSave = (Button) this.findViewById(R.id.bt_save);

// 为按钮添加事件

FileButtonOnClickEvent fileBtOnClickEve = new FileButtonOnClickEvent(this);

buttonRead.setOnClickListener(fileBtOnClickEve);

buttonSave.setOnClickListener(fileBtOnClickEve);

}

}

我们的FileRW.java的可读性是否很好?当然!以后继续改进。但我们的FileService并未使用接口,在JavaEE都使用接口来开发,这样可以实现解耦。由于在Android是手机操作系统平台,如果我们开设的类比较多,会占用系统资源,从而导致系统变慢。所以,尽量的减少接口或类的定义,但也要尽量的做到程序的可读性要好。

在这里我就不演示使用Android的单元测试了,因为它十分容易。我们可以定义一个单元测试类专门用于测试FileService类,Android的测试单元将自动启动模拟器。

5.运行程序

启动模拟器,部署我们的程序。输入文件名和文件内容,点击保存。文件被保存在Android的什么位置?我们知道Android是基于Linux实现的。所以它的根目录是”/”,我们的文件被保存在”/data/data/com.changcheng.file/files”目录下。

我们也可以通过菜单Windows->Show View->Other...->Android->File Explorer,打开 File Explorer面板。通过它可以查看Android的目录结构:

data:应用数据,我们保存的文件在/data/data/packagename/files。

sdcard:现在的手机一般都可以外插一个SD卡,这个目录就是SDCard的目录。操作此目录时需要在主配置文件中注册操作权限。

systemAndroid操作系统的文件,我们不要修改。

我们可以点击 File Explorer右上角的软盘向左箭头图标,导出文件。

6.其他程序获取文件路径的方法

1.绝对路径:/data/data/packagename/files/filename;

2.context:context.getFilesDir()+”/filename”;

缓存目录:/data/data/packagename/CachegetCacheDir();

如果文件过大就不能存放在手机的文件目录,需要存储到SDCard上。

SDCard目录:/sdcard/Environment.getExternalStorageDirectory()

使用SDCard目录前,需要判断是否有sdcardEnvironment.getExternalStorageState()。操作此目录时需要在主配置文件中注册操作权限。

三、Android的解析XML文件

我们在学习JavaWEB基础时,老方有讲解使用JavaSE解析XML文件。我们在学习JavaEE时一般都使用dom4j解析XML文件。在Android中解析XMLJavaSEJavaEE都差不多,我们也可以在Andorid中使用dom4j,但这会占用系统的资源。

Andorid中解析XML有三种技术SAXDOMpull,重点是Saxpull。尤其是pullAndroid推荐使用,Android系统自身就是使用pull来解析的。pull的解析速度和资源的占用可以与sax相媲美,但使用上比sax更简单。

1.Sax解析XML

Sax是采用事件驱动的方式解析XML文件的,它是流式处理的。什么是流式的?就是从文档首开始流向文档尾,不可倒退。

我们需要编辑一个继承自DefaultHandler的类,因为DefaultHandler实现了ContentHandler接口。关于使用Sax解析XML文件的方式和代码,在此就不做总结了。

2.DOM解析XML

DOM解析XML在我之前的日志中有介绍,在此就不再总结了。

明天继续学习pull解析XML文件!

更多相关文章

  1. 通过修改hosts文件成功更新Android(安卓)sdk .
  2. Android(安卓)Gradle编译学习日记之二(使用 Gradle 编译 Eclipse,
  3. Android(安卓)make脚本简记
  4. MAC下编译arm架构的tcpdump
  5. Android中的Ninja简介
  6. Android(安卓)触控事件解析(Mastering the Android(安卓)Touch Sy
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. Android(安卓)透明状态栏
  2. 回弹效果listview
  3. Android图片预览效果,支持缩放、平移切换
  4. AsyncTask 和Timer同时使用
  5. 解析json格式数据
  6. python+appium+unittest+HtmlTestRunner
  7. FragmentActivity和Activity的区别及何时
  8. 简单实现android短信发送器
  9. Android数组显示
  10. Android:AsyncTask 模拟下载