当前位置:   article > 正文

Android移动开发基础案例教程 第4章 数据存储_修改mainactivity类中调用spsaveqq类静态方法的地方,改为调用filesaveqq类

修改mainactivity类中调用spsaveqq类静态方法的地方,改为调用filesaveqq类的静态

4.1 数据存储方式

  • 文件存储是一种较常用的方法,与Java中的文件存储类似,都是通过I/O流的形式存储数据。
  • SharedPreferences是Android提供的用来存储一些简单的配置信息的一种机制。
  • SQLite数据库是Android自带的一个轻量级数据库,支持基本SQL语法。
  • ContentProvider是Android四大组件之一,可以将自己的数据共享给其他应用程序。
  • 网络存储是通过网络提供的存储空间来存储/获取数据信息。

4.2 文件存储

4.2.1 文件存储简介

  • 文件存储是Android中最基本的一种数据存储方式,它与Java中的文件存储类似,都是通过I/O流的形式把数据存储到文档中。

  • Android中的文件存储分为内部存储和外部存储。

    • image.png
1.内部存储—写入

image.png

    String fileName = "data.txt";   
    String content = "helloworld"; 
    FileOutputStream fos;
    try {
             fos = openFileOutput(fileName, MODE_PRIVATE);
             fos.write(content.getBytes()); 
             fos.close();   
     } catch (Exception e) {
            e.printStackTrace();
     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
2.内部存储—读取

image.png

     String content = "";
     FileInputStream fis;
     try {
           fis = openFileInput("data.txt"); 
           byte[] buffer = new byte[fis.available()];
           fis.read(buffer); 
           content = new String(buffer);
           fis.close();
     } catch (Exception e) {
          e.printStackTrace();
     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
3.外部存储—存入

image.png

     String state = Environment.getExternalStorageState(); 
     if (state.equals(Environment.MEDIA_MOUNTED)) {
           File SDPath = Environment.getExternalStorageDirectory();
           File file = new File(SDPath, "data.txt");
           String data = "HelloWorld";
           FileOutputStream fos;
           try {
      fos = new FileOutputStream(file);
        fos.write(data.getBytes());
        fos.close();
            } catch (Exception e) {
        e.printStackTrace();
            }
     }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
4.外部存储—读取

image.png

 String state = Environment.getExternalStorageState();
    if (state.equals(Environment.MEDIA_MOUNTED)) {
          File SDPath = Environment.getExternalStorageDirectory();
          File file = new File(SDPath, "data.txt");
          FileInputStream fis;
          try {
    fis = new FileInputStream(file);
    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
    String data = br.readLine();
          } catch (Exception e) {
    e.printStackTrace();
          }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
5.外部存储—声明权限
  • Android系统为了保证应用程序的安全性做了相关规定,如果程序需要访问系统的一些关键信息,必须要在清单文凭中声明权限才可以,否则程序运行时会直接崩溃。
  • 由于操作SD卡中的数据属于系统中比较关键的信息,因此需要在清单文件的节点中添加SD卡的读写权限。
<uses-permission     
     android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission   
     android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  • 1
  • 2
  • 3
  • 4

4.2.2 实战演练——保存QQ密码

image.png

1.MainActivity
package cn.itcast.saveqq;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.util.Map;
public class MainActivity extends AppCompatActivity implements
        View.OnClickListener {
    private EditText etNumber;
    private EditText etPassword;
    private Button btnLogin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化界面
        initView();
        Map<String, String> userInfo = SPSaveQQ.getUserInfo(this);
        if (userInfo != null) {
            etNumber.setText(userInfo.get("number"));
            etPassword.setText(userInfo.get("password"));
        }
    }
    private void initView() {
        etNumber = (EditText) findViewById(R.id.et_number);
        etPassword = (EditText) findViewById(R.id.et_password);
        btnLogin = (Button) findViewById(R.id.btn_login);
        //设置按钮的点击事件
        btnLogin.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //当单击“登录”按钮时,获取QQ账号和密码
        String number = etNumber.getText().toString().trim();
        String password = etPassword.getText().toString();
        //检验账号和密码是否正确
        if (TextUtils.isEmpty(number)) {
            Toast.makeText(this, "请输入QQ账号", Toast.LENGTH_SHORT).show();
            return;
        }
        if (TextUtils.isEmpty(password)) {
            Toast.makeText(this, "请输入密码", Toast.LENGTH_SHORT).show();
            return;
        }
        //登录成功
        Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
        //保存用户信息
        boolean isSaveSuccess = SPSaveQQ.saveUserInfo(this, number, password);
        if (isSaveSuccess) {
            Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "保存失败", Toast.LENGTH_SHORT).show();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
2.FileSaveQQ
package cn.itcast.saveqq;
import android.content.Context;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;
public class FileSaveQQ {
    //保存QQ账号和登录密码到data.txt文件中
    public static boolean saveUserInfo(Context context, String number,
                                       String password) {
        try {
            FileOutputStream fos = context.openFileOutput("data.txt",
                    Context.MODE_PRIVATE);
            fos.write((number + ":" + password).getBytes());
            fos.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    //从data.txt文件中获取存储的QQ账号和密码
    public static Map<String, String> getUserInfo(Context context) {
        String content = "";
        try {
            FileInputStream fis = context.openFileInput("data.txt");
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            content = new String(buffer);
            Map<String, String> userMap = new HashMap<String, String>();
            String[] infos = content.split(":");
            userMap.put("number", infos[0]);
            userMap.put("password", infos[1]);
            fis.close();
            return userMap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
3.SPSaveQQ
package cn.itcast.saveqq;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.HashMap;
import java.util.Map;
public class SPSaveQQ{
    // 保存QQ账号和登录密码到data.xml文件中
    public static boolean saveUserInfo(Context context, String number,
                                       String password) {
        SharedPreferences sp = context.getSharedPreferences("data",
                Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        edit.putString("userName", number);
        edit.putString("pwd", password);
        edit.commit();
        return true;
    }
    //从data.xml文件中获取存储的QQ账号和密码
    public static Map<String, String> getUserInfo(Context context) {
        SharedPreferences sp = context.getSharedPreferences("data",
                Context.MODE_PRIVATE);
        String number = sp.getString("userName", null);
        String password = sp.getString("pwd", null);
        Map<String, String> userMap = new HashMap<String, String>();
        userMap.put("number", number);
        userMap.put("password", password);
        return userMap;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

4.3 XML解析

4.3.1 三种解析方式

1.DOM解析

将XML文件中所有内容以DOM树形式存放在内存中,支持删除、修改等功能。缺点是消耗内存较大。

2.SAX解析

逐行扫描XML文件,读取文件的同时即可进行解析处理,不必等到文件加载结束。缺点是无法进行增、删、改等操作。

3.PULL解析

一个开源的Java项目,既可以用于Android应用,也可以JavaEE程序。Android中已经集成了PULL解析器。

4.3.2 实战演练——天气预报

image.png

1.XML文件
<?xml version="1.0" encoding="utf-8"?>
<infos>
    <city id="sh">
        <temp>20℃/30℃</temp>
        <weather>晴天多云</weather>
        <name>上海</name>
        <pm>80</pm>
        <wind>1级</wind>
    </city>
    <city id="bj">
        <temp>26℃/32℃</temp>
        <weather>晴天</weather>
        <name>北京</name>
        <pm>98</pm>
        <wind>3级</wind>
    </city>
    <city id="gz">
        <temp>15℃/24℃</temp>
        <weather>多云</weather>
        <name>广州</name>
        <pm>30</pm>
        <wind>5级</wind>
    </city>
</infos>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
2.MainActivity
package cn.itcast.weather;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity implements
        View.OnClickListener {
    private TextView tvCity;
    private TextView tvWeather;
    private TextView tvTemp;
    private TextView tvWind;
    private TextView tvPm;
    private ImageView ivIcon;
    private Map<String, String> map;
    private List<Map<String, String>> list;
    private String temp, weather, name, pm, wind;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化文本控件
        initView();
        try {
            //读取weather1.xml文件
            InputStream is = this.getResources().openRawResource(R.raw.weather1);
            //把每个城市的天气信息集合存到weatherInfos中
            List<WeatherInfo> weatherInfos = WeatherService.getInfosFromXML(is);
            //循环读取weatherInfos中的每一条数据
            list = new ArrayList<Map<String, String>>();
            for (WeatherInfo info : weatherInfos) {
                map = new HashMap<String, String>();
                map.put("temp", info.getTemp());
                map.put("weather", info.getWeather());
                map.put("name", info.getName());
                map.put("pm", info.getPm());
                map.put("wind", info.getWind());
                list.add(map);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, "解析信息失败", Toast.LENGTH_SHORT).show();
        }
        //自定义getMap()方法,显示天气信息到文本控件中,默认显示北京的天气
        getMap(1, R.drawable.sun);
    }
    private void initView() {
        tvCity = (TextView) findViewById(R.id.tv_city);
        tvWeather = (TextView) findViewById(R.id.tv_weather);
        tvTemp = (TextView) findViewById(R.id.tv_temp);
        tvWind = (TextView) findViewById(R.id.tv_wind);
        tvPm = (TextView) findViewById(R.id.tv_pm);
        ivIcon = (ImageView) findViewById(R.id.iv_icon);
        findViewById(R.id.btn_sh).setOnClickListener(this);
        findViewById(R.id.btn_bj).setOnClickListener(this);
        findViewById(R.id.btn_gz).setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {    //按钮的点击事件
        switch (v.getId()) {
            case R.id.btn_sh:
                getMap(0, R.drawable.cloud_sun);
                break;
            case R.id.btn_bj:
                getMap(1, R.drawable.sun);
                break;
            case R.id.btn_gz:
                getMap(2, R.drawable.clouds);
                break;
        }
    }
    //将城市天气信息分条展示到界面上
    private void getMap(int number, int iconNumber) {
        Map<String, String> cityMap = list.get(number);
        temp = cityMap.get("temp");
        weather = cityMap.get("weather");
        name = cityMap.get("name");
        pm = cityMap.get("pm");
        wind = cityMap.get("wind");
        tvCity.setText(name);
        tvWeather.setText(weather);
        tvTemp.setText("" + temp);
        tvWind.setText("风力  : " + wind);
        tvPm.setText("pm: " + pm);
        ivIcon.setImageResource(iconNumber);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
3.WeatherServer
package cn.itcast.weather;
import android.util.Xml;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.xmlpull.v1.XmlPullParser;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class WeatherService {
    //解析xml文件返回天气信息的集合
    public static List<WeatherInfo> getInfosFromXML (InputStream is)
            throws Exception {
        //得到pull解析器
        XmlPullParser parser = Xml.newPullParser();
        // 初始化解析器,第一个参数代表包含xml的数据
        parser.setInput(is, "utf-8");
        List<WeatherInfo> weatherInfos = null;
        WeatherInfo weatherInfo = null;
        //得到当前事件的类型
        int type = parser.getEventType();
        // END_DOCUMENT文档结束标签
        while (type != XmlPullParser.END_DOCUMENT) {
            switch (type) {
                //一个节点的开始标签
                case XmlPullParser.START_TAG:
                    //解析到全局开始的标签 infos 根节点
                    if("infos".equals(parser.getName())){
                        weatherInfos = new ArrayList<WeatherInfo>();
                    }else if("city".equals(parser.getName())){
                        weatherInfo = new WeatherInfo();
                        String idStr = parser.getAttributeValue(0);
                        weatherInfo.setId(idStr);
                    }else if("temp".equals(parser.getName())){
                        //parset.nextText()得到该tag节点中的内容
                        String temp = parser.nextText();
                        weatherInfo.setTemp(temp);
                    }else if("weather".equals(parser.getName())){
                        String weather = parser.nextText();
                        weatherInfo.setWeather(weather);
                    }else if("name".equals(parser.getName())){
                        String name = parser.nextText();
                        weatherInfo.setName(name);
                    }else if("pm".equals(parser.getName())){
                        String pm = parser.nextText();
                        weatherInfo.setPm(pm);
                    }else if("wind".equals(parser.getName())){
                        String wind = parser.nextText();
                        weatherInfo.setWind(wind);
                    }
                    break;
                //一个节点结束的标签
                case XmlPullParser.END_TAG:
                    //一个城市的信息处理完毕,city的结束标签
                    if("city".equals(parser.getName())){
                        weatherInfos.add(weatherInfo);
                        weatherInfo = null;
                    }
                    break;
            }
            type = parser.next();
        }
        return weatherInfos;
    }

    //解析json文件返回天气信息的集合(下一个例子的)
    public static List<WeatherInfo> getInfosFromJson(InputStream is)
            throws IOException {
        byte[] buffer = new byte[is.available()];
        is.read(buffer);
        String json = new String(buffer, "utf-8");
        //使用gson库解析JSON数据
       Gson gson = new Gson();
        Type listType = new TypeToken<List<WeatherInfo>>() { }.getType();
        List<WeatherInfo> weatherInfos = gson.fromJson(json, listType);
        return weatherInfos;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

4.WeatherInFo

package cn.itcast.weather;
public class WeatherInfo {
    private String id;
    private String temp;
    private String weather;
    private String name;
    private String pm;
    private String wind;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTemp() {
        return temp;
    }

    public void setTemp(String temp) {
        this.temp = temp;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPm() {
        return pm;
    }

    public void setPm(String pm) {
        this.pm = pm;
    }

    public String getWind() {
        return wind;
    }

    public void setWind(String wind) {
        this.wind = wind;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

4.4 JSON解析

4.4.1 JSON数据

1.JSON数据特点
  • JSON即JavaScript Object Notation(对象表示法),是一种轻量级的数据交换格式。
  • JSON是基于纯文本的数据格式,它可以传输String、Number、Boolean类型的数据,也可以传输数组,或者Object对象。
  • JSON文件的扩展名为.json。
  • JSON分为JSON对象和JSON数组两种数据结构。
2.对象结构

以“{”开始,以“}”结束。中间部分由0个或多个以“,”分隔的key:value对构成,注意关键字和值之间以“:”分隔。

image.png

3.数组结构

以“[”开始,以“]”结束。中间部分由0个或多个以“,”分隔的值的列表组成。

image.png

image.png

4.4.2 JSON解析

1.两种解析方式

image.png

2.解析JSON对象

image.png

3.解析JSON数组

image.png

4.解析JSON

image.png

image.png

4.4.3 实战演练——天气预报

image.png

代码见上一节

4.5 SharedPreferences

4.5.1 SharedPreferences的使用

1.SharedPreferences的特点
  • SharedPreferences是Android平台上一个轻量级的存储类。
  • 用于存储应用程序的配置参数,如用户名、密码等。
  • 通过key/value(键值对)的形式将数据保存在XML文件中。
  • value值只能是float、int、long、boolean、String、StringSet类型数据。
2.存储数据

image.png

3.获取数据

获取数据可以直接通过SharedPreferences对象的getXXX()方法 来实现。

image.png

image.png

4.5.2 实战演练——保存QQ密码

image.png

4.6 本章小结

本章主要讲解了Android中的数据存储,首先介绍了Android中常见的数据存储方式,然后讲解了文件存储以及XML和JSON数据的解析,最后讲解了SharedPreferences。数据存储是Android中非常重要的内容,每个应用程序基本上都会涉及到数据存储,因此要求初学必须熟练掌握本章知识。

✎ 本章作业 Android系统中的五种数据存储方式各自的特点。 SharedPreferences如何存储数据。

✎ 预习作业 SQLite数据库的使用 ListView控件的作用

【学习笔记】

【学习资料】

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/251862
推荐阅读
相关标签
  

闽ICP备14008679号