湖南某科技大学 安卓Android移动开发基础期中考试笔记
前言
建议大家把第三章的三个实战演练和本笔记的所有代码部分都在AS中手打一遍,手打的意思是看懂之后自己写出来,而不是照着抄。这不90分就到手了?
第一章 基础
- Android是一款基于Linux平台的开源操作系统,主要用于移动开发中。
- Android体系结构
一个实例:闹钟->通知管理器->多媒体框架->音频驱动
- 应用程序层(application)
应用程序层是一个核心应用程序的集合,所以安装在手机上的应用程序都在这一层。例如:系统自带的联系人程序、短信程序、下载的小游戏。- 应用程序框架层(application framework) Android SDK 和这一层有关
应用程序框架层主要提供构建应用程序时用到的各种API。例如:视图(View)、活动管理器(activity manager)、通知管理器(notification manager)。- 核心类库(libraries)
- 核心类库包含系统库和Android运行时库
- 系统库这一层主要通过c/c++来为Android系统提供主要的特性支持。例如:OpenGL/ES库提供类3D绘图的支持、Webkit库提供浏览器内核的支持。
- Android运行时库(android runtime)主要提供了一些核心库,能够允许开发者使用Java语言来编写Android程序。
- Linux内核(Linux Kernel) 驱动
Linux内核为Android设备的各种硬件提供了底层的驱动。例如:显示驱动、音频驱动。
- Android程序结构
- manifests
用于存放AndroidManifest.xml文件,整个项目的配置文件。注册四大组件、添加权限。<?xml version = "1.0" encoding="utf-8"?> <manifest xmls:android="http://schemas.anroid.com/apk/res/android" package="cn.itcast.myapplication" > <application android:allowBackup="true" //设置应用数据能够被备份或恢复。 android:icon="@mipmap/ic_launcher" //设置图标。 android:label="HelloWorld" //设置应用程序名 android:supportsRtl="true" //设置允许RTL(从右到左布局)。 android:theme="@style/AppTheme" > //设置主题。 <activity android:name=".MainActivity" > <intent-filter> <action anroid:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" </intent-filter> </activity> </application> </manifest>
- java
用于存放所有的Java代码。- res
- drawable
用于存放图片及XML文件- layout
存放布局文件- mipmap
用于存放应用程序图标- value
用于放置定义的字符串
- Gradle Scripts
存放项目相关文件
第二章 UI
- 线性布局
- android:orientation属性,有vertical和horizontal(默认)两个值
- android:layout_width和android:layout_heigh两个属性,有match_parent(继承父组件大小)、wrap_content(内容大小)两个值或者是数值。
- android:layout_weight(权重),值为数字,带引号。使用weight属性时,控件宽度不再由width决定,使用width一般设置为0dp。
- 相对布局
- 设置控件位置的属性
以下属性值为true或false
- android:layout_centerParent 设置当前控件位于父布局的中央位置
- android:layout_centerVertical 设置当前控件位于父布局垂直居中位置
- anroid:layout_centerHorizontal 设置当前控件位于父布局水平居中位置
- anroid:layout_alignParentTop 设置当前控件与父控件顶端对齐
- android:layout_alignParentBottom 设置当前控件与父控件底端对齐
- android:layout_alignParentLeft 设置当前控件与父控件左对齐
- android:layout_alignParentRight 设置当期控件与父控件右对齐
以下属性值为某控件的ID
- android:layout_above 设置当前控件位于某控件的上方
- android:layout_below 设置当前控件位于某控件的下方
- android:layout_toLeftOf 设置当前控件位于某控件的左边
- android:layout_toRightOf 设置当前控件位于某控件的右边
- android:layout_alignTop 设置当前控件与某控件顶端对齐
- android:layout_alignBottom 设置当前控件与某控件底端对齐
- android:layout_alignLeft 设置当前控件与某控件左对齐
- android:layout_alignRight 设置当前控件与某控件右对齐
- 设置某控件 间距的属性
某控件指的是?
- android:layout_marginTop 设置当前控件上边界与某控件的距离
- android:layout_marginBottom 设置当前控件下边界与某控件的距离
- android:layout_marginLeft 设置当前控件左边界与某控件的距离
- android:layout_marginRight 设置当前控件有边界与某控件的距离
- 设置布局内边距的属性
- android:paddingTop 设置布局顶部内边距的距离
- android:paddingBottom 设置布局底部内边距的距离
- android:paddingLeft 设置布局左边内边距的距离
- android:paddingRight 设置布局右边内边距的距离
- 表格布局
序号从0开始
TableLayout布局属性
- android:stretchColumns 设置某列被拉伸
- android:shrinkColumns 设置某列被收缩
- android:collapseColumns 设置某列被隐藏
TableLayout控件属性
- android:layout_column 设置该控件显示位置
- android:layout_span 设置该单元格占几列,默认为一列
- LogCat的使用
Log类日志输出六个级别(从低到高)
- Verbose Log.v(String, String)
- Debbug Log.d(String, String)
- Info Log.i(String, String)
- Warning Log.w(String, String)
- Error Log.e(String, String)
- Assert 没有对应的静态方法 级别最高
第三章 Activity
Activity的生命周期
- 生命周期状态
- 启动状态
- 运行状态
- 暂停状态
- 停止状态
- 销毁状态
- 生命周期方法
- onCreate()
activity创建时调用 - onStart()
activity即将可见时调用 - onResume()
activity获取焦点与用户开始交互时调用 - onPause()
activity被其他activity覆盖或锁屏时调用 - onDestroy()
activity被销毁时调用 - onRestart()
activity从停止状态再次启动时调用
Activity的启动模式
在AndroidManifest.xml中,通过标签的anroid:launchMode属性可以设置启动模式。
- standard模式
默认启动模式,每启动一个activity就会在栈顶创建一个新的实例,闹钟程序通常采用此方式 - singleTop模式
先判断启动的activity实例是否位于栈顶,如果位于栈顶则直接复用,浏览器的书签通常采用此模式 - singleTask模式
先检查栈中是否存在当前activity实例,如果存在,则直接使用,此实例之上的所有实例全部出栈 - singleInstance模式
启动一个新的任务栈来管理activity实例,无论从哪个任务栈中启动该activity,该实例在系统中只有一个。
Activity之间的跳转
- 显式意图
Intent intent = new Intent(this, Ativity02.class);
startActivity(intent);
- 隐式意图
MainActivity.java
Intent intent = new Intent();
intent.setAction("cn.itcast.START_ACTIVITY");
startActivity(intent);
AndroidManifest.xml
<activity android:name="cn.itcast.Activity02">
<intent-filter>
<action android:name="cn.itcast.START_ACTIVITY" />
<category android:name="anroid.intent.category.DEFAULT" />
</intent-filter>
</activity>
- 打开浏览器实现
MainActivity.java
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle bundle){
super.onCreate(bundle);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.main_button);
button.setOnClickListence(new View.OnClickListence(){
public void onClick(View v){
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
}
}
- 数据传递
MainActivity.java
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("username", "yuhaoWu");
startActivity(intent);
Activity2.java
Intent intent = getIntent();
string username = intent.getStringExtra("username")
- 数据回传
Activity1.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, Activity2.class);
startActivityForResult(intent,9527);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if(requestCode == 9527){
if(resultCode == 1){
String data = intent.getStringExtra("data");
System.out.println(data);
}
}
}
Activity2.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Intent intent = new Intent();
intent.putExtra("data","yuhaoWu");
setResult(1, intent);
}
Activity1打开Activity2,Activity2关闭后Activity1调用onActivityResult打印出ACtivity2回传的”yuhaoWu“
- intent.getSerializableExtra()方法
第四章 数据存储
Activity类实现了Context类,如果本章使用了Context类静态方法的语句不在Activity类里,则前面应加上“Context.”,如Context.openFileInput(filename)和Context.getSharedPreference(filename, mode)
数据存储方式
- 文件存储
提供了openFileInput()和openFileOutput()方法读取设备上的文件。可以存储大数据,如文本、图片、音频。 - SharedPreferences
用来存储一些简单的配置信息,采用XML格式将数据存储到数据库中如用户名、密码。 - SQLite数据库
支持SQL语法,利用很少的内存就有很好的性能,一般作为复杂信息的存储引擎,可以存储用户信息。 - ContentProvider
四大组件之一,主要用于应用程序之间的数据交换,它可以讲自己的数据共享给其他应用程序使用 - 网络存储
将数据存储到服务器上,通过网络提供的存储空间来存储信息
文件存储
- 内部存储
使用openFileInput(String filename, int mode)和openFileOutput(String filename)分别创建fileInputStream对象和fileOutputStream对象,进行文件读写。
写
String content = "helloworld";
fileOutputStream fos = openFileInput(filename, MODE_PRIVATE);
fos.write(content.getBytes());
fos.close();
读
fileInputStream fis = openFileInput(filename);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
String content = new String(buffer);
fis.close;
- 外部存储
使用外部存储前必须使用Environment.getExternalStorageState()方法来确认外部设备是否可用
必须先在manifest添加SD卡读写权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
写
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File SDPath = Environment.getExternalStorageDirectory();
File file = new File(SDPath, "data.txt");
String data = "helloworld";
fileOutputStream fos = new fileOutputStream(file);
fos.wirte(data.getByte());
fos.close();
}
读(略)
SharedPreferences
存储数据并获取
SharedPreferences sp = getSharedPreferences("data", MODE_PRIVATE); //获得SharedPreferences对象
SharedPreferences.Editor editor = sp.edit(); //获得Editor对象,这样才能对SharedPreferences对象编辑
editor.putString("name", "yuhaoWu"); //写入数据
editor.putInt("age", 20);
editor.remove("name"); //删除key为"name"的数据
editor.clear(); //删除全部数据
editor.putString("sex", "male");
editor.commit(); //提交!!!不提交不会更改。
String sex = sp.getString("sex", "");获取数据,若不存在,则返回""空。
第五章 SQLite数据库
SQLite数据库的创建
创建一个继承自SQLiteOpenHelper的Myhelper类,并重写onCreate()方法和Upgrade()方法
public class MyHelper extends SQLiteOpenHelper{
public MyHelper(Context context){
super(context, "itcast.db", null, 2); // 四个参数,上下文对象、 数据库名称、 游标工厂(通常是null)、数据库版本
}
@Override
public void onCreate(SQLiteDatabase db){
db.execSQL("CREATE TABLE information(
_id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(20),
price INTEGER
)") //
}
}
简答题 怎么做才能增/删/改/查一条数据
- 增加一条数据
通过调用helper的getWritableDatabase()方法得到可读写的SQLiteDatabase对象,然后新建一个ContentValues对象并将要插入的数据添加到ContentValues对象中,最后调用LSQLiteDatabase对象的**insert()**方法将数据插入到表中,再关闭数据库。
public void insert(String name, String price){
SQLiteDatabase db = helper.getWritableDatabase(); //获取可读写的SQLiteDatabase对象
ContentValues values = new ContentValues(); //新建ContentValues对象
values.put("name", name); //添加数据
values.put("price", price);
db.insert("information", null, values) //插入一条数据到information表,如果将要插入的行为空行时,将列名设置为null
db.close(); //关闭数据库
}
- 修改一条数据
通过调用helper的getWritableDatabase()方法得到可读写的SQLiteDatabase对象,然后新建一个ContentValues对象并将要修改的数据添加到ContentValues对象中,最后调用LSQLiteDatabase对象的updata()方法将数据插入到表中,再关闭数据库。
public void updata(String name1, String price1){
SQLiteDatabase db = helper.getWritableDatabase(); //获取可读写的SQLiteDatabase对象
ContentValues values = new ContentValues(); //新建ContentValues对象
values.put("price2", price1);
db.updata("information", values, "name2 = ?", new String[]{name1}); 修改name2 = name1的元组的price2为price1
db.close(); //关闭数据库
}
- 删除一条数据
通过调用helper的getWritableDatabase()方法得到可读写的SQLiteDatabase对象,然后调用SQLiteDatabase对象的delete()方法删除表中的数据,最后关闭数据库。
public int delete(long id){
SQLiteDatabase db = helper.getWritableDatabase(); //获取可读写的SQLiteDatabase对象
db.delete("information", "_id = ?", new String[] {id+""}); //删除_id为id的元组
db.close(); //关闭数据库
}
- 查询一条数据 (重要但我认为不会考)
通过调用helper的getReadableDatabase()方法得到可读的SQLiteDatabase对象,然后调用SQLiteDatabase对象的query()方法返回一个提供了遍历查询方法的行数集合Cursor,通过Cursor的方法来遍历查询数据,最后关闭Cursor和数据库。
public boolean find(long id){
SQLiteDatabase db = helper.getReadableSQLiteDatabase();
Cursor cursor = db.query(
"information", //表名
null, //列名
"_id=?", //查询条件子句
new String[]{""+id}, //查询条件子句对应的条件值
null, //分组方式
null, //having条件
null //排序方式
); //查询_id为id的所有元组
boolean result = cursor.moveToNext();
cursor.close();
db.close();
return result;
}
ListView控件
Android列表控件ListView详解
ListView指定了id属性之后,就会显示,如果没有进行数据适配,那么程序运行后界面空白,无数据显示。
- 常用适配器
- BaseAdapter
方法名称 | 功能描述 |
getCount() | 得到item条目的总数 |
getItem(int position) | 根据position得到某个item的对象 |
getItemId(int position) | 根据position得到某个item的id |
getView(int position, View convertView, ViewGroup parent) | 得到相应position对应的item视图,position是当前item的位置,convertView用于复用旧视图,parent用于加载XML布局 |
- SimpleAdapter
- ArrayAdapter
- ListView的优化
- 复用convertView
- 使用ViewHolder类
- ListView及其优化实战(看看就行,记一下关键代码)
activity_main文件添加一个ListView控件并命名ID及其他属性,另外需要新建一个list_item.xml文件作为ListView对应的item布局,其中有一个ImageView控件item_iv和一个TextView控件item_tv。
MainActivity.java
//全局变量
private ListView listview;
//Activity类中的onCreate()方法
MyBaseAdapter myadapter = new MyBaseAdapter();
listview.setAdapter(myadapter);
//内部类MyBaseAdapter重写的getView(int position, View convertView, ViewGroup parent)方法
View view = View.inflate(MainActivity.this, R.layout.list_item, null);
TextView textview = (TextView)view.findViewById(R.id.item_tv);
ImageView imageview = (ImageView)view.finViewById(R.id.item_iv);
textview.setText(names[position]);
imageview.setBackgroundResource(icons[position]);
return view;
//优化的getView方法和增加的ViewHolder内部类
public view getView(int position, View convertView, ViewGroup parent){
ViewHolder holder;
if(convertView == null){
convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item, parent, flase);
holder = new ViewHolder();
holder.textview = (TextView)convertView.findViewById(R.id.item_tv);
holder.imageview = (ImageView)convert.findViewById(R.id.item_iv);
convertView.setTag(holder);
}else{
holder = (ViewHolder)convertView.getTag();
}
holder.textview.setText(names[position]);
holder.imageview.setBackgroundResource(icons[position]);
return converView;
}
class ViewHolder{
TextView textview;
ImageView imageview;
}
第六章 BroadcastReceiver
- 无序广播
无序广播是完全异步执行的,所有监听这个广播的广播接收者都会接收到此广播消息,但是接收和执行的顺序是不确定的。无序广播效率最高,但是不可以被拦截。 - 有序广播
发送广播,MainActivity.java
Intent intent = new Intent();
intent.setAction("yuhaoWu");
sendOrderedBroadcast(intent, null);
添加广播接收者,MyBroadcastReceiverOne.java
public class MyBroadcastReceiverOne extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent){
Log.i("one", "1号已收到,over");
}
}
设置优先级,AndroidManifest.xml
<receiver android:name=".MyBroadcastReceiverOne">
<intent-filter android:priority="1000">
<action android:name="yuhaoWu" />
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiverTwo">
<intent-filter android:priority="10">
<action android:name="yuhaoWu" />
</intent-filter>
</receiver>
<receiver android:name=".MyBroadcastReceiverThree">
<intent-filter android:priority="100">
<action android:name="yuhaoWu" />
</intent-filter>
</receiver>
拦截,高优先级可以拦截低优先级的广播
在广播接收者类的onReceive方法中调用abortBroadcast()方法即可拦截.
第七章 Services
服务的生命周期(简答-描述)
- startService()启动方式
当通过startService()方法启动服务时,执行的生命周期方法为onCreate()、onStartCommon(),然后服务处于运行状态,直到自身调用stopSelf()方法或其他组件调用stopService()方法时服务停止,最终被系统销毁。
- Call to startService()
- onCreate()
- onStartCommand()
- Service Running
- onDestroy()
- Service shut down
- bindService()启动方式
当使用bindService()方法启动服务时,执行的生命周期方法为onCreate()、onBind(),然后服务处于运行状态,直到调用unBindService()方法时,服务被解绑调用onUnBind()方法,最终被销毁。
- Call to bindService()
- onCreate()
- onBind()
- Client are bound to service
- onUnBind()
- onDestroy()
- Service shut down
第八章 ContentProvider
基本概念
ContentProvider(内容提供者)是Android系统四大组件之一,其功能是在不同的应用程序之间实现数据共享,它不仅允许一个程序访问另一个程序中的数据,同时还可以选择只对那一部分数据进行共享,从而保证了程序中的隐私数据不被泄露。
URI组成结构
如何调用ContentProvider?
通过Context中的getContentResovler()方法获取ContentResovler类的实例。
内容提供者的创建
创建MyContentProvider需要继承抽象类ContentProvider,重写它的一系列抽象方法。
onCreate()在ContentProvider创建时调用
增删改查四个方法
getType()方法用于返回指定URI代表的数据的MIME类型,如jpg、txt。
同时需要在AndroidManifest.xml文件注册
<provider
android:name=".MyContentProvider"
android:authorities="cn.itcast.mycontentprovider"
android:enabled="true"
android:exported="true" />
内容提供者的使用
Uri uri = Uri.parse("content://cn.itacast.mycontentprovider/person"); //authority需与上面manifest文件中注册的一样
ContentResovler resolver = context.getContentResovler();
Cursor cusor = resovler.query(uri, new String[]{name, price, sex}, null, null, null);
while(cursor.moveToNext()){
String name = cursor.getString(0);
int price = cursor.getInt(1);
String sex = cursor.getString(2);
}
系统短信内容提供者的Uri为"content://sms/"