2017年2月28日 5:10 PM
上篇博文中写道,这次要学习数据的存储完善那个角色软件,结果在XML解析上卡了壳,看了N多论坛示例代码无奈总是执行不出来,没办法为了不拖慢进度只能继续往下学习,
这次要说的是文件输入输出流和SharedPreference
文件输入输出流
文件是Android中最基本的一种数据储存方式,它与Java中的文件存储相似,都是通过 I/O 流把数据存储在文件中或者读取到设备的缓存中,Android文件存储分为内部存储,外部存储,两者的区别在于,内部存储的目录是存放在data/data/<>/files内,而外部存储是存放在SD卡中,通常路径为mnt/sdcard/sdcard内
内部存储
内部存储使用的是Context提供的openFileOutput()和openFileInput()方法
FileOutputStream openFileOutput(String name,int mode);
FileInputStream openFileInput(String name);
其中参数表示为
- name : 文件名称
- mode : 打开模式
其中mode
MODE_PRIVATE : 该程序只能被当前程序读写,默认操作方式
MODE_APPEND: 该文件可以追加内容
MODE_WORLD_READABLE:该文件可以被其他应用读取,安全性低
MODE_WORLD_WRITEABLE:该文件可以被其他应用写入,安全性低
读写实例:
//写入文件内容
String file="example.txt"; //文件名
String text="Hello World!" // 文本内容
FileOutputStream fos; //文件输出流
try{
fos=openFileOutput(file,MODE_PRIVATE);
fos.write(text.getBytes());
fos.close();
}catch(Exception e){
e.printStackTrace();
}
//读取文件内容
String file="example.txt"
String content=""; //为即将写入的内容留出变量空间
FileInputStream fis; //文件输入流
try{
fis=openFileInput(file);
byte[] buffer=new byte[fis.available()];//在内存中开辟出一段缓存区域接受文本内容
fis.read(buffer); //读入内存
content=new String(buffer); //将内容赋值给变量,方便使用
}catch(Exception e){
e.printStrackTrace();
}
外部存储
使用外部存储之前需要在全局配置文件AndroidManifest.xml里应用外部存储的权限
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
由于外部存储设备灵活性强的特点,为了避免出错需要判断当前外部存储设备是否可用,需要以下语句进行判断
Environment.getExternalStorageState()
以上工作准备完毕后就可以使用FileOutputStream ,FileInputStream或者 FileReader,FileWriter进行读写
代码示例:
//外部文件写入
String status=Environment.getExternalStorageState();//判断外部存储设备是否可用,并将状态赋给status
if(status.equals(Environment.MEDIA_MOUNTED)){
File SD=Environment.getExternalStorageDirectory();//这里需要特别注意下,由于每部手机使用的外部设备型号不同,不能将路径直接写死,需要先获取
String text="Hello World!";
File file=new File(SD,"example.txt");//使用文件方法新建一个example.txt文件
FileOutputStream fos;//文件输出流
try{
fos=new FileOutputStream(file);
fos.write(text.getBytes());
fos.close();
}catch(Exception e){
e.printStackTrace();
}//以上和在内部存储里写的一样
//外部文件的读取
String status=Environment.getExternalStorageState();
if(status=Environment,MEDIA_MOUNTED){
File SD=Environment.getExternalStorageDirectory();
File file=new File(SD,"example.txt");
FileInputStream fis;//到这里与写文件的操作步骤相同
try{
fis = new FileInputStream(file);
BufferedReader BR=new BufferedReader(new InputStreamReader(fis));//使用BUfferedReader()方法里进行每行的读取(其实上网查过这个方法以后知道,其实这个是字符流,但每行胡少一个字符 = =)
String text=BR.readLine();// 就是这,读取个每行的字符
fis.close();
}catch(Exception e){
e.printStackTrace();
}
以上是我参考教材写出来的,我写了一个实例来演示内部文件的读取和写入,可以通过 radioButton实现模式切换,使用Toast显示文件内容,点击SAVE存储信息,点击SHOW显示信息
效果图
源码在下面,因为中间还用这个工程做了其他事,会有一部分垃圾代码,,,
//这里是布局文件 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
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="com.eee.save.MainActivity">
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Please input the Text"/>
<EditText
android:id="@+id/et1"
android:layout_below="@+id/tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RadioGroup
android:layout_below="@+id/et1"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/radioGroup">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Switch to inner"/>
<RadioButton
android:id="@+id/in"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Switch to SDcard"/>
<RadioButton
android:id="@+id/out"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RadioGroup>
<Button
android:text="XML Quick Sequence"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="11dp"
android:visibility="invisible"/>
<Button
android:text="XML QUICk ANALYSIS"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:visibility="invisible"
android:layout_alignBottom="@+id/button"
android:layout_alignEnd="@+id/button"
android:layout_marginBottom="49dp" />
<TextView
android:text="↓"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView3"
android:visibility="invisible"
android:layout_alignBottom="@+id/button2"
android:layout_centerHorizontal="true" />
<TextView
android:text="This is an Example!"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView"
android:visibility="invisible"
android:layout_alignTop="@+id/button2"
android:layout_centerHorizontal="true" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/linearLayout"
android:layout_below="@+id/radioGroup"
android:layout_centerHorizontal="true"
android:layout_marginTop="45dp">
<Button
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:text="Save"/>
<Button
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="show"/>
</LinearLayout>
</RelativeLayout>
//这里是Java代码,MainActivity.java
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Toast;
import org.xmlpull.v1.XmlSerializer;
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.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private EditText et;
private Button b1, b2,b3;
private List<PersonInfo> userData;//无关。。。
private RadioButton rb1,rb2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et = (EditText) findViewById(R.id.et1);
b1 = (Button) findViewById(R.id.save);
b2 = (Button) findViewById(R.id.show);
b3=(Button)findViewById(R.id.button);
rb1=(RadioButton)findViewById(R.id.in);
rb2=(RadioButton)findViewById(R.id.out);
b1.setOnClickListener(this);
b2.setOnClickListener(this);
b3.setOnClickListener(this);
userData=new ArrayList<PersonInfo>()
;
for(int i=0;i<3;i++){
userData.add(new PersonInfo("Wang "+i,100-i,80-i));
}//这里可以忽略,这里是生成XML的地方
}
@Override
public void onClick(View v){
switch (v.getId()){
case R.id.button:
Toast.makeText(MainActivity.this,"233",Toast.LENGTH_SHORT).show();
Serializer();
break;//这里是我执行XML生成的按钮,按钮让我在布局文件里给隐藏掉了
case R.id.save:
if (rb1.isChecked()){
Toast.makeText(MainActivity.this,"Switch to Inner successful!",Toast.LENGTH_SHORT).show();
String info =et.getText().toString().trim();
FileOutputStream fos;
try {
fos=openFileOutput("data.txt", Context.MODE_APPEND);
fos.write(info.getBytes());
fos.close();
} catch (Exception e){
e.printStackTrace();
}
Toast.makeText(this,"Save Successful",Toast.LENGTH_SHORT).show();
//以上是内部存储的代码
}else if (rb2.isChecked()){
Toast.makeText(MainActivity.this,"Switch to SDcard successful!",Toast.LENGTH_SHORT).show();
String status=Environment.getExternalStorageState();
if(status.equals(Environment.MEDIA_MOUNTED)){
File SD=Environment.getExternalStorageDirectory();
File file = new File(SD,"data.txt");
String info =et.getText().toString().trim();
FileOutputStream fos;
try{
fos=new FileOutputStream(file);
fos.write(info.getBytes());
fos.close();
}catch (Exception e){
e.printStackTrace();
}
}
}break;
//以上是外部存储的代码
case R.id.show:
if(rb1.isChecked()) {
Toast.makeText(MainActivity.this,"Switch to Inner successful!",Toast.LENGTH_SHORT).show();
String context = "";
FileInputStream fis;
try {
fis = openFileInput("data.txt");
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
context = new String(buffer);
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(this, "---> " + context + " <---", Toast.LENGTH_LONG).show();
//以上是内部读取的代码
}else if (rb2.isChecked()){
Toast.makeText(MainActivity.this,"Switch to SDcard successful!",Toast.LENGTH_SHORT).show();
String status=Environment.getExternalStorageState();
if(status.equals(Environment.MEDIA_MOUNTED)){
File SD=Environment.getExternalStorageDirectory();
File file=new File(SD,"data.txt");
FileInputStream fis;
try{
fis=new FileInputStream(file);
BufferedReader BR =new BufferedReader(new InputStreamReader(fis));
String info=BR.readLine();
fis.close();
Toast.makeText(this, "---> " + info + " <---", Toast.LENGTH_LONG).show();
}catch (Exception e){
e.printStackTrace();
}
}
}//以上是外部读取的代码
break;
}
}
}
以上就是关于文件存储的例子,估计看完就能明白了吧,文件操作不难,但是比较麻烦,下面开始介绍一个常用的轻量级存储的方法,SharedPreferences。
SharedPreferences
SharedPreferences用于Android应用里的参数保存,比如说是用户的设置,用户名密码的保存,对于数据的存储,SharedPreferences使用的键值对的方式进行存储,key-value,自动生成xml文件,存储在data/data/<>/shared_prefs中
通过context.getSharedPreference()获取SharedPreferences实例
SharedPreferences sp =context.SharedPreferences(String name,int mode);
其中
name 表示文件名,mode为文件操作模式,模式类似于文件流里的模式
MODE_PRIVATE : 该程序只能被当前程序读写,默认操作方式
MODE_APPEND: 该文件可以追加内容
MODE_WORLD_READABLE:该文件可以被其他应用读取,安全性低
MODE_WORLD_WRITEABLE:该文件可以被其他应用写入,安全性低
SharedPreferences只能获取数据,但是无法对获取的数据进行操作,数据的存储和修改需要通过SharedPreferences.Editor()实现
//SharedPreferences.Editor所支持的方法
SharedPreferences.Editor.edit(); //创建Editor对象
SharedPreferences.Editor.putString(String key,String value);
//向SharedPreferences中存入指定key的String值
SharedPreferences.Editor.putString(String key,int value);
//向SharedPreferences中存入指定key的int值
SharedPreferences.Editor.putString(String key,float value);
//向SharedPreferences中存入指定key的float值
SharedPreferences.Editor.putString(String key,long value);
//向SharedPreferences中存入指定key的long值
SharedPreferences.Editor.putString(String key,Boolean value);
//向SharedPreferences中存入指定key的Boolean值
SharedPreferences.Editor.remove(String key);
//删除SharedPreferences里指定key的值
SharedPreferences.Editor.clear(); //清除SharedPreferences里所有数据
boolean.commit(); //提交所做出的修改
使用SharedPreferences对数据的存储,获取和删除
数据的存储
思路为,先获取SharedPreferences的对象,再获取Editor编辑器,然后使用putString()方法添加数据,最后使用commit()方法提交修改
//使用SharedPreferences对数据进行存储
SharedPreferences sp =getSharedPreferences("example",MODE_PRIVATE);
//获取SharedPreferences对象,指定文件名example和打开模式
Editor editor=sp.edit();//获取Editor
editor.putString("ID","10011");
editor.putString("Name","优快云");//添加键值对
editor.commit();//提交修改
数据的获取
思路为获取SharedPreferences对象后,直接使用getString()方法获取对应key的值
SharedPreferences sp =context.getSharedPreferences();
//获取SharedPreferences的对象
String text =sp.getString("Name",""); //获取Name标签下的值
数据的删除
思路与数据的存储相似,首先获取SharedPreferences对象,Editor对象,通过remove()方法删除数据,最后用commit()方法提交修改
SharedPreferences sp =context.getSharedPreferences();
Editor editor =sp.edit();
editor.remove("Name");//删除指定key下的数据
//editor.clear(); ----->删除所有数据
editor.commit();
实例演示
这次使用的是那个角色工程,进行修改,新增登录界面,设置登录界面为Welcome Activity,可以选择是否记住密码(默认反选),点击Login跳转总结界面
效果图
代码部分:
//布局文件 activity_login(这里的activity_secact不演示了,前几篇博文里有)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<Button
android:id="@+id/login"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="350dp"
android:layout_centerHorizontal="true"
android:text="LOGIN"
android:textColor="#ffffff"
android:textSize="20sp"
android:background="#6495ED"/>
<LinearLayout
android:layout_marginTop="19dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_below="@+id/tx"
android:layout_centerHorizontal="true">
<RelativeLayout
android:id="@+id/un_test"
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:id="@+id/un"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="UserName"
android:textSize="20sp"/>
<EditText
android:id="@+id/username"
android:layout_toRightOf="@+id/un"
android:layout_width="200dp"
android:layout_marginLeft="10dp"
android:layout_height="wrap_content" />
</RelativeLayout>
<RelativeLayout
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:id="@+id/pwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Password"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:textSize="20sp"/>
<EditText
android:layout_width="180dp"
android:layout_marginLeft="40dp"
android:layout_height="wrap_content"
android:id="@+id/password"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="12dp"
android:inputType="textPassword"
/>
</RelativeLayout>
<TextView
android:textColor="#EE2C2C"
android:layout_marginLeft="230dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Remember?"
android:id="@+id/textView" />
<CheckBox
android:id="@+id/yn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="270dp"/>
</LinearLayout>
<ImageView
android:id="@+id/tx"
android:layout_marginTop="29dp"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/tx"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
//首先创建一个工具类 Utils,用来存储和读取数据
package com.eee.eeeee;
import android.content.Context;
import android.content.SharedPreferences;
import android.widget.CheckBox;
import java.util.HashMap;
import java.util.Map;
/**
* Created by li124 on 2017/2/28.
*/
public class Utils {
public static Boolean saveUserInfo(Context context,String number,String password,String status){
SharedPreferences sp=context.getSharedPreferences("data",Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sp.edit();
editor.putString("userName",number);
editor.putString("pwd",password);
editor.putString("Status",status);
editor.commit();
return true;
}
public static Map<String,String> getUserInfo(Context context){
SharedPreferences sp=context.getSharedPreferences("data",Context.MODE_PRIVATE);
String userName=sp.getString("userName",null);
String pwd=sp.getString("pwd",null);
String status=sp.getString("status",null);
Map<String,String> userMap =new HashMap<String,String>();
userMap.put("userName",userName);
userMap.put("pwd",pwd);
userMap.put("Status",status);
return userMap;
}
}
//其次建立登录界面Activity并在AndroidManifest将登录Activity设为欢迎界面
<activity
android:name=".Login"
android:label="Login">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
//Login_activity
package com.eee.eeeee;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import java.util.Map;
/**
* Created by li124 on 2017/2/28.
*/
public class Login extends AppCompatActivity {
private EditText et_un, et_pwd;
public int x=1;
private CheckBox cb;
private Button button;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
et_un = (EditText) findViewById(R.id.username);
et_pwd = (EditText) findViewById(R.id.password);
button = (Button) findViewById(R.id.login);
cb=(CheckBox)findViewById(R.id.yn);
Map<String, String> userInfo = Utils.getUserInfo(this);//新建map获取数据
// String check=userInfo.get("Status");
if (userInfo != null) {
et_un.setText(userInfo.get("userName"));
et_pwd.setText(userInfo.get("pwd"));//获取用户名和密码
// if(check=="C"){
// cb.setChecked(true);
// }else{
// cb.setChecked(false);
// }
}
// intent.putExtra("un", et_un.getText().toString().trim());
// intent.putExtra("pd", et_pwd.getText().toString().trim());
button.setOnClickListener(new View.OnClickListener() {
//CheckBox cb=(CheckBox)findViewById(R.id.yn);
@Override
public void onClick(View view) {
Intent intent = new Intent(Login.this, SecACT.class);
String password=et_pwd.getText().toString();
String username=et_un.getText().toString();
String status="";
if (cb.isChecked()){
Log.i("----->",username);
x=2;
status="C";
}else {
Log.i("----->",password);
x=0;
status="UC";
}//这里就是判断是否保存密码的地方
if(TextUtils.isEmpty(username)){
Toast.makeText(Login.this,"UserName is Empty!",Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(password)){
Toast.makeText(Login.this,"Password is Empty!",Toast.LENGTH_SHORT).show();
return;
}//判断是否密码和用户名为空
if(x==2){
boolean issaved =Utils.saveUserInfo(Login.this,username,password,status);
if(issaved){
Toast.makeText(Login.this,"Successful!",Toast.LENGTH_SHORT).show();
startActivity(intent);
}else{
Toast.makeText(Login.this,"Fail!",Toast.LENGTH_SHORT).show();
}//判断保存是否成功
}else if(x==0){
Toast.makeText(Login.this,"Login Successful!",Toast.LENGTH_SHORT).show();
startActivity(intent);
}//这里是在不选remember时直接登录
}
});
}
}
//由于SecAct里有变化,将代码重新贴一遍
package com.eee.eeeee;
import android.os.Bundle;
import android.content.Intent;
import android.inputmethodservice.Keyboard;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Map;
import static com.eee.eeeee.R.styleable.View;
/**
* Created by li124 on 2017/2/24.
*/
public class SecACT extends AppCompatActivity {
public TextView tv1,tv2,tv3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_secact);
Button b1=(Button)findViewById(R.id.back1);
// intent.putExtra("ED","Hello World");
// setResult(RESULT_OK,intent);
// b1.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View view) {
//
// finish();
// }
// });
tv1=(TextView)findViewById(R.id.name);
tv2=(TextView)findViewById(R.id.pass);
tv3=(TextView)findViewById(R.id.sex);
Map<String, String> userInfo = Utils.getUserInfo(this);
String username=userInfo.get("userName");
String password=userInfo.get("pwd");
String s="Man";
tv1.setText("Your UserName: "+username);
tv2.setText("Your PassWord: "+password+" (Please Do not tell Others)");
tv3.setText("Your Sex: "+s);//这里稍微做下改动,获取数据的方式不再是通过intent获取了,而是读取xml获取数据,intent传递传递数据的方法在以下做出注释
// Intent i =getIntent();
// String name =i.getStringExtra("un");
// String pass = i.getStringExtra("pd");
// String sex =i.getStringExtra("sex");
// tv1.setText("Your UserName: "+name);
// tv2.setText("Your PassWord: "+pass+" (Please Do not tell Others)");
// tv3.setText("Your Sex: "+sex);
/**Bundle**/
// Bundle bundle=intent.getExtras();
// String name=bundle.getString("un");
// String pass=bundle.getString("pd");
// String sex1=bundle.getString("sex");
// tv1.setText("Your UserName: "+name);
// tv2.setText("Your PassWord: "+pass+" (Please Do not tell Others)");
// tv3.setText("Your Sex: "+sex1);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(SecACT.this,CharAct.class);
intent.putExtra("name",tv1.getText().toString().trim());
if(getData().equals("Woman")){
intent.putExtra("code","2");
}else if(getData().equals("Man")){
intent.putExtra("code","1");
}
Log.i("---->",getData());
startActivity(intent);
}
});
}
public String getData(){
Intent in =getIntent();
String x=in.getStringExtra("sex");
return x;
}
}
这样就是全部的内容了,看了也许会懂一点了吧 (讲的不好请见谅,部分代码示例修改参考自教材)= =
(ps:第一次使用MarkDown写博客,不知道效果怎么样,就先这样吧,关于XML我打算先放下一会,再说。。。)