Android应用开发-数据存储和界面展现(一)

常见布局

相对布局(RelativeLayout)

  • 组件默认位置都是左上角(左对齐、顶部对齐父元素),组件之间可以重叠

  • 可以相对于父元素上下左右对齐,相对于父元素,水平居中、竖直居中、水平竖直同时居中

    • 设置右对齐父元素

      android:layout_alignParentRight="true"
  • 可以相对于其他组件上下左右对齐

    • 设置与指定组件右对齐

      android:layout_alignRight="@id/tv1"
  • 可以布局于其他组件的上方、下方、左边、右边

    • 设置组件在指定组件的右边

      android:layout_toRightOf="@id/tv1"
    • 设置在指定组件的下边

      android:layout_below="@id/tv1"

线性布局(LinearLayout)

  • 有一个布局方向,水平或者竖直

    • 指定子组件按水平布局

      android:orientation="horizontal"
  • 在竖直布局下,设置左对齐、右对齐,水平居中会生效,其它无效

  • 在水平布局下,设置顶部对齐、底部对齐、竖直居中会生效,其他无效

  • 使用match_parent时注意不要把其他组件顶出去

  • 权重:按比例分配屏幕的剩余宽度或者高度

    android:layout_weight="1"

帧布局(FrameLayout)

  • 组件默认位置都是左上角(左对齐、顶部对齐父元素),组件之间可以重叠

  • 可以设置上下左右对齐,水平竖直居中,设置方式与线性布局一样

  • 不能相对于其他组件布局

表格布局(TableLayout)

  • 每个TableRow节点是一行,它的每个子节点是一列

  • 表格布局中的节点可以不设置宽高,因为设置了也无效

    • 根节点TableLayout的子节点宽为匹配父元素,高为包裹内容

    • TableRow节点的子节点宽为包裹内容,高为包裹内容

    • 以上默认属性无法修改

  • 根节点中可以设置以下属性,表示让第1列拉伸填满屏幕宽度的剩余空间

    android:stretchColumns="1"

绝对布局(AbsoluteLayout)

  • 基本用不到

  • 直接指定组件的x、y坐标

    android:layout_x="144dp"
    android:layout_y="154dp"

Logcat

  • 日志信息总共分为5个等级

    • verbose:冗余,最低等级

    • debug:调试

    • info:正常等级的信息

    • warn:警告

    • error:错误

  • 定义过滤器方便查看

  • System.out.print输出的日志级别是info,tag是System.out

  • Android提供的日志输出api

    Log.v(TAG, "加油吧,童鞋们");
    Log.d(TAG, "加油吧,童鞋们");
    Log.i(TAG, "加油吧,童鞋们");
    Log.w(TAG, "加油吧,童鞋们");
    Log.e(TAG, "加油吧,童鞋们");

Android的存储

内部存储空间

  • RAM内存:运行内存,相当于电脑的内存

  • ROM内存:存储内存,相当于电脑的硬盘(这个才是内部存储空间,是必须有的)

外部存储空间

  • SD卡:相当于电脑的移动硬盘(可有可无)

    • 2.2之前,SD卡路径:sdcard

    • 4.3之前,SD卡路径:mnt/sdcard

    • 4.3开始,SD卡路径:storage/sdcard

    • 为了兼容低版本的程序,Android系统在原SD卡的位置都保留有一个"快捷方式"

现在买的手机,如魅族MX5 16G版,这个16G实际上指的是外部存储空间,而厂家并没有告诉我们手机的内部存储空间是多少

在内部存储读写数据

用API获得内部存储的真实路径

  • getFilesDir()得到的file对象的路径是data/data/[package name]/files

    • 存放在这个路径下的文件,只要你不删,它就一直在
  • getCacheDir()得到的file对象的路径是data/data/[package name]/cache

    • 存放在这个路径下的文件,当内存不足时,有可能被删除
  • 系统管理应用界面的清除缓存,会清除cache文件夹下的东西,清除数据,会清除整个包名目录下的东西

在外部存储读写数据

  • 最简单的打开SD卡的方式

    File file = new File("sdcard/xxx.txt");
  • 使用API获得SD卡的真实路径,因为部分手机厂商会更改SD卡的路径

    File file = new File(Environment.getExternalStorageDirectory(),"xxx.txt")
  • 判断SD卡是否准备就绪

    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
  • SD卡主要的几种状态

    • MEDIA_UNKNOWN:不能识别sd卡

    • MEDIA_REMOVED:没有sd卡

    • MEDIA_UNMOUNTED:sd卡存在但是没有挂载

    • MEDIA_CHECKING:sd卡正在准备

    • MEDIA_MOUNTED:sd卡已经挂载,可用

  • 写SD卡需要权限

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  • 读SD卡,在4.0之前不需要权限,4.0之后可以设置为需要

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

查看源代码查找获取SD卡剩余容量的代码

  • 导入Settings项目

  • 查找“可用空间”得到

     <string name="memory_available" msgid="418542433817289474">"可用空间"</string>
  • 查找"memory_available",得到

    <Preference android:key="memory_sd_avail" 
        style="?android:attr/preferenceInformationStyle" 
        android:title="@string/memory_available"
        android:summary="00"/>
  • 查找"memory_sd_avail",得到

    //这个字符串就是SD卡剩余容量
    formatSize(availableBlocks * blockSize) + readOnly
    //这两个参数相乘,得到SD卡以字节为单位的剩余容量
    availableBlocks * blockSize
  • 存储设备会被分为若干个区块,每个区块有固定的大小

  • 区块大小 * 区块数量 等于 存储设备的总大小

文件访问权限

  • 指的是谁能访问这个文件(夹)

  • 在Android系统中,每一个应用,都是一个独立的用户

  • 使用10个字母来表示

  • drwxrwxrwx

  • 第一个字母:

    • d:表示文件夹

    • -:表示文件

  • 第一组rwx:表示的是文件拥有者(owner)对该文件的权限

    • r:read,读

    • w:write,写

    • x:execute,执行

  • 第二组rwx:表示的是跟文件拥有者属于同一用户组(group)的用户对该文件的权限

  • 第三组rwx:表示的是其他用户(other)对该文件的权限

SharedPreference

  • 非常适合用来保存零散的简单的数据

  • 往SharedPreference里写数据

    //拿到一个SharedPreference对象
    SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
    //拿到编辑器
    Editor ed = sp.edit();
    //写数据
    ed.putString("name", "eniac");
    ed.commit();
  • 从SharedPreference里取数据

    //拿到一个SharedPreference对象
    SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
    //从SharedPreference里取数据
    String name = sp.getString("name", "");

生成XML文件备份短信

  • 创建几个虚拟的短信对象,存在list中

  • 备份数据通常都是备份至SD卡

使用StringBuffer拼接字符串

  • 把整个xml文件所有节点append到sb对象里

    sb.append("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>");
    //添加smss的开始节点
    sb.append("<smss>");
    .......
  • 把sb写到输出流中

    fos.write(sb.toString().getBytes());

使用XMl序列化器生成xml文件

  • 得到xml序列化器对象

    XmlSerializer xs = Xml.newSerializer();
  • 给序列化器设置输出流

    File file = new File(Environment.getExternalStorageDirectory(), "backupsms.xml");
    FileOutputStream fos = new FileOutputStream(file);
    //给序列化器指定好输出流
    xs.setOutput(fos, "utf-8");
  • 开始生成xml文件

    xs.startDocument("utf-8", true);
    xs.startTag(null, "smss");
    ......

pull解析xml文件

  • 原始XML资源一般保存在/res/xml/路径下

  • 先自己写一个weather.xml文件,存一些天气信息

根据XML资源的ID获取解析该资源的解析器

    XmlPullParser xp = getResources().getXml(R.xml.weather);

开始解析

  • 拿到指针所在当前节点的事件类型

    int type = xp.getEventType();
  • 事件类型主要有五种

    • START_DOCUMENT:xml头的事件类型

    • END_DOCUMENT:xml尾的事件类型

    • START_TAG:开始节点的事件类型

    • END_TAG:结束节点的事件类型

    • TEXT:文本节点的事件类型

  • 如果获取到的事件类型不是END_DOCUMENT,就说明解析还没有完成,如果是,解析完成,while循环结束

    while(type != XmlPullParser.END_DOCUMENT)
  • 当我们解析到不同节点时,需要进行不同的操作,所以判断一下当前节点的name

    • 当解析到weather的开始节点时,new出list

    • 当解析到city的开始节点时,创建city对象,创建对象是为了更方便的保存即将解析到的文本

    • 当解析到name开始节点时,获取下一个节点的文本内容,temp、pm也是一样

      case XmlPullParser.START_TAG:
      //获取当前节点的名字
          if("weather".equals(xp.getName())){
              citys = new ArrayList<City>();
          }
          else if("city".equals(xp.getName())){
              city = new City();
          }
          else if("name".equals(xp.getName())){
              //获取当前节点的下一个节点的文本
              String name = xp.nextText();
              city.setName(name);
          }
          else if("temp".equals(xp.getName())){
              String temp = xp.nextText();
              city.setTemp(temp);
          }
          else if("pm".equals(xp.getName())){
              String pm = xp.nextText();
              city.setPm(pm);
          }
          break;
  • 当解析到city的结束节点时,说明city的三个子节点已经全部解析完了,把city对象添加至list

    case XmlPullParser.END_TAG:
        if("city".equals(xp.getName())){
                citys.add(city);
        }

你可能感兴趣的:(Android应用开发-数据存储和界面展现(一))