目录
3.AVD(Android Virtual Devices)
1. 自定义一个文件写入操作类Filestorage.java
一、实验目的
- 了解Android开发
- 掌握传感器调用
- 交互式界面设计
二、实验要求
1) 搭建开发平台;
2)编写简单程序,实现按钮、屏幕操作的基本功能,应用程序下传安装在手机运行;
3)调用传感器,采集数据;
4)使用屏幕显示功能,实时显示采集的数据;
5)使用屏幕绘图功能,实时绘制采集的传感器数据;
6)使用对话框方式设置存储位置,保存数据;
7)实地测试,数据分析处理(根据实际数据情况,各自选用有效地方法)
三、实验原理
(一)第一次实验
本次实验我们将搭建开发平台,编写简单程序,实现按钮、屏幕操作的基本功能,应用程序下传安装在手机运行。我们需要搭建Android的开发环境并开发一个按键交互小程序。下面我们首先介绍一下Android开发所需要用到的基础框架:JDK和Android SDK开发套件。
1.JDK(Java Development Kit)
JAVA作为一款知名的编程语言,自面世以来一直非常的流行。在最近几年的编程语言排行榜上更是稳坐第一名的宝位。而Android系统在开发之时也选择了JAVA作为其编程语言。JDK的全名叫做Java Development Kit JAVA开发包,从而为我们使用JAVA编程提供了相应的环境以及类库。到目前为止,Java已经发展到了Java V8版,并在不断完善之中。而本次实验使用的Android开发均要使用JDK作为基础的开发环境。
2.Android SDK
Android SDK是一个为Android开发的软件包,它包含了调试器、API函数库、安卓模拟器以及一系列开发文档在内的各种工具。谷歌官方开发出了基于Eclipse的ADT(Android Develop Tools)插件,通过为Eclipse安装插件的方式支持Android的开发,目前官方已经停止ADT插件的开发与维护工作,并开发出了更加强大以及好用的Android Studio软件。本次实验则使用JDK+Android Studio的组合来开发Android APP。
3.AVD(Android Virtual Devices)
AVD就是运行于电脑上的安卓虚拟器,它可以使我们在没有手机的情况下通过电脑测试数据。
这与我们真实运行手机的情况非常相近。这样我们就可以非常方便的在电脑上调试程序。
4.Android 系统平台架构分析
Android 平台由Linux内核、中间件、应用程序平台和应用软件组成,其系统架构如下图所示:
从图中我们可以看到整个安卓系统由Linux核心层、库、安卓运行时、应用程序框架以及应用层构成。而我们一般开发APP都在应用层进行开发。
a) Linux操作系统和驱动(Linux kernel):
由C语言实现。 Android核心系统服务依赖于Linux2.6内核,包括:安全性、内存管理、进程管理、网络协议、驱动模型。Linux内核也作为硬件和软件栈之间的抽象层。除了标准的Linux内核外,Android还增加了内核的驱动程序:Binder(IPC)驱动、显示驱动、输入设备驱动、音频系统驱动、摄像头驱动、WiFi驱动、蓝牙驱动、电源管理。
b) 程序库 (LIBRARIES)
程序库是指可供使用的各种标准程序、子程序、文件以及它们的目录等信息的有序集合,Android包含一些C/C++库,Android系统中不同的组件通过应用程序框架可以使用这些库本地框架是有C/C++实现。包含C/C++库,被Android系统中不同组件使用,它们通过Android应用程序框架为开发者进行服务。
c) Java运行环境(ANDROIDRUNTIME)
Android运行库包括两部分:一是核心库,二是自身的Dalvik虚拟机。
核心库提供Java编程语言核心库的大多数功能。
Dalvik虚拟机是Google专为Android开发的 。每一个Android应用程序都在自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。
d) Android应用框架(ANDROIDFRAMEWORK)
应用程序框架是指定义了一个应用程序运行所必须的全部功能组件,开发者也可以访问核心应用程序所使用的API框架。在Android系统中,开发人员也可以完全访问核心应用程序所使用的API框架。
e) Android应用程序(APPLICATIONS)
Android应用程序都是有Java语言编写的。用户开发的Android应用程序和Android的核心应用程序是同一层次的,它们都是基于Android的系统API构建的。
(二)第二次实验
我们将进行基于Android系统的APP开发实验。而本次实验则是关于手机传感器的应用——加速传感器小程序。下面我们首先介绍一下各个传感器。
1.Android的三大类传感器
Android传感器按大方向划分大致有这么三类传感器:动作(Motion)传感器、环境(Environmental)传感器、位置(Position)传感器。
(1)动作传感器
这类传感器在三个轴(x、y、z)上测量加速度和旋转角度。包括如下几个传感器:
加速(accelerometer)传感器、重力(gravity)传感器、陀螺仪(gyroscope)传感器、旋转向量(rotational vector )传感器。
(2)环境传感器
这类传感器可以测量不同环境的参数,例如,周围环境的空气温度和压强、光照强度和湿度。包括如下几个传感器:
湿度(barometer)传感器、光线(photometer)传感器、温度(thermometer)传感器
(3)位置传感器
这类传感器可以测量设备的物理位置。包括如下几个传感器:
方向(orientation)传感器、磁力(magnetometer)传感器
了解后我们就开始进入传感器的编程工作了,接下来我们看一下Android为我们提供的传感器框架(Android sensor framework,简称ASF)。
2.Android传感器框架
Android SDK为我们提供了ASF,可以用来访问当前Android设备内置的传感器。ASF提供了很多类和接口,帮助我们完成各种与传感器有关的任务。例如:
1)确定当前Android设备内置了哪些传感器。
2)确定某一个传感器的技术指标。
3)获取传感器传回来的数据,以及定义传感器回传数据的精度。
4)注册和注销传感器事件监听器,这些监听器用于监听传感器的变化,通常从传感器回传的数据需要利用这些监听器完成。
ASF允许我们访问很多传感器类型,这些传感器有一些是基于硬件的传感器,还有一些是基于软件的传感器。基于硬件的传感器就是直接以芯片形式嵌入到Android设备中,这些传感器直接从外部环境获取数据。基于软件的传感器并不是实际的硬件芯片,基于软件的传感器传回的数据本质上也来自于基于硬件的传感器,只是这些数据通常会经过二次加工。所以基于软件的传感器也可以称为虚拟(virtual)传感器或合成(synthetic)传感器。
Android对每个设备的传感器都进行了抽象,其中SensorManger类用来控制传感器,Sensor用来描述具体的传感器,SensorEventListener用来监听传感器值的改变。
(1)SensorManager类
用于创建sensor service的实例。该类提供了很多用于访问和枚举传感器,注册和注销传感器监听器的方法。而且还提供了与传感器精度、扫描频率、校正有关的常量。
(2)Sensor类
Sensor类为我们提供了一些用于获取传感器技术参数的方法。如版本、类型、生产商等。例如所有传感器的TYPE类型如下:
序号 |
传感器 |
Sensor类中定义的TYPE常量 |
1 |
加速度传感器 |
TYPE_ACCELEROMETER |
2 |
温度传感器 |
TYPE_AMBIENT_TEMPERATURE |
3 |
陀螺仪传感器 |
TYPE_GYROSCOPE |
4 |
光线传感器 |
TYPE_LIGHT |
5 |
磁场传感器 |
TYPE_MAGNETIC_FIELD |
6 |
压力传感器 |
TYPE_PRESSURE |
7 |
临近传感器 |
TYPE_PROXIMITY |
8 |
湿度传感器 |
TYPE_RELATIVE_HUMIDITY |
9 |
方向传感器 |
TYPE_ORIENTATION |
10 |
重力传感器 |
TYPE_GRAVITY |
11 |
线性加速传感器 |
TYPE_LINEAR_ACCELERATION |
12 |
旋转向量传感器 |
TYPE_ROTATION_VECTOR |
注意:1-8是硬件传感器,9是软件传感器,其中方向传感器的数据来自重力和磁场传感器,10-12是硬件或软件传感器。
(3)SensorEvent类
系统使用该类创建传感器事件对象。该对象可以提供与传感器事件有关的信息。传感器事件对象包括的信息有原始的传感器回传数据、传感器类型、数据的精度以及触发事件的时间。
(4)SensorEventListener接口
该接口包含两个回调方法,当传感器的回传值或精度发生变化时,系统会调用这两个回调方法。
/** * 传感器精度变化时回调 */
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
/*** 传感器数据变化时回调*/
@Override
public void onSensorChanged(SensorEvent event) {
.
.
.
}
4.获取传感器技术参数
下来我们编写代码来获取一下自己手机的传感器技术参数。
TextView tvSensors = (TextView) findViewById(R.id.tv_sensors);
//获取传感器SensorManager对象
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor sensor : sensors) {
tvSensors.append(sensor.getName() + "\n");
}
(三)第三次实验
本次实验则是在上一次获取传感器数据的基础上实现屏幕绘图功能,和进一步完善数据的格式。
1.实时获取系统时间
1.获取系统时间的方法
2.通过DateFormat方式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");// HH:mm:ss
//获取当前时间
Date date = new Date(System.currentTimeMillis());
(2)第二种方法Calendar calendar = Calendar.getInstance();
(3)第三种方法Time t=new Time(); // or Time t=new Time("GMT+8"); 加上Time Zone资料
我选择通过SimpleDateFormat来获取系统的时间,但是存在一个问题,TextView的内容一旦设定好之后,就不会自动更新了,所以用一个线程,在线程里不断循环,线程每休眠1s,sendMessage给Handle,在handleMessage方法里更新UI线程即TextView的内容。
2.android如何在子线程中更新UI
android的UI更新不是线程安全的,换句话说就是不允许在子线程中进行UI的更新,如果想进行UI的更新,就必须在主线程中进行。
异步消息处理机制
Handler、Looper、Message都是与Android异步消息处理线程相关的概念。
异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。
1)Message
这个很容易理解,就是消息,他可以携带少量的消息,比如你在子线程中去更新UI,就将要更新的内容放到message中,然后将message发送到主线程中,由主线程去做更新UI的操作。也就是说,messge可以用于不同线程中进行数据交换4
2)Handler
这个就是处理者的意思。你可以在线程中调用Handler的sendMessage方法去发送消息,然后在主线程中,通过handleMessage去接受这个message消息,然后去处理。
3)MessageQueue
消息队列,Android主线程包含一个消息队列,它主要用于存放所有通过Handler发送的消息,可以是Message,也可以是Runnable。主线程在创建的时候会默认创建消息队列,子线程在创建的时候默认不会创建消息队列,但是可以手动创建。当在主线程创建一个Handler,这个Handler会自动绑定主线程以及主线程的消息队列。然后在子线程通过这个Handler发送消息的时候,这个消息就会被加入到主线程的消息队列了。
4)Looper
那么,通过Handler的sendMessage可以发送消息加入到主线程的消息队列中。那么,主线程在什么情况下,从消息队列中取出这些消息进行处理呢?就需要Looper了。Looper是每个线程中的消息队列的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,每当发现消息队列中有消息,就会取出来,然后传递到Handler的handleMessage()方法中。所以,我们只需要在主线程中完成handleMessage()方法的实现,剩下的就不需要你操心了,Looper会帮我们完成其他所有的事情的。
Looper和消息队列一样,主线程会自动创建,而且每个线程只有一个消息队列和一个Looper。
3.屏幕绘图功能
Android——Canvas类的使用
Canvas类(android.graphics.Canvas)
Canvas类就是表示一块画布,你可以在上面画你想画的东西。当然,你还可以设置画布的属性,如画布的颜色/尺寸等。Canvas提供了如下一些方法:
Canvas():创建一个空的画布,可以使用setBitmap()方法来设置绘制的具体画布;
Canvas(Bitmap bitmap):以bitmap对象创建一个画布,则将内容都绘制在bitmap上,bitmap不得为null;
Canvas(GL gl):在绘制3D效果时使用,与OpenGL有关;
drawColor:设置画布的背景色;
setBitmap:设置具体的画布;
clipRect:设置显示区域,即设置裁剪区;
isOpaque:检测是否支持透明;
rotate:旋转画布;
同时还要理解一个paint类,paint类拥有风格和颜色信息如何绘制几何学,文本和位图。
Paint 代表了Canvas上的画笔、画刷、颜料等等;
Paint类常用方法:
setARGB(int a, int r, int g, int b) // 设置 Paint对象颜色,参数一为alpha透明值
setAlpha(int a) // 设置alpha不透明度,范围为0~255
setAntiAlias(boolean aa) // 是否抗锯齿
setColor(int color) // 设置颜色,这里Android内部定义的有Color类包含了一些常见颜色定义
setTextScaleX(float scaleX) // 设置文本缩放倍数,1.0f为原始
setTextSize(float textSize) // 设置字体大小
setUnderlineText(booleanunderlineText) // 设置下划线
(四)第四次实验
1. 图表控件MPAndroidChart
一款在github上发布的,十分强大的图表框架。
2.添加第三方库
①直接搜索法
点击项目设置按钮
依次选择 App > Dependencies
依次选择 + > Library dependency
下图所表示的库和Gradle文件是对应的
点击GradleOK后,刷新,以及重新Build项目
②libs添加法
这里直接复制你的第三方jar包到目录app > lib下s ,如果没有libs就新建一个 首先点击Android ,切换到Project,重新Build项目
③Module添加法
新建了一个Module名称为 mylibrary,在App中调用这个类
然后我们开始添加Module,点击项目设置小按钮
app >Dependencies > + >3.Module dependency
选择Module,点击Build项目
④Gradle 直接添加法
找到build.gradle(Module:app),然后找到dependencies,
这里我们可以看到我们刚才添加的库,刚才那个项目设置是和这里是一一对应的。
我们这里以github上android 图表框架MPA为例,去到它的官网,我们可以看到它的请求网页:
compile 'com.github.PhilJay:MPAndroidChart:v3.0.2'
⑤添加.so链接库法
如果你的app需要集成百度地图之类的,一定有这样的so动态库。
复制lib下的所有文件,到Android Studio的app > libs下
然后找到build.gradle(Module:app) 文件,在android节点下添加如下内容
sourceSets {
main {
jniLibs.srcDirs =[]
}
}
然后build一下
或者直接创建一个jniLibs目录,路径为:app > src > main >jniLibs
(五)第五次实验
1. Android的数据存储方式
Android提供了5种方式存储数据:
--使用SharedPreferences存储数据;
--文件存储数据;
--SQLite数据库存储数据;
--使用ContentProvider存储数据;
--网络存储数据;
先说下,Preference,File, DataBase这三种方式分别对应的目录是/data/data/Package Name/Shared_Pref, /data/data/Package Name/files,/data/data/Package Name/database 。 在Android中通常使用File存储方式是用Context.openFileOutput(StringfileName, int mode)和Context.openFileInput(String fileName)。 Context.openFileOutput(String fileName, int mode)生成的文件自动存储在/data/data/PackageName/files目录下,其全路径是/data/data/PackageName/files/fileName 。注意下,这里的参数fileName不可以包含路径分割符(如"/")。
通常来说,这种方式生成的文件只能在这个apk内访问。但这个结论是指使用Context.openFileInput(StringfileName)的方式。使用这种方式,每个apk只可以访问自己的/data/data/Package Name/files目录下的文件,原因很简单,参数fileName中不可以包含路径分割符,Android会自动在/data/data/Package Name/files目录下寻找文件名为fileName的文件。
(1)使用SharedPreferences存储数据
首先说明SharedPreferences存储方式,它是Android提供的用来存储一些简单配置信息的一种机制,例如:登录用户的用户名与密码。其采用了Map数据结构来存储数据,以键值的方式存储,可以简单的读取与写入,具体实例如下:
void ReadSharedPreferences(){
String strName,strPassword;
SharedPreferences user =
getSharedPreferences(“user_info”,0);
strName = user.getString(“NAME”,””);
strPassword = user getString(“PASSWORD”,””);
}
void WriteSharedPreferences(String strName,String strPassword){
SharedPreferences user =
getSharedPreferences(“user_info”,0);
uer.edit();
user.putString(“NAME”, strName);
user.putString(“PASSWORD” ,strPassword);
user.commit();
}
数据读取与写入的方法都非常简单,只是在写入的时候有些区别:先调用edit()使其处于编辑状态,然后才能修改数据,最后使用commit()提交修改的数据。实际上SharedPreferences是采用了XML格式将数据存储到设备中,在DDMS中的File Explorer中的/data/data/<package
name>/shares_prefs下。以上面的数据存储结果为例,打开后可以看到一个user_info.xml的文件,打开后可以看到:
<?xml version=”1.0″ encoding=”UTF-8″?>
<map>
<string name=”NAME”>moandroid</string>
<string name=” PASSWORD”>SharedPreferences</string>
</map>
使用SharedPreferences是有些限制的:只能在同一个包内使用,不能在不同的包之间使用。
(2)文件存储数据
文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。FilterInputStream, FilterOutputStream等可以到Java io package说明中去详细学习,不再此详细说明,具体实例如下:
String fn = “moandroid.log”;
FileInputStream fis = openFileInput(fn);
FileOutputStream fos = openFileOutput(fn,Context.MODE_PRIVATE);
除此之外,Android还提供了其他函数来操作文件,详细说明请阅读Android SDK。
(3)网络存储数据
网络存储方式,需要与Android 网络数据包打交道,关于Android 网络数据包的详细说明,请阅读Android SDK引用了Java SDK的哪些package。
(4)ContentProvider
ContentProvider简介
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。
Uri类简介
Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider ,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:
1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。
2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
² 要操作contact表中id为10的记录,可以构建这样的路径:/contact/10
- 要操作contact表中id为10的记录的name字段, contact/10/name
- 要操作contact表中的所有记录,可以构建这样的路径:/contact?
- 要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下:
要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri =Uri.parse("content://com.changcheng.provider.contactprovider/contact")
UriMatcher、ContentUrist和ContentResolver简介
因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。
UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路径全部给注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配
content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);//#号为通配符
2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。
ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
withAppendedId(uri, id)用于为路径加上ID部分
parseId(uri)方法用于从路径中获取ID部分
ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,来操作数据。
2. 文件存储
Android中内部存储,外部存储的概念
内部存储
概念:注意内部存储不是内存。内部存储位于系统中很特殊的一个位置,如果你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用所创建的所有文件都在和应用包名相同的目录下。也就是说应用创建于内部存储的文件,与这个应用是关联起来的。当一个应用卸载之后,内部存储中的这些文件也被删除。从技术上来讲如果你在创建内部存储文件的时候将文件属性设置成可读,其他app能够访问自己应用的数据,前提是他知道你这个应用的包名,如果一个文件的属性是私有(private),那么即使知道包名其他应用也无法访问。 内部存储空间十分有限,因而显得可贵,另外,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。所以对于内部存储空间,我们要尽量避免使用。Shared Preferences和SQLite数据库都是存储在内部存储空间上的。内部存储一般用Context来获取和操作。
访问内部存储的API方法:
1、Environment.getDataDirectory()
2、getFilesDir().getAbsolutePath()
3、getCacheDir().getAbsolutePath()
4、getDir(“myFile”,
MODE_PRIVATE).getAbsolutePath()
外部存储
概念:最容易混淆的是外部存储,因为老的Android系统的跟新的Android系统是有差别的,很多人去网上查找资料,看了一下以前的资料,又看了一下现在的资料,但是发现它们说法不一样然后就困惑了。首先说一个大家普遍的概念“如果在pc机上是区分外部存储和内部存储的话,那么电脑自带的硬盘算是内部存储,U盘或者移动硬盘就是外部存储了。”因此很多人带着这样的理解去看待安卓手机,把内置存储(机身存储)当做内部存储,而把扩展的SD卡当做是外部存储。这么认为确实没错,因为在4.4(API19)以前的手机上确实是这样的,手机自身带的存储卡就是内部存储,而扩展的SD卡就是外部存储。但是从4.4的系统开始,很多的中高端机器都将自己的机身存储扩展到了8G以上,比如有的人的手机是16G的,有的人的手机是32G的,但是这个16G,32G是内部存储吗,不是的!!!,它们依然是外部存储,也就是说4.4系统及以上的手机将机身存储存储(手机自身带的存储叫做机身存储)在概念上分成了”内部存储internal” 和”外部存储external” 两部分。
清除缓存和清除数据的区别:
清除缓存:我们知道应用程序在运行过程中需要经过很多过程,比如读入程序,计算,输入输出等等,这些过程中肯定会产生很多的数据,它们在内存中,以供程序运行时调用。所以清除缓存清除的是APP运行过程中所产生的临时数据。
清除数据:清除数据才是真正的删除了我们保存在文件中的数据(永久性数据,如果不人为删除的话会一直保存在文件中)例如当我们在设置里面清除了某个应用的数据,那么/data/user/0/packname//storage/emulated/0/Android/data/packname/下的文件里面的数据会全部删除,包括cache,files,lib,shared_prefs等等。
3. 对话框
对话框的几种实现方式:
- Activity
- Popwindow
- Dialog
- Fragment
关键类
- AlertDialog
- ProgressDialog
- DialogFragment
- Activity
特点介绍:
- Dialog 这类的实现google官方不推荐因为没有生命周期. 如果意外销毁会导致数据的丢失. 不过使用简单. 没什么特别的要求用这个
- DialogFragment 可以算的上是最佳实现. 如果对话框界面相对复杂的话可以用这个.
- Activity 自带渐变的过渡动画
- popwindow 可以附着到其他控件周围.
4.文件夹浏览
应用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的。
大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中。这样当该应用被卸载后,这些数据还保留在SDCard中,留下了垃圾数据。
如果你想让你的应用被卸载后,与该应用相关的数据也清除掉,该怎么办呢?
通过Context.getExternalFilesDir()方法可以获取到SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据通过Context.getExternalCacheDir()方法可以获取到SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
如果使用上面的方法,当你的应用在被用户卸载后,SDCard/Android/data/你的应用的包名/ 这个目录下的所有文件都会被删除,不会留下垃圾信息。
通过Context.getFilesDir()方法可以获取到/data/data/youPackageName/files这个目录,一般放一些短时间保存的数据,同样引用卸载后,这个目录下的数据也会删除,不会留下垃圾信息。
而且上面二个目录分别对应 设置->应用->应用详情里面的”清除数据“与”清除缓存“选项
总结一下android 中的几种目录:
一、 files
1.Context.getFilesDir(),该方法返回/data/data/youPackageName/files的File对象。
2. Context.openFileInput()与Context.openFileOutput(),只能读取和写入files下的文件,返回的是FileInputStream和FileOutputStream对象。
3. Context.fileList(),返回files下所有的文件名,返回的是String[]对象。
4. Context.deleteFile(String),删除files下指定名称的文件。
5. Context.getExternalFilesDir()方法可以获取到
SDCard/Android/data/youPackageName/files/ 目录,一般放一些长时间保存的数据
二、cache
1.Context.getCacheDir(),该方法返回 /data/data/youPackageName/cache的File对象,这个文件里面的数据在设备内存不足的时候,会被系统删除数据。注意:你不能依赖系统帮你删除这些文件,当这个文件夹里面的数据超过1MB的时候,系统会删除这个文件夹里面的数据。
2. Context.getExternalCacheDir()方法可以获取SDCard/Android/data/youPackageName/cache/目录,一般存放临时缓存数据。
三、custom dir
getDir(Stringname, int mode),返回 /data/data/youPackageName/ 下的指定名称的文件夹File对象,如果该文件夹不存在则用指定名称创建一个新的文件夹。
创建文件的权限
MODE_PRIVATE:说明该文件只能被当前的应用程序所读写;
MODE_APPEND:以追加方式打开该文件,应用程序可以向该文件中追加内容;
MODE_WORLD_READABLE:该文件的内容可以被其他的应用程序所读取;
MODE_WORLD_WRITEABLE:该文件的内容可以被其他的应用程序所读、写;
5. 适配器的使用
概念
Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带。在常见的View(List View,Grid View)等地方都需要用到Adapter。如下图直观的表达了Data、Adapter、View三者的关系。
Android中所有的Adapter一览:
由图可以看到在Android中与Adapter有关的所有接口、类的完整层级图。在我们使用过程中可以根据自己的需求实现接口或者继承类进行一定的扩展。比较常用的有 Base Adapter,Impleader,Adapter,Counteradaptation等。
- BaseAdapter是一个抽象类,继承它需要实现较多的方法,所以也就具有较高的灵活性;
- ArrayAdapter支持泛型操作,最为简单,只能展示一行字。
- SimpleAdapter有最好的扩充性,可以自定义出各种效果。
- SimpleCursorAdapter可以适用于简单的纯文字型ListView,它需要Cursor的字段和UI的id对应起来。如需要实现更复杂的UI也可以重写其他方法。可以认为是SimpleAdapter对数据库的简单结合,可以方便地把数据库的内容以列表的形式展示出来。
列表的显示需要三个元素&