湖南某科技大学 安卓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控件
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/"