今天谈两点:sharedPreference,xml文件序列化和反序列
一,sharedPreference:
SharedPreferences是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息。其存储位置在/data/data/<包名>/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。实现SharedPreferences存储的步骤如下:
1、根据Context获取SharedPreferences对象:
SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
2、利用edit()方法获取Editor对象:
Editor editor = sp.edit();
3、通过Editor对象存储key-value键值对数据:
editor.putString("用户名", name);
editor.putString("密码", password);
插入数据:
调用Editor.putxxxx方法,两个参数分别为键和值。
获取数据:
调用Editor.getxxxx方法,两个参数分别为键和不存在指定键时的默认值。
删除数据:
调用Editor.remove方法,参数为指定的键。
清空所有数据:
调用Editor.clear方法
4、通过commit()方法提交数据:
editor.commit();
例如一下的代码:
MainActivity
package com.example.login;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import com.example.SharedPreference.R;
import com.example.login.service.LoginService;
public class MainActivity extends Activity {
private static final String tag = "MainActivity";
private EditText et_name;
private EditText et_password;
private CheckBox RemenberPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化
et_name = (EditText) findViewById(R.id.et_name);
et_password = (EditText) findViewById(R.id.et_password);
RemenberPassword = (CheckBox) findViewById(R.id.cb_remenberpawd);
/*
* 信息回显
*/
// 获取SharedPreferences对象
SharedPreferences sp = getSharedPreferences("config", Context.MODE_PRIVATE);
String name = sp.getString("用户名", "");
String password = sp.getString("密码", "");
et_name.setText(name);
et_password.setText(password);
}
/**
* 登录
*/
public void login(View view) {
String name = et_name.getText().toString().trim();
String password = et_password.getText().toString();
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) {
Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
} else {
// 判断是否保存用户名密码
if (RemenberPassword.isChecked()) {
// 保存密码
Log.i(tag, "需要保存的用户名和密码。");
LoginService.saveUserInfo(this, name, password);
Toast.makeText(this, "保存用户信息成功", Toast.LENGTH_SHORT).show();
}
// 登录,发送消息到服务器,服务器验证正确性
if ("123".equals(name) && "4038".equals(password)) {
Toast.makeText(this, "登录成功", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "登录失败", Toast.LENGTH_LONG).show();
}
}
}
}
LoginService.java
package com.example.login.service;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
/**
* 保存用户名和密码的业务方法
* @author Administrator
*/
public class LoginService {
public static void saveUserInfo(Context context, String name, String password) {
// 获取SharedPreferences对象
SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
// 获取Editor对象
Editor editor = sp.edit();
editor.putString("用户名", name);
editor.putString("密码", password);
// 提交:类似于数据库的事务,保证数据同时提交成功
editor.commit();
}
}
文件会 shared_prefs目录下生成:
文件会以键值对的方式存储:
二,xml文件序列化和反序列
1、XML文件序列化:
这里我们引用短信备份的案例,即将短信备份成XML文件输出到内存卡上保存起来。
XML文件序列化有两种方式,以下代码都写出来了,按照如图的格式输出XML文本:
代码如下:
package com.example.WriteXML;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Xml;
import android.view.View;
import android.widget.Toast;
import com.example.WriteXML.domain.smsInfo;
public class MainActivity extends Activity {
private List<smsInfo> smsInfos;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
smsInfos = new ArrayList<smsInfo>();
Random random = new Random();
long number = 1350000001;
// 创建10条短信
for (int i = 0; i < 10; i++) {
smsInfos.add(new smsInfo(System.currentTimeMillis(), random
.nextInt(2) + 1, "短信内容" + i, Long.toString(number + i), i));
}
}
// 短信的备份方式1
public void BackSMS1(View view) {
// 假设我已经获得了所有的短信
StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
sb.append("<smss>");
for (smsInfo info : smsInfos) {
sb.append("<date>");
sb.append(info.getDate());
sb.append("</date>");
sb.append("<type>");
sb.append(info.getType());
sb.append("</type>");
sb.append("<body>");
sb.append(info.getBody());
sb.append("</v>");
sb.append("<address>");
sb.append(info.getAddress());
sb.append("</address>");
}
sb.append("</smss>");
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
try {
File file = new File(Environment.getExternalStorageDirectory(),
"BackSMS.xml");
FileOutputStream fos = new FileOutputStream(file);
fos.write(sb.toString().getBytes());
fos.close();
Toast.makeText(this, "短信备份成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "短信备份失败", 0).show();
}
} else {
Toast.makeText(this, "SD卡未挂载", 0).show();
}
}
/**
* private long date; private int type; private String body; private String
* address;
*
* @param view
*/
// 短信备份方式2
public void BackSMS2(View view) {
XmlSerializer serializer = Xml.newSerializer();// 创建一个序列器
try {
File file = new File(Environment.getExternalStorageDirectory(),"BackSMS2.xml");
FileOutputStream fos = new FileOutputStream(file);
//初始化序列号器,指定xml数据写入到哪个文件,并指定文件的编码方式
serializer.setOutput(fos, "utf-8");
serializer.startDocument("utf-8", true);
serializer.startTag(null, "smss");
for (smsInfo info : smsInfos) {
serializer.startTag(null, "sms");
serializer.attribute(null, "id", info.getId()+"");
serializer.startTag(null, "date");
serializer.text(info.getDate()+"");
serializer.endTag(null, "date");
serializer.startTag(null, "type");
serializer.text(info.getType()+"");
serializer.endTag(null, "type");
serializer.startTag(null, "body");
serializer.text(info.getBody());
serializer.endTag(null, "body");
serializer.startTag(null, "address");
serializer.text(info.getAddress());
serializer.endTag(null, "address");
serializer.endTag(null, "sms");
}
serializer.endTag(null, "smss");
serializer.endDocument();
fos.close();
Toast.makeText(this, "短信备份成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "短信备份失败", 0).show();
}
}
}
在这里,假设使用第一种方式,就会出现一些意外情况,比如,在短信内容里面多一个“<”符号,备份时会出错:
结果:
所以,我们通常用方式二。
2、XML文件反序列化(XML文件解析)
这里我们引用天气显示的案例,一般提供的天气API都是XML文件,我们需要把XML文件解析出来,然后显示在app上。
首先,我们先模仿制作一个包涵天气资讯的XML文件:
然后我们定义一个getWeatherInfos的方法,采用pull解析器来解析xml文件,实现解析的业务:
package com.example.weather.service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
import com.example.weather.domain.weatherInfo;
public class WeatherService {
public static List<weatherInfo> getWeatherInfos(InputStream is) throws Exception {
// creating a pull parser
XmlPullParser pullParser = Xml.newPullParser();
// initialize the pull parser
pullParser.setInput(is, "UTF-8");
// creating a weatherInfos list, using to memory a piece of data
List<weatherInfo> weatherInfos = null;
// creating a weather element, using to set the value of it
weatherInfo weathers = null;
// When the parser to a location, returns the type of the current event
// (START_TAG, END_TAG, TEXT, etc.)
// 当解析器解析到的某个位置时,返回当前位置的事件类型( START_TAG , END_TAG ,文本等)
int type = pullParser.getEventType();
while (type != XmlPullParser.END_DOCUMENT) {// 检测XML文件是否解析完
switch (type) {
case XmlPullParser.START_TAG:
if ("infos".equals(pullParser.getName())) {
// 解析到全局开始的标签
weatherInfos = new ArrayList<weatherInfo>();
} else if ("city".equals(pullParser.getName())) {
// 解析到城市开始的标签
weathers = new weatherInfo();
} else if ("temp".equals(pullParser.getName())) {
/*
* If current event is START_TAG then if next element is
* TEXT then element content is returned or if next event is
* END_TAG then empty string is returned.
*/
String temp = pullParser.nextText();
weathers.setTemp(temp);
} else if ("wind".equals(pullParser.getName())) {
String wind = pullParser.nextText();
weathers.setWind(wind);
} else if ("weather".equals(pullParser.getName())) {
String weather = pullParser.nextText();
weathers.setWeather(weather);
} else if ("name".equals(pullParser.getName())) {
String name = pullParser.nextText();
weathers.setName(name);
} else if ("pm".equals(pullParser.getName())) {
String pm = pullParser.nextText();
weathers.setPm(pm);
}
break;
case XmlPullParser.END_TAG:
if ("city".equals(pullParser.getName())) {
// a city has finished
weatherInfos.add(weathers);
weathers = null;
}
break;
}
type = pullParser.next();
}
return weatherInfos;
}
}
显示结果: