您的位置:首页 > 移动开发 > Android开发

Android基础——02数据存储和界面展现

2015-10-09 19:50 603 查看

测试介绍

好的软件不是写出来, 测出来的.

1、根据测试的时候 是否有源代码:

白盒测试: 写测试代码 测试源代码里面的业务方法

黑盒测试: 不知道源代码, 测试应用程序的业务逻辑.

2、根据测试的粒度

方法测试 function test

单元测试 unit test junit测试框架

集成测试 integration test

系统测试 system test

3、根据测试的暴力程度

冒烟测试 smoke test

压力测试 pressure test

android中的压力测试:

–>adb shell

–>monkey 5000

单元测试

【1】定义一个类继承AndroidTestCase

【2】在清单文件配置uses-library和instrumentation





在没有笔记的情况下,该怎么配置清单信息呢?

自己手动创建一个Android的测试工程,在测试工程里面会自动配置好

单元测试的步骤是:

先创建一个类,里面有个计算和的方法

package com.itheima.unit;

public class Calc {

/**
* 定义一个计算器相机的方法
*/

public int add(int x,int y){
return x + y;
}

}


然后再定义一个类,继承AndroidTestCase,里面写上要测试的方法和数据,并写明断言,如果断言正确,则说明单元测试显示正确结果,否则显示错误结果

package com.itheima.unit;

import android.test.AndroidTestCase;

public class CalcTest extends AndroidTestCase {

//写测试方法
public void testAdd(){

Calc calc = new Calc();
int result = calc.add(5, 3);
//断言
assertEquals(8, result);

}

}


在清单文件中这样配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itheima.unit"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<!--配置要测试的包名-->
<instrumentation

android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.itheima.unit" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >

<!-- 配置函数库 -->

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

<activity
android:name="com.itheima.unit.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>






出此案绿色的条就说明单元测试成功了

日志猫的使用

通常通过打Log的方式,日志信息会打印在日志猫上,以此来查看程序的错误

package com.itheima.logcat;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {

private static final String tag = "MainActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Log.v(tag, "我是v级别");
Log.i(tag, "我是info级别");
Log.d(tag, "我是debug级别");
Log.w(tag, "我是warn级别");
Log.e(tag, "我是error级别");
System.out.println("哈哈哈哈");

}

}


verbose是黑色的

debug是蓝色的

info是绿色的

warn是黄色的

error是红色的

system.out是绿色的

Login登陆案例

【1】画UI



实现以上UI的代码是:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名" />

<EditText
android:id="@+id/et_userpassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:password="true"
android:hint="请输入密码" />

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
>

<CheckBox
android:id="@+id/cb_ischeck"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住用户名密码" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="login"
android:layout_alignParentRight="true"
android:text="登录" />
</RelativeLayout>

</LinearLayout>


【2】写业务逻辑:

想要实现的需求是在写上用户名密码之后,当勾选记住用户名密码的时候,点击登录,就会把用户输入的用户名密码写入到手机的内存中,

而且在下一次启动的时候,会先读取内存中的用户的信息,然后将内存中的信息显示到屏幕上

package com.itheima.login;

import java.util.Map;

import android.os.Bundle;
import android.app.Activity;
import android.text.TextUtils;
import android.view.Menu;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

private EditText et_name;
private EditText et_userpassword;
private CheckBox cb_ischeck;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//[1]找到我们关心的控件

et_name = (EditText) findViewById(R.id.et_username);
et_userpassword = (EditText) findViewById(R.id.et_userpassword);
cb_ischeck = (CheckBox) findViewById(R.id.cb_ischeck);

//[1.1]读取 data/data 下  info.txt信息
Map<String, String> maps = UserInfoUtils.readInfo();
if (maps!=null) {
//把name 和 pwd 取出来
String name = maps.get("name");
String pwd = maps.get("pwd");
//[1.2]把name 和pwd 显示到editText控件上

et_name.setText(name);
et_userpassword.setText(pwd);

}

}

//[2]写按钮的点击事件
public void login(View v){

//[2.1]获取用户名和密码
String name = et_name.getText().toString().trim();
String pwd = et_userpassword.getText().toString().trim();
//[2.2]判断name 和  pwd 是否为空
if (TextUtils.isEmpty(name)||TextUtils.isEmpty(pwd)) {

Toast.makeText(MainActivity.this, "用户名或密码不能为空", 1).show();

}else {
//[2.3]进行登录的逻辑
System.out.println("连接服务器  进行登录 等我们讲到 第四天 网络 编程 在说");

if (cb_ischeck.isChecked()) {
//[2.4]把用户名和密码的数据给我存起来
boolean result = UserInfoUtils.saveInfo(name, pwd);
if (result) {
Toast.makeText(MainActivity.this, "保存成功", 1).show();

}else{
Toast.makeText(MainActivity.this, "保存失败", 1).show();
}

}else {
Toast.makeText(MainActivity.this, "请勾选cb", 1).show();

}

}

}

}


中间需要有一个把用户名和密码写入到内存中的操作,我们单独给他封装成一个工具类,然后直接使用工具类的方法来进行写入操作,代码如下:

package com.itheima.login;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;

public class UserInfoUtils {

// 保存用户名和密码的业务方法
public static boolean saveInfo(String username, String pwd) {

try {

String result = username + "##" + pwd;
// [1]创建file类指定我们要把数据存储的位置
File file = new File("/data/data/com.itheima.login/info.txt");

// [2]创建一个文件输出流
FileOutputStream fos = new FileOutputStream(file);

fos.write(result.getBytes());
fos.close();
return true;

} catch (Exception e) {
e.printStackTrace();
return false;
}

}

// 读取用户的信息
public static Map<String, String> readInfo() {
// [1]定义map
try {
Map<String, String> maps = new HashMap<String, String>();
File file = new File("/data/data/com.itheima.login/info.txt");
FileInputStream fis = new FileInputStream(file);
BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
String content = bufr.readLine(); // 读取数据

// 切割字符串 封装到map集合中

String[] splits = content.split("##");
String name = splits[0];
String pwd = splits[1];
// 把name 和 pwd 放入map中
maps.put("name", name);
maps.put("pwd", pwd);
fis.close();
return maps;

} catch (Exception e) {
e.printStackTrace();
return null;
}

}

}


使用上下文获取到文件目录

在上边的例子中如果写一个要保存的文件的路径会非常的麻烦,

/data/data/com.itheima.login/info.txt

如果使用上下文的话就会非常的省事

context.getFileDir.getPath();

这样就获取到了本工程所在的目录/data/data/com.itheima.login,还会在包下自己创建一个文件夹/data/data/com.itheima.login/files,比硬编码方便的多。

使用上下文还可以直接获取到本工程的输出流,

上边的例子用上下文获取到输出流的方式来进行实现的话,就会很方便:

package com.itheima.login;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;

public class UserInfoUtils {

// 保存用户名和密码的业务方法
public static boolean saveInfo(Context context,String username, String pwd) {

try {

String result = username + "##" + pwd;

// [3]通过上下文获取FileOutputStream
FileOutputStream fos = context.openFileOutput("infoo.txt", 0);
fos.write(result.getBytes());
fos.close();
return true;

} catch (Exception e) {
e.printStackTrace();
return false;
}

}

// 读取用户的信息
public static Map<String, String> readInfo(Context context) {
// [1]定义map
try {
Map<String, String> maps = new HashMap<String, String>();

FileInputStream fis = context.openFileInput("infoo.txt");
BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
String content = bufr.readLine(); // 读取数据

// 切割字符串 封装到map集合中

String[] splits = content.split("##");
String name = splits[0];
String pwd = splits[1];
// 把name 和 pwd 放入map中
maps.put("name", name);
maps.put("pwd", pwd);
fis.close();
return maps;

} catch (Exception e) {
e.printStackTrace();
return null;
}

}

}


把数据保存到sd卡中

【1】第一种方法:就是直接把路径写死了,

“/mnt/sdcard/info.txt”

这里需要注意的是往sd卡中写数据的时候,需要先给用户一个权限,



这样才能把数据写入到sd卡上

【2】第二种方法:使用Environment对象获取到sd卡的目录:



使用这样的一个类不仅可以直接拿到sd卡的目录,还可以获取到sd卡的状态(是挂载的还是卸载的)使代码更具有健壮性

代码如下:

package com.itheima.login;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.os.Environment;

public class UserInfoUtils {

// 保存用户名和密码的业务方法
public static boolean saveInfo(String username, String pwd) {

try {

String result = username + "##" + pwd;
// [1]创建file类指定我们要把数据存储的位置  把数据保存到sd卡

String sdPath = Environment.getExternalStorageDirectory().getPath();

File file = new File(sdPath,"haha.txt");

// [2]创建一个文件输出流
FileOutputStream fos = new FileOutputStream(file);

fos.write(result.getBytes());
fos.close();
return true;

} catch (Exception e) {
e.printStackTrace();
return false;
}

}

// 读取用户的信息
public static Map<String, String> readInfo() {
// [1]定义map
try {
Map<String, String> maps = new HashMap<String, String>();
String sdPath = Environment.getExternalStorageDirectory().getPath();
File file = new File(sdPath,"haha.txt");
FileInputStream fis = new FileInputStream(file);
BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
String content = bufr.readLine(); // 读取数据

// 切割字符串 封装到map集合中

String[] splits = content.split("##");
String name = splits[0];
String pwd = splits[1];
// 把name 和 pwd 放入map中
maps.put("name", name);
maps.put("pwd", pwd);
fis.close();
return maps;

} catch (Exception e) {
e.printStackTrace();
return null;
}

}

}


获取sd卡的可用空间

先要将sd卡获取到的目录封装成一个file对象,然后file对象里面有获取最大值和可用值的方法,返回的是是个long类型的单位为字节的大小

然后使格式化的类Formatter里面的formatFileSize方法来讲byte单位的大小转换为正常格式的字符串,

将获取到的正常格式的sd卡的大小显示在手机屏幕上

代码如下:

package com.itheima.getsdcarddata;

import java.io.File;

import android.os.Bundle;
import android.os.Environment;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.text.format.Formatter;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]找到我们关心的控件
TextView tv_total_size = (TextView) findViewById(R.id.textView1);
TextView tv_useable_size = (TextView) findViewById(R.id.textView2);

//[2]获取sd卡总大小 和可用空间

File file = Environment.getExternalStorageDirectory();
long totalSpace = file.getTotalSpace(); //总大小
long usableSpace = file.getUsableSpace(); //可用空间

//[3]转换数据格式
String formatToatalSpace = Formatter.formatFileSize(this, totalSpace);
String formatusableSpace = Formatter.formatFileSize(this,usableSpace);

//[4]展示到textview上
tv_total_size.setText("总大小:"+formatToatalSpace);
tv_useable_size.setText("可用的:"+formatusableSpace);

}

}


文件权限的介绍

文件的权限有四种:

私有:private

可追加的:append

可读的:read

可写的write

创建四种权限模式的文件

先创建四个按钮,按钮上绑定事件生成各自对应的文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click1"
android:text="private" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click2"
android:text="append" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click3"
android:text="read" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click4"
android:text="write" />

</LinearLayout>


开始写生成文件的业务逻辑:

package com.itheima.pri;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

//点击按钮 生成一个私有的文件
public void click1(View v){

try {
FileOutputStream fos = openFileOutput("private.txt", MODE_PRIVATE);
//          fos.write("private".getBytes());
fos.write("haha".getBytes());

fos.close();
} catch (Exception e) {
e.printStackTrace();
}

}

//点击按钮   使用MODE_APPEND模式 生成一个append.txt文件
public void click2(View v){
try {
FileOutputStream fos = openFileOutput("append.txt", MODE_APPEND);
//              fos.write("append".getBytes());
fos.write("hehe".getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}

}

//点击按钮   使用MODE_WORLD_READABLE 模式  生成一个read.txt 文件
public void click3(View v){
try {
FileOutputStream fos = openFileOutput("read.txt", MODE_WORLD_READABLE);
fos.write("read".getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}

}

//点击按钮  使用这个模式MODE_WORLD_WRITEABLE  生成一个write.txt文件
public void click4(View v){
try {
FileOutputStream fos = openFileOutput("write.txt", MODE_WORLD_WRITEABLE);
fos.write("write".getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}

}

}


生成的文件如下图所示:



解释一下后边的rw-的意思:只用一张图来说



想要使用读取到之前创建好的文件的内容呢?

新创建一个工程,创建读取流,读取目标文件下的文件:

package com.itheima.readfile;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

try {
File file = new File("/data/data/com.itheima.pri/files/write.txt");
FileInputStream fis = new  FileInputStream(file);
BufferedReader bufr = new BufferedReader(new InputStreamReader(fis));
String content = bufr.readLine();

System.out.println("content:"+content);

} catch (Exception e) {
e.printStackTrace();
}

}

}


这里记住,只有可读权限的文件可以被读取到,其他类型的文件因为权限不够,所以读取不到。

修改已经存在的文件的权限:

进入到文件所在的目录:



找到对应的包找到对应的文件夹:



开始修改文件的权限:



这样文件权限就修改成功了,777表示三个阶段的文件权限都给了所有的权限,有权限就用1表示,没权限就用0表示,以此来算下的二进制码来表示的

SharedPreference介绍

在之前的存储用户信息的过程中,一直使用的是流来进行操作的,在Android中完全可以不用流来进行操作,就是使用SharedPreference来操作:



步骤是:根据上下文获取到SharedPreference对象,然后使用sp调用edit方法获取到Editor对象,使用Editer对象进行put操作,最后进行commit提交数据。

在获取数据的时候同样是得到sp对象,然后直接调用get方法获取到数据

代码示例:

package com.itheima.login;

import java.util.Map;

import android.os.Bundle;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.text.TextUtils;
import android.view.Menu;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import com.itheima.sptest.R;

public class MainActivity extends Activity {

private EditText et_name;
private EditText et_userpassword;
private CheckBox cb_ischeck;
private SharedPreferences sp;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//[0] 先初始化 sp 的实例
/**
* name  会帮助我们生成一个xml文件
* mode 模式
*/
sp = getSharedPreferences("config", 0);

//[1]找到我们关心的控件

et_name = (EditText) findViewById(R.id.et_username);
et_userpassword = (EditText) findViewById(R.id.et_userpassword);
cb_ischeck = (CheckBox) findViewById(R.id.cb_ischeck);

//[2]在 config.xml文件中把我们关心的数据取出来 然后显示到edittext控件上
String name = sp.getString("name", "");
String pwd = sp.getString("pwd", "");

//[3]把name 和 pwd 设置到edittext上
et_name.setText(name);
et_userpassword.setText(pwd);

//TODO  把checkbox状态逻辑给我写好
}

//[2]写按钮的点击事件
public void login(View v){

//[2.1]获取用户名和密码
String name = et_name.getText().toString().trim();
String pwd = et_userpassword.getText().toString().trim();
//[2.2]判断name 和  pwd 是否为空
if (TextUtils.isEmpty(name)||TextUtils.isEmpty(pwd)) {

Toast.makeText(MainActivity.this, "用户名或密码不能为空", 1).show();

}else {
//[2.3]进行登录的逻辑
System.out.println("连接服务器  进行登录 等我们讲到 第四天 网络 编程 在说");

if (cb_ischeck.isChecked()) {

//2.4  使用SharedPreferences 去保存数据   拿到sp的实例

//[2.5]获取sp的编辑器
Editor edit = sp.edit();
edit.putString("name", name);
edit.putString("pwd", pwd);

//[2.6]记得把edit 进行提交
edit.commit();

}else {
Toast.makeText(MainActivity.this, "请勾选cb", 1).show();

}

}

}

}


生成xml文件的第一种方式

就是传统的方式:通过sb组拼字符串的方式慢慢的写成一个xml文件的格式

将数据封装成对象,存进集合当中,在组拼字符串的时候直接遍历集合取出对象,然后取出对象里面的数据就好了

代码示例

先来一个数据封装成的对象:

package com.itheima.generatexml;

public class Sms {

private String address;

private String body;

private String date;

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public String getBody() {
return body;
}

public void setBody(String body) {
this.body = body;
}

public String getDate() {
return date;
}

public void setDate(String date) {
this.date = date;
}

}


开始组拼xml文档的字符串:

package com.itheima.generatexml;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

private List<Sms> smsLists;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//[1]初始化我们要备份的数据

smsLists = new ArrayList<Sms>();

for (int i = 0; i < 10; i++) {
Sms sms =new Sms();
sms.setAddress("10008"+i);
sms.setBody("nihao"+i);
sms.setDate("201"+i);
//[2]把sms对象加入到 集合中
smsLists.add(sms);

}

}

//点击按钮  通过StringBuffer 的方式生成一个xml文件
public void click(View v){

//[1]创建sb对象
StringBuffer sb = new StringBuffer();

//[2]开始组拼xml文件头
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
//[3]开始组拼xml根节点
sb.append("<smss>");
//[4]开始组拼sms节点
for (Sms sms : smsLists) {
sb.append("<sms>");

//[5]开始组拼address节点
sb.append("<address>");
sb.append(sms.getAddress());
sb.append("</address>");

//[6]开始组拼body节点
sb.append("<body>");
sb.append(sms.getBody());
sb.append("</body>");

//[7]开始组拼date节点
sb.append("<date>");
sb.append(sms.getDate());
sb.append("</date>");

sb.append("</sms>");
}

sb.append("</smss>");

//[8]把数据保存到sd卡中
try {
File file = new File(Environment.getExternalStorageDirectory().getPath(),"smsbackup.xml");
FileOutputStream fos = new FileOutputStream(file);
fos.write(sb.toString().getBytes());
fos.close();//关闭流

} catch (Exception e) {
e.printStackTrace();
}

}

}


最后记住,因为在代码中要将数据写入到sd卡中,所以需要给一个权限:

这样一个xml文件就形成了。

生成xml文件的第二种方式

使用XmlSerializer类里面的方法进行操作

首先获取XmlSerializer对象,使用Xml.newSerializer()方法生成对象

设置序列化参数:setOutput()

设置文档开头startDocument()

设置开始标签startTag();

设置结束节点endTag();

设置节点中的文字text();

结束文档endDocument();

代码示例:

数据还是那个数据,集合还是那个集合

package com.itheima.generatexml;

public class Sms {

private String address;

private String body;

private String date;

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public String getBody() {
return body;
}

public void setBody(String body) {
this.body = body;
}

public String getDate() {
return date;
}

public void setDate(String date) {
this.date = date;
}

}


开始生成xml文件

package com.itheima.generatexml;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlSerializer;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.util.Xml;
import android.view.Menu;
import android.view.View;
import com.itheima.generatexml2.R;

public class MainActivity extends Activity {

private List<Sms> smsLists;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//[1]初始化我们要备份的数据

smsLists = new ArrayList<Sms>();

for (int i = 0; i < 10; i++) {
Sms sms =new Sms();
sms.setAddress("10008"+i);
sms.setBody("nihao"+i);
sms.setDate("201"+i);
//[2]把sms对象加入到 集合中
smsLists.add(sms);

}

}

//点击按钮  通过的XmlSerializer方式生成一个xml文件
public void click(View v){
try {
//[1]获取XmlSerializer 类的实例  通过Xml这个工具类去获取
XmlSerializer serializer = Xml.newSerializer();
//[2]设置 xmlserializer序列化器参数
File file  = new File(Environment.getExternalStorageDirectory().getPath(),"smsbackup2.xml");
FileOutputStream fos = new FileOutputStream(file);
serializer.setOutput(fos, "utf-8");
//[3]开始写xml文档开头
serializer.startDocument("utf-8", true);
//[4]写 xml的根节点  namespace 命名空间
serializer.startTag(null, "smss");

//[5]循环写 sms节点
for (Sms sms : smsLists) {
serializer.startTag(null, "sms");

// [6]开始address节点
serializer.startTag(null, "address");
serializer.text(sms.getAddress());
serializer.endTag(null,"address");

// [7]开始body节点
serializer.startTag(null, "body");
serializer.text(sms.getBody());
serializer.endTag(null,"body");

// [8]开始date节点
serializer.startTag(null, "date");
serializer.text(sms.getDate());
serializer.endTag(null,"date");

//sms节点结束
serializer.endTag(null, "sms");

}

serializer.endTag(null, "smss");

//写文档结尾
serializer.endDocument();
fos.close();//关闭流

} catch (Exception e) {
e.printStackTrace();
}

}

}


因为数据是写入到sd卡中的,所以要在清单文件中给一个权限

对xml文件进行解析

就是通过XmlPullParser工具类来进行解析的

这个类的来源也是通过Xml类获取到的

获取到parser对象之后,通过setInput方法来设置要读取的xml文件和要使用的编码方式

解析xml文件的时候是按照指针的方式一行一行的往下读取的,针对每一行都有自己对应的事件

获取这样的事件的方法就是getEventType

指针一行一行的往下走是要依赖一个next方法的。

然后开始通过判断获取到的事件对象(int值)来判断指针指到的节点是开始节点开始结束节点,还可以获取到所在节点的名称和内容,还有属性

详情见代码

获取资产目录里面的文件可以使用上下文对象,getAsses().open(“资产目录中的文件名”)返回的是一个流对象

代码:

想要将xml文件中的内容显示到一个textView中,画UI

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:id="@+id/tv_weather"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />

</RelativeLayout>


创建bean

package com.itheima.xmpparser;

public class Channel {

private String id;
private String city;
private String temp;
private String wind;
private String pm250;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getWind() {
return wind;
}
public void setWind(String wind) {
this.wind = wind;
}
public String getPm250() {
return pm250;
}
public void setPm250(String pm250) {
this.pm250 = pm250;
}
@Override
public String toString() {
return "Channel [id=" + id + ", city=" + city + ", temp=" + temp
+ ", wind=" + wind + ", pm250=" + pm250 + "]";
}

}


创建解析xml文件的工具类:

package com.itheima.xmpparser;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;

import android.util.Xml;

public class WeatherParser {

/**
* 服务器是以流的形式把数据返回的
* @return
*/
public static List<Channel> parserXml(InputStream in) throws Exception{

//[0]声明集合对象
List<Channel> weatherLists = null;
Channel  channel = null;
//[1]获取XmlPullParser 解析的实例
XmlPullParser parser = Xml.newPullParser();

//[2]设置XmlPullParser 的参数
parser.setInput(in, "utf-8");

//[3]获取事件类型
int type = parser.getEventType();
while(type!= XmlPullParser.END_DOCUMENT){

switch (type) {
case XmlPullParser.START_TAG:   //解析开始标签
//[4]具体判断一下 解析到是哪个开始标志
if ("weather".equals(parser.getName())) {
//[5]创建一个集合对象
weatherLists = new ArrayList<Channel>();

}else if("channel".equals(parser.getName())){
//[6]创建Channel对象
channel = new Channel();
//[7]获取id值
String id = parser.getAttributeValue(0);
channel.setId(id);

}else if("city".equals(parser.getName())){
//[8]获取city的数据
String city = parser.nextText();
channel.setCity(city);

}else if("temp".equals(parser.getName())){
//[8]获取city的数据
String temp = parser.nextText();
channel.setTemp(temp);

}else if("wind".equals(parser.getName())){
//[8]获取city的数据
String wind = parser.nextText();
channel.setWind(wind);

}else if("pm250".equals(parser.getName())){
//[8]获取city的数据
String pm250 = parser.nextText();
channel.setPm250(pm250);
}

break;

case XmlPullParser.END_TAG:     //解析结束标志
//判断要解析的结束标签
if ("channel".equals(parser.getName())) {
//把javabean对象存到集合中
weatherLists.add(channel);

}

break;
}

//不停的向下解析
type = parser.next();

}

return weatherLists;

}

}


在主函数中解析xml文件

package com.itheima.xmpparser;

import java.io.InputStream;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

try {
//[1]显示天气信息
TextView tv_weather = (TextView) findViewById(R.id.tv_weather);
//[1.1]获取资产的管理者 通过上下文

InputStream inputStream = getAssets().open("weather.xml");

//[2]调用我们定义的解析xml业务方法
List<Channel> weatherlists = WeatherParser.parserXml(inputStream);

StringBuffer sb = new StringBuffer();
for (Channel channel : weatherlists) {
sb.append(channel.toString());
}

//[3]把数据展示到textviwe上
tv_weather.setText(sb.toString());

} catch (Exception e) {
e.printStackTrace();
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: