一.Android的体系结构:
最底层:经过裁剪的linux内核;
再往上是使用C、C++编写的一些类库,还有Android虚拟机(Dalvik VM--DVM);
再往上是应用框架层 (其中四个最重要)即Android提供的一些组件可以直接使用。
Activities --> 每个屏幕
Content Providers --> 内容提供保证不同应用程序之间的访问
Intent
Services
二.Android程序的运行过程:
*.java-->*.class-->*.dek
因为Dalvik虚拟机是基于寄存器实现的所以速度较快,而且专有*.dek文件减少了*.class文件上的冗余信息,只包含需要使用的信息,而且会把所有的*.class文件整合到一起;一个应用程序会产生一个*.apk文件,apk 文件的本质是一个zip包。
三.搭建Android的开发环境
Eclipse、JDK、下载Android-SDK、安装ADT插件(Android Development Tools);
当以上的应用都下载完成,首先配置JDK,其次在Eclipse上的help菜单进行安装ADT;当ADT安装完成后将SDk目录路径配到Eclipse中;当Eclipse菜单栏中出现机器人时说明配置成功;
四.使用Eclipse创建第一个Android项目
此时在一个Android项目中的目录结构如下:假设我们现在创建一个HelloAndroid的项目
以 HelloAndroid为例:
src:
|-- 模型层,使用java代码进行编写
|-- 控制层类似于javaweb中的servlet,进行activities的创建
gen:
|-- 包(在创建时自己设置)
|-- 有一个R.java文件(自动生成,不要修改)
Android2.3:
|-- Android提供的开发jar包
assets:
在英文中是资产的意思,表示是固定资源的引用;一般放置音频视频文件,但较少使用;
bin
res
是英文resource的缩写,表示资源;
|-- drawable-hdpi
|-- drawable-ldpi
|-- drawable-mdpi
|-- drawable-xhdpi --> 四个文件夹进行不同尺寸的图片的存放
layout:
|-- 使用*.xml文件进行布局信息的配置
values:
|-- strings.xml --> 对字符串进行配置
colors.xml--> 对颜色信息进行设置
|-- 使用*.xml文件进行各种信息的设置,例如:style、array...
-- AndroidManifest.xml 类似于javaweb中的web.xml文件是用来对所有的activity类进行配置的;
-- proguard-project.txt
-- project.properties
注意:在对以上的图片,values下的xml文件等信息进行命名是一律小写;
另外R.java文件中会自动生成所有命名的图片等资源性文件; 在*.xml文件中访问时通过 @Strings/app_name;在java程序中通过R.string.app_name进行访问
五.Activity类和Resources类
观察生成的Activity类:public class HelloAndroidActivity extends Activity {}
继承于Activity类:那我们Activity类的机构呢?
java.lang.Object
android.content.Context
android.content.ContextWrapper
android.view.ContextThemeWrapper
android.app.Activity
Activity类是Context类的子类,表示Activity的上下文;
这其中几个重要的方法:
|- public View findViewById(int id)
:根据android控件的id返回一个视图的对象
|- public final void setProgress(int progress)
:设置ProgressBar进度条的进度
|- public final void setSecondaryProgress(int secondaryProgress)
:设置第二进度条的进度
|- public Window getWindow()
:获得一个Window窗体的对象
|- public void setContentView(int layoutResID)
:在某个Activity类中对指定id的视图进行设置
|- public void setContentView(View view)
:在某个Activity类中对指定试图对象进行设置
|- public void finish()
:关闭该Activity类的对象
|- public Intent getIntent()
:获得Intent的对象
|- public final CharSequence getTitle()
:获得该Activity类对象的标题
|- public void setTitle(CharSequence title)
:设置标题
|- public void setTitle(int titleId)
:设置标题
|- public void setVisible(boolean visible)
:设置整个屏幕是否可见
|- public void startActivity(Intent intent)
:通过Intent对象启动一个新的activity
|- public void startActivityForResult(Intent intent,int requestCode)
:根据传入的Intent对象和请求编号获取返回的值
|- public Resources getResources()
:返回一个资源文件的对象
|- public final boolean requestWindowFeature(int featureId)
:改变窗体的特征;featureId是具体的常量字段
|- protected void onActivityResult (int requestCode, int resultCode, Intent data)
:用于在回传的时候接受回传的值并进行处理
|- public final void setResult(int resultCode,Intent data)
:设置回传的结果
|- public void registerForContextMenu (View view)
:将一个上下文菜单绑定到视图上
|- public MenuInflater getMenuInflater ()
:得到一个MenuInflater的对象
所有资源文件是Resources类的对象:
Android开发包中提供了几个方法便于在java程序中调用:
|- public int getColor(int id) throws Resources.NotFoundException
:获得id所对应的的颜色
|- public float getDimension(int id) throws Resources.NotFoundException
:获得id所得应的尺寸
|- public Drawable getDrawable(int id) throws Resources.NotFoundException
:根据id返回一个图片的对象
|- public int getInteger(int id) throws Resources.NotFoundException
:根据id返回一个整数
|- public int[] getIntArray(int id) throws Resources.NotFoundException
:根据id返回一个整型数组
|- public XmlResourceParser getLayout(int id) throws Resources.NotFoundException
:返回一个布局对象
|- public String getString(int id) throws Resources.NotFoundException
:根据id返回一个字符串
|- public String[] getStringArray(int id) throws Resources.NotFoundException
:根据id返回一个字符串对象
六.简单介绍资源文件和权限Manifest.permission
所谓的资源文件就是讲一些相同类别的属性整合到一起;
例如:strings.xml文件中所存放的都是字符串等等
好处:便于国际化,清晰一目了然;
那么都有哪些常用的资源型文件呢?
|- drawable-hdpi
|- drawable-ldpi
|- drawable-mdpi
|- drawable-xhdpi -- 存放图片资源
|- layout(文件夹)
|-- main.xml -- 布局文件
|- values(文件夹)
|-- strings.xml -- 字符串文件
|-- colors.xml -- 颜色文件
|-- styles.xml -- 类型文件
|-- arrays.xml -- 数组文件
|- demens.xml -- 尺寸文件
|- theme.xml -- 主题文件其实就是整个屏幕的风格就是类型文件的一种
主题文件:<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="sharpTheme">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">?android:windowNoTitle</item>
</style>
</resources>
该主题的风格是将屏幕上的标题去掉;然后在需要的activity类中进行配置;
但是activity类中的方法setTheme()没有效果;
同样的也可以在java程序中实现以上功能:
requestWindowFeature(Window.FEATURE_NO_TITLE);
在类 Window已经定义了十七中窗体的风格;
设置全屏模式:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
Manifest.permission类是声明权限的类:
在android中诸如打电话、发短信之类的操作都需要经过权限声明:
例如:
<!-- 拨号权限 -->
<uses-permission android:name="android.permission.CALL_PHONE"/>
<!-- 发送信息权限 -->
<uses-permission android:name="android.permission.SEND_SMS"/>
七.Intent类(机器人邮递员)
Intent类是不同activity类之间进行联系的桥梁相当于request,此类的结构如下:
public class Intent extends Object implements Parcelable
其中的重要方法如下:一系列的putExtra()和getExtra()
|- 构造方法:
|-- public Intent()
:声明一个邮递员的对象
|-- public Intent(String action)
:根据传入的动作生成一个邮递员;比如说浏览网页,打电话等;
|-- public Intent(String action,Uri uri)
:根据动作和地址生成一个邮递员;
|-- public Intent(Context packageContext,Class<?> cls)
:生成一个确定往返地址的邮递员
|-- public Intent(String action,Uri uri,Context packageContext,Class<?> cls)
:根据指定动作往返的地址生成一个邮递员
|- 普通方法:
|-- public Intent setClass(Context packageContext,Class<?> cls)
:生成一个往返确定的邮递员
|-- public Intent addCategory(String category)
:对某个邮递员增加一个确定的种类;category是常量属性
|-- public Intent addFlags(int flags)
:对某个邮递员增加一个标志;flag是常量属性
|-- public Intent setAction(String action)
:给某个邮递员设置动作
|-- public String getAction()
:获得某个邮递员绑定的动作
|-- public Intent setData(Uri data)
:设置地址
|-- public Uri getData()
:获得某个邮递员去处的地址
|-- public int getFlags()
:获得邮递员绑定的标志
|-- public Bundle getExtras()
:返回一个Bundle的对象
|-- public Intent putExtra(String name,Bundle value)
:在该邮递员身上存放一个键值对
|-- public Intent setComponent(ComponentName component)
:根据传入的ComponentName对象生成一个邮递员
在实际开发中使用Intent类进行传值分为两种:
|- 隐式传值(即往返页面不确定)一种:
所谓的隐式传值实际上时过滤器的使用;
其实启动我们的android项目实际上就是一种过滤器的使用,当我们的项目启动时会发出一个过滤器:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
声明了邮递员的动作和种类,只有完全匹配的Activity类才能最先开始实例化,当匹配完成后该Activity类
通过onCreate()进行实例化; 当我们进行隐式传值的时候动作和种类必须写全否则报错;
如果没有种类则使用缺省的:Intent.CATEGORY_DEFAULT
|- 显示传值(即往返页面是确定的)三种:
|-- Intent intent = new Intent(Activity.this,OtherActivity.class);
|-- Intent intent = new Intent();
intent.setClass(Activity.this,OtherActivity.class);
|-- Intent intent = new Intent();
intent.setComponent(new ComponentName(Activity.this,OtherActivity.class));
在显示传值中有一个特殊传值方式:回传
该方式的流程:假设现在有两个Activity:FirstActivity、SecondActivity类
|- 通过方法:startActivityForResult(Intent intent,int requestCode)启动SecondActivity
|- 在SecondActivity中获得该Intent的对象,并绑定键值对;
|- 通过setResult(int resultCode,Intent intent)重新启动FirstActivity
|- 关闭SecondActivity类
|- 在FirstActivity类中通过重写的OnActivityResult(int requestCode,int resultCode,Intent intent)
获取回传的值并进行其他操作;
说明:requestCode:请求码,保证请求的唯一性,由用户自定义
resultCode:结果码,判定回传是否成功,由系统定义
|- public static final int RESULT_CANCELED -- 0 表示失败
|- public static final int RESULT_FIRST_USER -- 1 通过用户自定义的值进行启动
|- public static final int RESULT_OK -- -1 表示成功
特殊之处:
|- 启动方法不同;startActivity(Intent intent) -- startActivityForResult(Intent intent,int requestCode)
|- 跳转之后,在SecondActivity类中回传的启动方法也不同;
startActivity(Intent intent)-- setResult(int resultCode,Intent intent)
|- 需要重写方法对回传的值进行获取并处理;onActivityResult(int requestCode,int resultCode,Intent intent)
|- 当进行回传操作的时候,需要关闭SecondActivity页面
八.地址类Uri,打电话、发邮件
Uri:
该类的继承结构如右:public abstract class Uri extends Object implements Parcelable, Comparable<Uri>
在该类中有几个重要的方法:
|- public int compareTo(Uri other)
:与另一个Uri对象进行比较
|- public static Uri fromFile(File file)
:利用文件对象创建一个地址
|- public static Uri parse(String uriString)
:将从字符串中解析一个Uri对象
在进行以下操作时别忘记在配置文件配置权限
打电话:
方法一:String phone = 546564565;
Uri uri = Uri.parse("tel"+phone);
Intent intent = new Intent(Intent.ACTION_CALL);
startActivity(intent);
方法二:String phone = 546564565;
Intent intent = new Intent(Intent.ACTION_CALL,Uri.parse("tel"+phone));
startActivity(intent);
方法三:String phone = 546564565;
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel"+phone));
startActivity(intent);
九.Activity生命周期
onStart ()
onCreate()
onStart()
onResume()
onRestart()
onPause()
onStop()
onDestroy()
在以上的Activity生命周期中同样是从实例化到销毁;
注释:(1)在当前Activity正在运行的时候,有另一个Activity类要运行,则当前Activity被中断
(2)在当前的Activity完全被遮盖的时候,Activity进入停止状态
(3)如果当前Activity又回到了屏幕的最前面,则重新与用户进行交互
(4)如果当前Activity又回到了屏幕的最前面,通过调用方法重新与用户进行交互
说明:当一个Activity正常显示在屏幕的最前面的时候,经历了三个方法:onCreate()、onStart()、onResume()
十.Android基本控件
TextView
该类的继承结构:java.lang.Object
android.view.View
android.widget.TextView
在该类中定义了一些如下的属性及其相对应的方法;
NO. xml属性 说明
1 android:autoLink 将符合指定格式的文本转换为可单击的超链接形式
2 android:cursorVisible 设置该文本框的光标是否可见(在EditText中使用)
3 android:drawableButtom 在文本框的底部插入图片
4 android:drawableLeft 在文本框的左部插入图片
5 android:drawableRight 在文本框的又部插入图片
6 android:drawableTop 在文本框的顶部插入图片
7 android:drawablePadding 在文本框的内边距插入图片
8 android:ellipsize 设置在文本内容超过TextView长度时如何处理文本
9 android:gravity 设置文本框内文本的对齐方式
10 android:height 设置文本框的高度
11 android:hint 设置当控件中的内容为空时默认显示的内容(在EditText中使用)
12 android:minHeight 设置文本控件的最小高度
13 android:maxHeight 设置最大高度
14 android:minWidth 设置最小宽度
15 android:maxWidth 设置最大宽度
16 android:scrollHorizontally 设置当该文本框不够显示全部内容时是否允许水平滚动
17 android:selectAllOnFocus 如果文本框的内容可选择,设置当他获得焦点的时候是否自动选中所有文本
18 android:shadowColor 设置文本框内文本的阴影颜色
19 android:shadowDx 设置文本框内文本的阴影在水平方向进行偏移
20 android:shadowDy 设置文本框内文本的阴影在垂直方向进行偏移
21 android:shadowRadius 设置文本框内文本的阴影的角度
22 android:text 设置文本框的内容
23 android:textColor 设置文本框内容的颜色
24 android:textColorHighlight 设置文本框内文本被选中时的颜色(在EditText中使用)
25 android:textScaleX 设置文本框内文本在水平方向上的缩放因子
26 android:textSize 设置文本框内文本的尺寸
27 android:textStyle 设置文本框内文本的字体的风格,如:斜体等
28 android:typeface 设置文本框内文本的字体
29 android:width 设置文本的宽度
30 android:android:inputType 设置文本类型(在EditText中使用)
EditText
该类的继承结构:java.lang.Object
android.view.View
android.widget.TextView
android.widget.EditText
NO. xml属性 说明
1 android:cursorVisible 设置该文本框的光标是否可见
2 android:hint 设置当控件中的内容为空时默认显示的内容
3 android:textColorHint 设置默认字体的颜色
3 android:textColorHighlight 设置文本框内文本被选中时的颜色
4 android:capitalize = "characters"//以大写字母写
5 android:textAlign="center"//EditText没有这个属性,但TextView有,居中
6 android:textAppearance="?android:attr/textAppearanceLargeInverse"//文字外观
7 android:autoText 如果设置,将自动执行输入值的拼写纠正
8 android:digits 设置允许输入哪些字符。如“1234567890.+-*/)”
9 android:lineSpacingExtra 设置行间距。
十一.菜单选项
所谓的菜单选项是当点击手机自带的Menu所出现的子菜单栏;
Android SDK提供的菜单有如下几种:
1. 选项菜单:即MenuItem,是最常规的菜单,android把它叫做option menu;
2. 子菜单:即SubMenu,SubMenu的子菜单不支持嵌套;
3. 上下文菜单:即ContextMenu,长按视图控件出现的菜单;
4. 扩展菜单:选项菜单最多只能显示6个菜单项,超过6个时,第6个菜单项会被系统替换
为一个叫“更多”的子菜单,原来显示不下的菜单项都作为“更多”菜单的子菜单项。
5. 图标菜单:就是带图标的菜单;需要注意的是子菜单项、上下文菜单项、扩展菜单项均无法显示图标。
6. 选择菜单:用的较少,暂不介绍;
Menu -- public interface Menu
在该接口中有几个重要的方法:
|- public MenuItem add(int groupId,int itemId,int order,int titleRes)创建一个菜单 -- 引用strings的资源文件
|- public MenuItem add(int groupId,int itemId,int order,CharSequence title)创建一个菜单 -- 直接写字符串
|- public MenuItem getItem(int index)根据id号返回一个子菜单项
|- public int size()返回总共的菜单的个数
|- public SubMenu addSubMenu(int groupId,int itemId,int order,CharSequence title)生成一个指定的子菜单对象
|- public SubMenu addSubMenu(int groupId,int itemId,int order,int titleRes)生成一个指定的子菜单
|- public void removeGroup(int groupId)删除组
|- public void setGroupVisible(int group,boolean visible)设置组可见
MenuItem -- public interface MenuItem
在该接口中有几个重要的方法:
|- public int getGroupId()获得所在组的编号
|- public Drawable getIcon()返回在该菜单的图片
|- public int getItemId()返回菜单项的id号
|- public int getOrder()返回该菜单项的排序号
|- public MenuItem setTitle(int title)设置名称
|- public CharSequence getTitle()返回该菜单的名字
|- public SubMenu getSubMenu()返回一个子菜单的对象
|- public boolean isChecked()判断是否选中
|- public boolean hasSubMenu()判断是否有子菜单
|- public abstract MenuItem setOnMenuItemClickListener (MenuItem.OnMenuItemClickListener
menuItemClickListener) 进行MenuItem的点击事件
SubMenu -- public interface SubMenu extends Menu
在该接口中有几个重要的方法:
|- public MenuItem getItem()返回一个菜单项的对象
|- public SubMenu setIcon(Drawable icon)设置图片
|- public SubMenu setIcon(int iconRes)这是资源图片
ContextMenu -- public interface ContextMenu extends Menu
该接口中有几个方法:
|- public ContextMenu setHeaderIcon(Drawable icon)设置图标
|- public ContextMenu setHeaderIcon(int iconRes)设置图标资源
|- public ContextMenu setHeaderTitle(CharSequence title)设置标题
|- public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) 创建上下文菜单中的内容
在实际中进行上下文菜单创建时分两步走:
|- 首先通过registerForContextMenu(View view)绑定到视图上
|- 重写onCreateContextMenu()进行显示内容的设置
//一.创建菜单项即MenuItem -- 注意:菜单项不能再嵌套菜单,他的主要功能是操作
MenuItem file = menu.add(groupId_1, 0, 0, "菜单项1");
//二.创建子菜单
SubMenu subfile = menu.addSubMenu(groupId_2, 0, 0, "子菜单1");
MenuInflater inflater = this.getMenuInflater();
inflater.inflate(R.menu.menu, subfile);
return super.onCreateOptionsMenu(menu);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, -- 创建上下文菜单
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
//为上下文菜单设置标题
menu.setHeaderTitle("上下问菜单的操作菜单:");
//用资源填充上下文菜单亦或 menu.add();
MenuInflater inflater = this.getMenuInflater(); -- 使用资源文件进行填充菜单内容
inflater.inflate(R.menu.context_menu, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) { -- 子菜单的点击事件
// TODO Auto-generated method stub
if(item.getItemId() == R.id.city1){
Toast.makeText(this, "**********", 0).show();
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onContextItemSelected(MenuItem item) { -- 上下文菜单的点击事件
// TODO Auto-generated method stub
if(item.getItemId() == R.id.context_1){
Toast.makeText(this, "上下文菜单", 0).show();
}
return super.onContextItemSelected(item);
}
}
通过以上的代码,就以上的三个具体的菜单而言,子菜单和上下文菜单会在开发中使用,而MenuItem则是
作为对菜单的操作而存在的;
十二.单选按钮--RadioGroup、RadioButton和复选框--CheckBox
在HTML中的单选是将相同类型的控件,设置为相同的名字,这表示控件在一个组中,所以能达到单选的效果;
因此RadioGroup就是这么一个效果;
RadioGroup
该类的继承结构如下:java.lang.Object
android.view.View
android.view.ViewGroup
android.widget.LinearLayout
android.widget.RadioGroup
在该类中有几个重要的方法:
|- public void check(int id)设置默认选中的项
|- public void clearCheck()清空默认选中
|- public int getCheckedRadioButtonId()获得被选中的按钮的id
|- public void setOnCheckedChangeListener(RadioGroup.OnCheckedChangeListener listener)在进行单选按钮点击事件时使用
RadioButton:
该类的继承结构如下:java.lang.Object
android.view.View
android.widget.TextView
android.widget.Button
android.widget.CompoundButton
android.widget.RadioButton
CheckBook:
该类的继承结构如下:java.lang.Object
android.view.View
android.widget.TextView
android.widget.Button
android.widget.CompoundButton
android.widget.CheckBox
以上两个类具有相同的继承结构且本身并无任何方法(除了构造方法)
因此都是继承于父类CompoundButton有几个重要的方法:
|- public boolean isChecked()判断该按钮是否被选中
|- public void setButtonDrawable(int resid)设置按钮的图片
|- public void setChecked(boolean checked)将该按钮设置为选中状态
|- public void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener listener)对该按钮进行监听操作
十三.显示--ListView和适配器SimpleAdapter
ListActivity
该类的继承结构如下:java.lang.Object
android.content.Context
android.content.ContextWrapper
android.view.ContextThemeWrapper
android.app.Activity
android.app.ListActivity
在该类中有几个重要的方法:
|- public ListView getListView()返回一个ListView的对象
|- public long getSelectedItemId()获得被选中项的id
|- public void setListAdapter(ListAdapter adapter)为自带的id号为android.R.id.list的ListView控件对象上设置适配器
|- protected void onListItemClick (ListView l, View v, int position, long id) 继承与父类的方法,点击事件时需要重写
ListView
该类的继承结构如下:java.lang.Object
android.view.View
android.view.ViewGroup
android.widget.AdapterView<ListAdapter>
android.widget.AbsListView
android.widget.ListView
在该类中有几个重要的方法:
|- public void clearChoices()清除选中
|- public ListAdapter getAdapter()获得ListAdapter的对象
|- public void setAdapter(ListAdapter adapter)对该ListView对象设置适配器
|- public boolean isItemChecked(int position)判断子项目是否被选中
进行监听操作,使用继承于父类的方法:
|- public void setOnItemClickListener(AdapterView.OnItemClickListener listener)对ListView控件进行点击触发的事件
|-- 此方法中的内部类重写的方法
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,int arg2, long arg3) {}
|- public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener)对ListView控件进行长按触发的事件
|-- 此方法中的内部类重写的方法
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,int arg2, long arg3) {}
参数说明:1. 从ListView的继承结构上可以看出AdapterView<?>是其父类
2. 在整个ListView控件中被点击的控件
3. 被点击的控件在List数组中的位置
4. The row id of the item that was clicked
SimpleAdapter
该类的继承结构如下:java.lang.Object
android.widget.BaseAdapter
android.widget.SimpleAdapter
该类中有一个重要的方法:
|- public SimpleAdapter(Context context, -- 表示在那个Activity上创建适配器的对象
List<? extends Map<String,?>> data, -- 引入一个数据源(存放书的信息)
int resource, -- 布局文件,即一个ListView中的布局
String[] from, -- 比如书:bookName、bookPrice
int[] to) -- 将以上书的信息映射到那两个控件上
:该方法用来搭配ListView控件来控制显示效果;
十四.下拉列表--Spinner和适配器ArrayAdapter
Spinner
该类的继承结构如下:java.lang.Object
android.view.View
android.view.ViewGroup
android.widget.AdapterView<SpinnerAdapter>
android.widget.AbsSpinner
android.widget.Spinner
在该类的父类中有一个重要的方法:
|- public void setAdapter(SpinnerAdapter adapter)使用适配器来构建下拉列表的内容
|- public void setPrompt(CharSequence prompt) 给该下拉列表的对象设置标题
|- public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener)点击下拉列表触发的事件
|- public T getItem(int position)获取传入位置的对象
|- public long getItemId(int position)获取传入位置的项的id
|- public int getPosition(T item)根据传入的项的对象获得其所处的位置
|- public void setDropDownViewResource(int resource)更改下拉列表的显示风格
|- public static ArrayAdapter<CharSequence> createFromResource(Context context,
int textArrayResId,
int textViewResId)
:在一个屏幕上创建一个指定显示的适配器显示下拉列表的内容;
ps:参数一:某个Activity类的对象
参数二:引入的数组文件的id
参数三:指定系统中的某个下拉列表的风格(android自带的)
十五.图片视图--ImageView、图片按钮--ImageButton、时间选择器--TimePicker、日期选择器--DatePicker(上)
ImageView
该类的继承结构如下:java.lang.Object
android.view.View
android.widget.ImageView
该类也是View的直接子类;
对该类进行操作的几个重要方法:
|- public void setMaxHeight (int maxHeight)
:设置图片的最大高度
|- public void setMaxWidth (int maxWidth)
:设置图片的最大宽度
|- public void setScaleType (ImageView.ScaleType scaleType)
:设置图片显示格式(如居中) -- 该格式由系统自带
|- public void setImageResource (int resId)
:使用从R.java中生成的图片的id设置图片
|- public void setLayoutParams (ViewGroup.LayoutParams params)
:设置图片在整个屏幕上的的布局
ps:public LinearLayout.LayoutParams(int width,int height)
ImageButton
该类的继承结构如下:java.lang.Object
android.view.View
android.widget.ImageView
android.widget.ImageButton
从以上继承结构可以得出:
|- ImageButton按钮与Button按钮无任何直接关系
|- ImageButton是ImageView的直接子类,是对ImageView的扩充
TimePicker
该类的继承结构如下:java.lang.Object
android.view.View
android.view.ViewGroup
android.widget.FrameLayout -- 帧布局
android.widget.TimePicker
对该类进行操作的几个重要的方法:
|- public boolean is24HourView ()
:判断是否是24小时制
|- public void setIs24HourView (Boolean is24HourView)
:将时间选择器设置为24小时制
|- public void setCurrentHour (Integer currentHour)
:设置小时
|- public void setCurrentMinute (Integer currentMinute)
:设置分
|- public Integer getCurrentHour()
:获得小时
|- public Integer getCurrentMinute()
:获得分
DatePicker
该类的继承结构如下:java.lang.Object
android.view.View
android.view.ViewGroup
android.widget.FrameLayout
android.widget.DatePicker
对该类进行操作的几个重要方法:
|- public int getYear ()
:获得年份
|- public int getMonth ()
:获得月份,ps:月份是从0开始的
|- public int getDayOfMonth ()
:获得天
|- public void updateDate (int year, int month, int dayOfMonth)
:更新年月日
|- public void init (int year,
int monthOfYear,
int dayOfMonth,
DatePicker.OnDateChangedListener onDateChangedListener)
:对日期进行监听操作
例子:
public class DatePickerActivity extends Activity {
private DatePicker date;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
date = (DatePicker)findViewById(R.id.date);
date.updateDate(2013, 03, 31);
date.init(date.getYear(), date.getMonth(), date.getDayOfMonth(),
new DatePicker.OnDateChangedListener(){
@Override
public void onDateChanged(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
Toast.makeText(DatePickerActivity.this, year+"-"+monthOfYear+"-"+dayOfMonth, 0).show();
}});
}
}
通过该方法对DatePicker进行监听;
十六.网格视图--GridView
GridView
该类的继承结构如下:java.lang.Object
android.view.View
android.view.ViewGroup
android.widget.AdapterView<ListAdapter>
android.widget.AbsListView
android.widget.GridView
对该类操作的一些重要方法:
|- public GridView(Context context)
:在该Context的对象上创建一个GridView对象
|- public void setStretchMode(int stretchMode)
:缩放模式 -- android:stretchMode="columnWidth"
|- public void setVerticalSpacing (int verticalSpacing)
:设置垂直间距 -- android:verticalSpacing="10dp"
|- public void setHorizontalSpacing (int horizontalSpacing)
:设置水平间距 -- android:horizontalSpacing="10dp"
|- public void setNumColumns (int numColumns)
:设置每列显示的个数,如果设为auto_fit则表示自动设置 -- android:numColumns="auto_fit"
|- public void setGravity (int gravity)
:设置对齐方式 -- android:gravity="center"
|- public void setSelection (int position)
:设置默认选中项
|- public void setAdapter (ListAdapter adapter)
:设置适配器
|- public long getItemIdAtPosition (int position)
:获得传入位置的项的id号
就使用步骤而言个人感觉GridView控件与ListView控件的使用步骤是差不多的:
|- 自己本身的布局文件
|- 创建各自控件上的布局文件
|- 利用适配器进行自己控件布局的显示内容
在开发中有两种方式:
方式一.使用SimpleAdapter适配器完成
例子1:
public class GridViewActivity extends Activity {
private SimpleAdapter adapter;
private GridView gridview;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(this.initAdapter());
gridview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
long title = gridview.getItemIdAtPosition(arg2);
GridViewActivity.this.setTitle("NO."+String.valueOf(title));
}
});
}
public SimpleAdapter initAdapter(){
ArrayList<HashMap<String,Integer>> data = new ArrayList<HashMap<String,Integer>>();
try {
Field img = R.drawable.class.getDeclaredField("ic_launcher");
for(int i=0;i<9;i++){
HashMap<String,Integer> map = new HashMap<String, Integer>();
map.put("image", img.getInt(R.drawable.class));
map.put("title", i);
data.add(map);
}
adapter = new SimpleAdapter(this,
data,
R.layout.griditem,
new String[]{"image","title"}, --#
new int[]{R.id.ItemImage,R.id.ItemText}); --#
} catch (Exception e) {
e.printStackTrace();
}
return adapter;
}
}
在以上的程序中使用了反射来进行适配器的创建;回顾一下以上方法的作用:
|- getDeclaredField(String name) -- 得到该类本身创建的指定属性名称的属性
|- getInt(Object obj) -- 返回该Field对象在该类的Class对象中的整型表示形式
注意:在实际开发中,用#标记的两行在显示的时候可能会有一点缺陷,此时可以将两个数组中内容的位置进行调换;
方式二.继承BaseAdapter适配器完成
例子2:
第一步:继承BaseAdapter类完成适配器的配置
public class GridViewByBaseAdapter extends BaseAdapter {
private Context context;
private int[] imgId;
public GridViewByBaseAdapter(Context context,int[] imgId){
this.context = context;
this.imgId = imgId;
}
@Override
public int getCount() { //返回传入的数组的长度
return this.imgId.length;
}
@Override
public Object getItem(int position) {
return this.imgId[position];
}
@Override
public long getItemId(int position) {
return this.imgId[position];
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView img = new ImageView(this.context);
img.setScaleType(ImageView.ScaleType.CENTER); // 居中显示
img.setImageResource(this.imgId[position]);
return img;
}
}
继承BaseAdapter类重写该类的五个方法:(继承于public interface Adapter)
|- public int getCount()
:返回数据源中数据的个数
|- public Object getItem(int position)
:返回传入位置的数据的对象
|- public long getItemId(int position)
:返回传入位置的数据的id值
|- public View getView(int position, View convertView, ViewGroup parent)
:得到指定视图
适配器完成之后只要在Activity类中进行调用就行;
十七.主线程子线程的桥梁--Handler
在java程序中是将主方法作为主线程的;
其实在android程序中一个最先出现的Activity就是一个主线程;
主要作用:(1) 安排消息或Runnable 在某个主线程中某个地方执行
(2) 安排一个动作在不同的线程中执行
(3)接受子线程发送的数据, 并用此数据配合主线程更新UI.
Handler -- public class Handler extends Object
该类的继承结构:java.lang.Object
android.os.Handler
在该类中有几个重要的方法:
|- public Handler(Handler.Callback callback)
:实例化一个Handler对象,并重写方法进行接受子线程传递的信息
|- public void handleMessage(Message msg)
:接受子线程传递的信息
|- public final boolean post(Runnable r)
:执行一个线程 -- 注意此子线程算不上一个真正的子线程,还是主线程执行的;
|- public final boolean postAtTime(Runnable r,long uptimeMillis)
:在指定的时间执行线程
|- public final boolean postDelayed(Runnable r,long delayMillis)
:延迟指定的时间执行线程
|- public final boolean sendMessage(Message msg)
:发送子线程传递的信息
|- public boolean sendMessageAtTime(Message msg,long uptimeMillis)
:在指定的时间发送子线程传递的信息
|- public final boolean sendMessageDelayed(Message msg,long delayMillis)
:延迟指定的时间发送子线程传递的信息
|- public final Message obtainMessage()
:得到一个信息的对象
|- public final void removeCallbacks(Runnable r)
:将某个子线程对象从队列中移除
所有放在post()中执行的线程都不是真正的新的线程;
例子:
public class HandlerActivity extends Activity {
private Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler.post(run);
setContentView(R.layout.main);
System.out.println("当前正在运行的线程的名称:"+Thread.currentThread().getName()+"--id:"+Thread.currentThread().getId());
}
Runnable run = new Runnable(){
@Override
public void run() {
System.out.println("当前正在运行的线程的名称:"+Thread.currentThread().getName()+"--id:"+Thread.currentThread().getId());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
在以上的程序中通过System.out输出的结果是:当前正在运行的线程的名称:main--id:1
当前正在运行的线程的名称:main--id:1
显而易见的就是这就是同一个线程;
注意:在主线程中不要执行耗时的操作,不然超时五秒或强制关闭;
十八.进度条--ProgressBar(结合线程)
ProgressBar
该类的继承结构如下:java.lang.Object
android.view.View
android.widget.ProgressBar
从以上的继承结构可以看出,ProgressBar与其他控件不同,它是View类的直接子类;
该类中较重要的方法:
|- public boolean isShown ()
:判断是否显示
|- public ProgressBar(Context context)
:在该屏幕上生成一个进度条的对象
|- public int getMax()
:得到进度条的最大值
|- public int getProgress()
:得到进度条现在的值
|- public void setProgressDrawable(Drawable d)、
:给进度条设置图片
|- public Drawable getProgressDrawable()
:得到进度条的图片
|- public int getSecondaryProgress() -- 第二进度条指的是该进度条上的第二进度
:得到第二进度条
|- public synchronized void setSecondaryProgress (int secondaryProgress)
:给进度条设置第二进度
|- public synchronized void setProgress (int progress)
:给进度条设置进度
|- public synchronized void setMax (int max)
:给进度条的对象设置最大的进度数
|- public void setVisibility(int v)
:给进度条设置可见度
ps:View.GONE -- 隐藏的不可见的
View.VISIBLE -- 可见的
例子:
public class ProgressBarThread extends Activity {
private ProgressBar progress;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.othermain);
btn = (Button)findViewById(R.id.on);
progress = (ProgressBar)findViewById(R.id.bar_thread);
btn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
progress.setVisibility(View.VISIBLE); -- 设置进度条可见
handler.post(run); -- 执行线程
}});
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
progress.setProgress(msg.arg1);
handler.post(run);
}};
Runnable run = new Runnable(){
int i = 0;
@Override
public void run() { -- 执行线程的主体方法进行i的加操作
i += 5;
Message message = handler.obtainMessage(); -- 获得一个信息的对象
message.arg1 = i; -- 将增加后的值赋给信息的属性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendMessage(message); -- 将信息发送出去
if(i==progress.getMax()){
handler.removeCallbacks(run); -- 将线程从队列里移除出去
}
}};
}
以上程序实现的是一个动态的进度条的效果;每秒钟进5;
十九.拖动条--SeekBar(结合线程)
SeekBar
该类的继承结构如下:java.lang.Object
android.view.View
android.widget.ProgressBar
android.widget.AbsSeekBar
android.widget.SeekBar
该类的点击事件的操作方法:
|- public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener l)
在对拖动条进行点击事件处理的时候: public static interface SeekBar.OnSeekBarChangeListener
并重写该接口中的三个方法:
|- public void onProgressChanged(SeekBar seekBar,int progress,boolean fromUser)
:在拖动条的进度改变时调用
|- public void onStartTrackingTouch(SeekBar seekBar)
:在开始拖动的时候触发
|- public void onStopTrackingTouch(SeekBar seekBar)
:在停止拖动的时候触发
以上程序展现的是一个自动前进的拖动条的效果;
十九.焦点事件、长按事件、键盘事件、触摸事件
焦点事件:setOnFocusChangeListener()
长按事件:setOnLongClickListener()
配合以下的方法进行更换手机桌面:
|- public void android.content.ContextWrapper.clearWallpaper() throws IOException
:清除手机屏幕的桌面
|- public Drawable getWallpaper()
:得到手机背景的图片
|- public void setWallpaper(Bitmap bitmap) throws IOException
:通过Bitmap设置桌面背景
|- public void setWallpaper(InputStream data) throws IOException
:通过字节输入流设置桌面背景
在以上程序中注意配置权限;<uses-permission android:name="android.permission.SET_WALLPAPER"/>
二十.事件处理小结
1. 单击事件:setOnClickListener()适用于Button、EditText、TextView
2. 单选钮的点击事件:setOnCheckedChangeListener()
3. 下拉列表的点击事件:setOnItemSelectedListener()
4. 监听时间变化:setOnTimeChangedListener()
5. 监听日期变化:init()
6. ListView的监听事件:setOnItemClickListener()、setOnItemLongClickListener()
7. GridView的点击事件:setOnItemClickListener()
8. 子菜单、菜单项的点击事件:onOptionsItemSelected()
9. 上下文菜单的点击事件:onContextItemSelected()
10. SeekBar的点击事件:setOnSeekBarChangeListener()
11. 焦点事件:setOnFocusChangeListener()
12. 长按事件:setOnLongClickListener()
13. 键盘事件:setOnKeyListener()
14. 触摸事件:setOnTouchListener()
二十一. Notification--系统消息提示
在整个消息的服务中,是以以下的顺序来进行消息的系统提示:
NotificationManager --> PendingIntent --> Notification --> 在后台弹出消息的提示
| |
| 由NotificationManager类对消息和意图的对象进行封装 |
-------------------------------------------------------------
NotificationManager -- public class NotificationManager extends Object
该类的继承结构如下:java.lang.Object
android.app.NotificationManager
在该类中有两个方法:
|- public void notify(int id, Notification notification)
:根据消息的请求码推迟消息
|- public void notify(int id, Notification notification)
:根据消息的请求码弹出消息
PendingIntent -- public final class PendingIntent extends Object implements Parcelable
该类的继承结构如下:java.lang.Object
android.app.PendingIntent
该类中的几个重要的方法:
|- public static PendingIntent getActivity(Context context,int requestCode,
Intent intent,int flags)
:通过指定的请求码和Intent对象和标志位获得Activity类的意图
|- public static PendingIntent getBroadcast(Context context,int requestCode,
Intent intent,int flags)
:通过指定的请求码和Intent对象和标志位获得广播类的意图
|- public static PendingIntent getService(Context context,int requestCode,
Intent intent,int flags)
:通过指定的请求码和Intent对象和标志位获得服务类的意图
Notification -- public class Notification extends Object implements Parcelable
该类的继承结构如下:java.lang.Object
android.app.Notification
在该类中有五个属性:
|- public int defaults
:在消息弹出的时候指定提示的方式
|- public static final int DEFAULT_LIGHTS
:系统默认的亮度
|- public static final int DEFAULT_SOUND
:系统默认的提示音
|- public static final int DEFAULT_VIBRATE
:系统默认的振动
|- public static final int DEFAULT_ALL
:使用默认的全部提示
在该类中的几个方法:
|- public Notification()
:声明一个消息的对象
|- public Notification(int icon,CharSequence tickerText,long when)
:根据指定的消息图标、消息的提示标题、显示的时间(一般System.currentTimeMillis())
|- public void setLatestEventInfo(Context context,CharSequence contentTitle,
CharSequence contentText,PendingIntent contentIntent)
:给消息设置消息的标题、消息的内容和意图的对象
//使用getSystemService(String name)获得系统层次的服务
NotificationManager noti = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
//通过指定的消息图标,消息提醒标题,消息发送时间生成一个消息的对象
Notification notification = new Notification(R.drawable.ic_launcher,"消息提醒", System.currentTimeMillis());
notification.defaults = notification.DEFAULT_SOUND;
//当点击信息时,就会向系统发出openintent意图
//由前向后参数:上下文对象、请求码、邮递员对象(在点击消息之后跳转)、
//标志位(系统自带Intent.FLAG_ACTIVITY_NEW_TASK表示新开一个Activity来显示消息的内容)
Intent intent = new Intent(NotificationActivity.this, OtherActivity.class);
intent.putExtra("message", message);
PendingIntent pintent = PendingIntent.getActivity(NotificationActivity.this, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK );
//param4:点击通知时,发出的意图
//由前向后参数:上下文对象、内容标题、消息内容、意图对象
notification.setLatestEventInfo(NotificationActivity.this, "想念", message, pintent);
//发送通知 param1:要发送通知码 param2:通知
//由前向后参数:该消息的请求码、消息的对象
noti.notify(0, notification);
}});
}
}
在以上的程序中,进行意图对象创建的时候参数Intent对象可以设置为空;
当标志位flag设置为Intent.FLAG_ACTIVITY_NEW_TASK时表示可以将消息的内容传到另外的Activity类显示;
二十一. openFileOutput()、openFileInput() -- 小型文件的读取
在Android中小型文件可以直接存储在手机中;
而这些存储操作使用的也是流;
这些文件默认保存在data/data/包名/files/文件名
如果该文件存在则覆盖,不存在则自动创建;
openFileOutput(String name, int mode)
第一个参数指的是文件名;
第二个参数用于指定操作模式,有四种模式,分别为:
|- Context.MODE_PRIVATE = 0
说明:默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容
会覆盖原文件的内容。
|- Context.MODE_APPEND = 32768
说明:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
|- Context.MODE_WORLD_READABLE = 1
说明:当前文件可以被其他应用读取。
|- Context.MODE_WORLD_WRITEABLE = 2
说明:当前文件可以被其他应用写入。
如果希望文件被其他应用读和写:
openFileOutput("gem.txt", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
Activity还提供了getCacheDir()和getFilesDir()方法:
getCacheDir() -- 用于获取/data/data/<package name>/cache目录 -- 缓存
getFilesDir() -- 用于获取/data/data/<package name>/files目录 -- 文件
二十二. SDCard -- 大文件存储
当进行大型文件的存储时,就要使用我们的sd卡;
在使用SDCard之前,需要进行权限的配置;
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
首先判断是否有sd卡(并且可以进行读写):
boolean flage = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
获取sd卡的目录:
File sdCardDir = Environment.getExternalStorageDirectory(); -- 获取sd卡路径
File sdCardDir = new File("/sdcard"); //获取SDCard目录
File saveFile = new File(sdCardDir, "hello.txt");
//等同于:
File saveFile = new File("/sdcard/hello.txt");
File saveFile = new File("/mnt/sdcard/hello.txt");
现在使用的默认的是/mnt/sdcard,使用方法获取而不绝对的指定;
二十三. SharedPreferences -- 配置参数数据的保存
Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。
使用SharedPreferences保存数据,其背后是用xml文件存放数据,
文件存放在/data/data/<package name>/shared_prefs目录
在实际应用中:如果相同文件名则覆盖,否则自动创建;
该文件的格式:<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="bgmusic">spring</string>
<string name="bgcolor">blue</string>
</map>
实际上就是一个map集合;
1. 同一应用
向xml文件中添加数据:
SharedPreferences share = getSharedPreferences("xyy", Context.MODE_PRIVATE);
Editor editor = share.edit();
editor.putString("bgmusic", content.getText().toString());
editor.putString("bgcolor", "blue");
editor.commit();//提交修改
注意:文件名不需要加后缀吗,因为默认就是xml文件;
从xml文件中取值:
SharedPreferences share = getSharedPreferences("xyy", Context.MODE_PRIVATE);
share.getString("bgmusic",""); -- 第二个参数表示不存在对应的value则返回该参数的值
注意:如果访问其他应用中的Preference,前提条件是:
该preference创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE权限。
2.不同应用
Context otherAppsContext = createPackageContext("com.gem.activity", Context.CONTEXT_IGNORE_SECURITY);
SharedPreferences shared = otherAppsContext.getSharedPreferences("uset", Context.MODE_WORLD_READABLE);
String bgcolor = sharedPreferences.getString("bgcolor", "");
也可以使用流直接读取:File xmlFile = new File("/data/data/<package name>/shared_prefs/uset.xml");
二十四. Xml解析--XMLPullParse
在Android中也自定义了xml文件的解析器;
在Android中解析xml文件使用XmlPullParser接口
此解析方式与Sax解析大同小异;
XmlPullParser -- public interface XmlPullParser
该接口中几个重要的字段:
|- public static final int START_DOCUMENT
:文档的开始
|- public static final int START_TAG
:标签的开始
|- public static final int END_TAG
:标签的结束
|- public static final int END_DOCUMENT
:文档的结束
该接口中的几个重要的方法:
|- public int getAttributeCount()
:得到该标签中属性的数量
|- public String getAttributeName(int index)
:返回所引处属性的名称
|- public String getAttributeValue(int index)
:返回索引处属性对应的value值
|- public int getEventType() throws XmlPullParserException
:返回事件的类型(整型)
|- public String getInputEncoding()
:得到输入流的编码
|- public String getName()
:得到标签的名称
|- public String nextText() throws XmlPullParserException,IOException
:假设现在的事件是START_TAG,如果它的下一个元素是文本元素,就返回文本元素的
的内容,如果该文本内容为空返回空;否则抛出异常;
|- public void setInput(InputStream inputStream,String inputEncoding) throws XmlPullParserException
:设置输入流的编码;
p".equals(parser.getName()) -- 这是正确可行的
但:parser.getName().equals("emp") -- 这是不可行的,错误的
二十五. JSON解析
JSON采用完全独立与语言平台的文本格式;使用JSON可以将对象中表示的一组数据转为字符串;
然后在各个应用程序之间传递字符串;
对于字符串,用户可以自己拼凑,也可以使用JSON里的操作类;
Android中集成了JSON,所以用户在使用时不需要导包;
JSON的操作类:
1. org.json.JSONObject -- JSON定义的基本单元 == {key : [数值1,数值2,...]}
2. org.json.JSONArray -- 代表有序的数值 == [数值1,数值2,...]
3. org.json.JSONStringer -- 可以快速和便捷的创建JSON文本
4. org.json.JSONTokener -- 负责从JSON中提取数据
5. org.json.JSONException -- JSON的异常类
但是在实际使用中还是较多的使用前两个;
二十六. 内嵌数据库--SQLite
Android集成了一个轻量级的数据库:SQLite;
此数据库只适用于与少量数据的存储,不适合大量数据的复杂操作;
且此数据库支持T-SQL语句;
说明:SQLite3支持 NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型。
虽然它支持的类型虽然只有五种,但实际上sqlite3也接受varchar(n)、char(n)、decimal(p,s)
等数据类型,只不过在运算或保存时会转成对应的五种数据类型
重温下基本的T-SQl语句:
查询语句:select * from 表名 where 条件子句 group by 分组字句 having ... order by 排序子句
如:select * from person order by id desc
select name from person group by name having count(*)>1
分页SQL与mysql类似,获取5条记录,跳过前面3条记录
如:select * from Account limit 5 offset 3
或者 select * from Account limit 3,5
插入语句:insert into 表名(字段列表) values(值列表)。
如: insert into person(name, age) values(‘tom’,3)
更新语句:update 表名 set 字段名=值 where 条件子句。
如:update person set name=‘tom‘ where id=10
删除语句:delete from 表名 where 条件子句。
如:delete from person where id=10
在android中当需要操作SQLite数据库的时候需要得到一个SQLiteOpenHelper对象,
而SQLiteOpenHelper是一个抽象类,用户需要继承这个类,并实现该类中的一些方法。
SQLiteOpenHelper -- public abstract class SQLiteOpenHelper extends Object
该类的继承结构:java.lang.Object
android.database.sqlite.SQLiteOpenHelper
继承SQLiteOpenHelper类重写两个方法:
|- public abstract void onCreate(SQLiteDatabase db)
:创建数据库 -- 该方法在调用3,4两个方法时进行调用
|- public abstract void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)
:更新数据库 -- 版本号进行更新时调用
|- public SQLiteDatabase getReadableDatabase()
:返回一个可读的SQLiteDatabase类的对象
|- public SQLiteDatabase getWritableDatabase()
:返回一个可写的SQLiteDatabase类的对象
如果说继承抽象类SQLiteOpenHelper是并实现其中的两个方法已完成对数据库和表的创建;
那么在对表的后续操作Android提供了一个名为SQLiteDatabase的类,该类封装了一些操作数据库的API,
使用该类可以完成对数据进行添加(Create)、查询(Retrieve)、更新(Update)和删除(Delete)操作
(这些操作简称为CRUD)。
SQLiteDataBase -- public class SQLiteDatabase extends SQLiteClosable
该类的继承结构:java.lang.Object
android.database.sqlite.SQLiteClosable
android.database.sqlite.SQLiteDatabase
在该类中有以下几个方法:
|- public void execSQL(String sql)throws SQLException
:执行sql语句
|- public boolean isReadOnly()
:判断数据库是否只读
|- public void execSQL(String sql, Object[] bindArgs)throws SQLException
:执行带有占位符的sql语句第二个参数表示占位符的数据
|- public Cursor rawQuery(String sql,String[] selectionArgs)
:执行带有占位符的查询语句,参数含义同上
|- public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,
String groupBy,String having,String orderBy)
:查询表返回一个游标的对象
|- public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,
String groupBy,String having,String orderBy,String limit)
:分页查询
|- public long insert(String table,String nullColumnHack,ContentValues values)
:在Android因为默认调用该方法必须插入一条记录,第二个参数的意思是当第三个参数为空或者元素
个数等于0时,插入第二个参数的值,但是一般来说不太可能,一般将第二个参数设置为null
|- public int delete(String table,String whereClause,String[] whereArgs)
:使用自带的方法进行删除数据
|- public int update(String table,ContentValues values,String whereClause,String[] whereArgs)
:更新数据
|- public void close ()
:关闭连接
范例:
在该类中几个方法:
|- public byte[] getBlob(int columnIndex)
:得到该列的字节数组
|- public String getString(int columnIndex)
:得到该列的字符串
|- public int getColumnIndex(String columnName)
:返回该字段名称的索引
|- public String getColumnName(int columnIndex)
:返回该索引处的字段名称
|- public int getInt(int columnIndex)
:返回该列的int型值
|- public float getFloat(int columnIndex)
:返回float
|- public double getDouble(int columnIndex)
:返回double
|- public boolean isAfterLast()
:判断是否是最后一个
|- public boolean moveToFirst()
:到第一个时
|- public boolean moveToNext()
:往下一个移动
使用dos命令进行数据库的操作:
首先要进行配置: 配置在环境变量
D:\eclipse-android\android_software密码:xwang@gemptc.com\android\android-sdk-windows\platform-tools;
D:\eclipse-android\android_software密码:xwang@gemptc.com\android\android-sdk-windows\tools;
第一步:adb shell
第二步:# cd data/data/com.xyy.sqlite/databases
第三步:# sqlite3 xyy.db
第四步:.help
第五步:.schema
之后就可以进行sql语句的使用;
注意:sql语句以分号结尾;
二十七. ContentProvider -- 数据共享机制
数据库在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据。
一个Content Provider类实现了一组标准的方法接口,从而能够让其他的应用保存或读取此ContentProvider
的各种数据类型。
通俗点来讲就是讲一个应用程序的数据库操作交由另外的应用程序来完成;
开发ContentProvider程序:
第一步:继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。
第二步:需要在AndroidManifest.xml使用<provider>对该ContentProvider进行配置;
<provider android:name=".PersonContentProvider"
android:authorities="cn.gem.provider.personprovider"/>
说明:但是在实际开发中,是很少将自己的数据共享给别的应用的;
开发之需要了解:知道有这么个方法就行;
重点是通过ContentProvider对系统提供的Provider进行操作;
那么在实际中如何操作呢?
下面通过获取联系人为例进行操作:
那么在进行操作之前需要配置权限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITER_CONTACTS" />
但是在实际开发中以上方法的操作步骤都是固定的,因此Android又提供了一个适配器类SimpleCursorAdapter类;
一个简单地对联系人进行上下文菜单的显示:
在以后对其他的应用程序进行访问时,都是通过地址类Uri进行访问ContentResolver类来进行查询;
Uri -- public abstract class Uri extends Object implements Parcelable, Comparable<Uri>
在该类中有以下几个重要的方法:
|- public static Uri parse(String uriString)
:解析字符串获得地址
|- public static Uri withAppendedPath(Uri baseUri,String pathSegment)
:在给定的uri地址上进行添加编号
例子:
Uri uri = Uri.parse("content://cn.gem.provider.personprovider/person")
Uri resultUri = ContentUris.withAppendedId(uri, 10);
//生成后的Uri为:content://cn.gem.provider.personprovider/person/10
ContentUris -- public class ContentUrisextends Object
该类用于获取Uri路径后面的ID部分,它有两个比较实用的方法:
|- public static Uri withAppendedId(Uri contentUri,long id)
:同上面的方法
|- public static long parseId(Uri contentUri)
:解析地址返回一个
例子:
Uri uri = Uri.parse("content://cn.gem.provider.personprovider/person/10")
long personid = ContentUris.parseId(uri);//获取的结果为:10
ContentResolver -- public abstract class ContentResolver extends Object
在该类中有以下几个方法:
|- public final Uri insert(Uri url,ContentValues values)
:对数据库增加数据
|- public final int delete(Uri url,String where,String[] selectionArgs)
:对数据库删除数据
|- public final int update(Uri uri,ContentValues values,String where,String[] selectionArgs)
:对数据库进行更新数据
|- public final Cursor query(Uri uri,String[] projection,String selection,
String[] selectionArgs,String sortOrder)
:对数据库进行查询数据
以上四个方法的第一个参数都是Uri的对象:
这些方法的第一个参数为Uri,代表要操作的是哪个ContentProvider和对其中的什么数据进行操作,
假设给定的是: Uri.parse("content://cn.gem.provider.personprovider/person/10"),
那么将会对主机名为cn.gem.provider.personprovider的ContentProvider进行操作,
操作的数据为person表中id为10的记录。
在实际操作中以下的操作是相似的:
使用ContentResolver对ContentProvider中的数据进行添加、删除、修改和查询操作:
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://cn.gem.provider.personprovider/person");
//添加一条记录
ContentValues values = new ContentValues();
values.put("name", "gem");
values.put("age", 25);
resolver.insert(uri, values);
//获取person表中所有记录
Cursor cursor = resolver.query(uri, null, null, null, "personid desc");
while(cursor.moveToNext()){
Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));
}
//把id为1的记录的name字段值更改新为lihao
ContentValues updateValues = new ContentValues();
updateValues.put("name", "lihao");
Uri updateIdUri = ContentUris.withAppendedId(uri, 2);
resolver.update(updateIdUri, updateValues, null, null);
//删除id为2的记录
Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);
resolver.delete(deleteIdUri, null, null);
二十八. 广播 -- BroadcastReceiver
概述:
广播被分为两种不同的类型:普通广播(Normal broadcasts)和有序广播(Ordered broadcasts)
两者之间的区别:
|- 普通广播之间是异步的,可以在同一时刻被所有接收者接收(逻辑上),消息传递的效率高;
缺点是:接收这不能将结果传递给下一个接收者,并且无法终止广播Intent的传播;
|- 有序广播是按照接受者声明的优先级别,被接收者依次接收广播
优先级别声明在intent-filter元素的android:priority属性中,数越大优先级越高;
取值范围:-1000到1000,亦或者调用IntentFilter类中的setPriority()设置;
有序广播可以终止,也可以传值给下一个接收者;
那么如何进行普通广播和有序广播的发送呢?
在Context类中有以下几个重要的方法:
|- public abstract void sendBroadcast(Intent intent)
:发送一个指定意图的广播
|- public abstract void sendOrderedBroadcast(Intent intent,String receiverPermission)
:发送一个有序广播
BroadcastReceiver -- public abstract class BroadcastReceiver extends Object
该类的继承结构如下:java.lang.Object
android.content.BroadcastReceiver
在该类中有一个重要的方法:
|- public abstract void onReceive(Context context,Intent intent)
:接收到广播之后需要做的事;
创建一个广播需要进行以下的步骤:
第一步:继承BroadcastReceiver类,重写onReceiver()
示例:
public class Broadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {}
}
第二步:订阅感兴趣的广播
第一种方式:使用代码进行订阅
public class BroadCastReceiverActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
Broadcast receiver = new Broadcast();
registerReceiver(receiver, filter);
}
}
第二种方式:
在AndroidManifest.xml文件中的<application>进行配置:
<receiver android:name=".Broadcast">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
根据发送者不同,广播可分为两种:
|- 系统发送:此种方式为系统发送,只需拦截,比如系统收发短信、删除增加应用等;
|- 自定义发送:此方式为用户自定义发送,只需拦截器的信息与自定义的信息一致;
在进行以上操作时切记要配置权限;
二十九. 后台服务 -- Service
在以上的广播中,继承BroadcastReceiver类重写onReceiver()但是在该方法的存活时间只有十秒,超过
十秒系统会认为无响应;因此该方法中不能执行耗时过长的操作;切记也不能使用线程,因为该方法的
执行时间只有十秒,线程还来不及执行完;
那么怎么通过广播进行别的耗时操作呢?
Android中提供类Service来执行耗时的操作,该类在后台执行;
Service服务又分为两种:无绑定、有绑定
Service -- public abstract class Service extends ContextWrapper implements ComponentCallbacks
该类的继承结构如下:java.lang.Object
android.content.Context
android.content.ContextWrapper
android.app.Service
那么如何创建Service服务呢?
第一步:继承Service类,并重写其中几个方法;
第二步:通过Intent对象启动服务
注意:服务的onCreate()只有在初始化的时候调用;服务一旦第一次启动之后,就不会调用onCreate()
但是服务本身又分两种:
|- 普通服务:调用者退出仍然执行
此种服务的实行步骤如下:onCreate()-->onStartCommand()-->onStart()-->onDestroy()
开始:调用Context类中的startService(Intent intent)
停止:调用Context类中的stopService(Intent intent)
|- 绑定服务:调用者退出服务随之停止
此种服务的实行步骤如下:onCreate()-->onBind()-->onUnbind()-->onDestroy()
开始:调用Context类中的bindService(Intent intent,ServiceConnection service,int flag)
停止:调用Context类中的unbindService(ServiceConnection service)