标签:
>解压压缩文件,得到:①Android SDK (类似于JDK)② Eclipse ③ADT
>配置两个path环境变量:D:\adt-bundle-windows-x86\sdk\platform-tools;D:\adt-bundle-windows-x86\sdk\tools
>配置基本的Eclipse的设置:
调整字体大小,字符集,配置android sdk的位置
>创建模拟器:
- 2. 创建第一个Android项目: HelloAndroid
next-next-next-Empty Activity-next-finish
打开应用程序的AndroidManifest.xml文件,修改minsdkVersion值为8.
1). 应用项目的
>L01_HelloWorld:指明当前工程的名称
>src:存放我们编写的java代码
>XxxActivity:一个XxxActivity对应着一个可以与用户交互的应用程序的界面。
>继承于Activity
>重写onCreate()方法。在方法内:
super .onCreate(savedInstanceState); 调用父类的此方法,进行必要的初始化操作
setContentView(R.layout. activity_main); 加载布局文件
>gen : 系统自动生成的文件目录。里面包含着以应用程序包名命名的一个包 ,包含着R.java
>R类:实际上代表着res文件目录,通过R类,可以实现代码和应用程序之间的调用。
R类的内部结构是系统自动生成的,一般我们不去操作
>assets:资产目录
>bin:编译以后的classes.dex 文件,apk文件都保存在此目录下
>libs:存放第三方的jar包
res:全称:resource:资源,代表着当前应用程序的资源目录。内部保存着layout/drawable / values-strings/values-style
>drawable-xxx:提供了不同分辨率的图片,供不同分辨率的手机所使用。
>layout:布局文件。对应着每一个应用程序界面的布局,布局文件就声明在此文件目录下。
文件都是xml格式
>values-strings.xml:声明当前应用程序需要的字符串数据。可以在功能清单文件和布局文件中使用
>values-style.xml:当前应用程序的样式和主题都声明在此
AndroidManifest.xml:功能清单文件。类似于web工程中的web.xml文件
>指明当前应用程序的包名、可以适配的sdk的最低版本、当前应用程序的版本号、权限
<application>:指明当前应用程序的名称label,图标icon,主题Theme
<activity>对应着一个用户界面的Activity。每一个应用程序的Activity的子类,都需要在此功能清单文件中注册。
可以声明属性:name /label /theme / launchmode
< intent-filter>
< action android:name ="android.intent.action.MAIN" />
< category android:name ="android.intent.category.LAUNCHER" />
</ intent-filter>
此处的intent-filter的作用:
action:当前的action的值指明了当前的Activity是当前应用的主界面
category:使得当前的应用程序可以显示在系统的桌面应用中
2). 应用APK的
3). Android系统的
4). SDK的
1). ADB: 调试工具
2). DDMS: eclipse中的debug调试工具:
3). Log: 日志工具类
结论:
1.如果给视图组件设置具体的长度或者宽度时,我们要选择使用dp为单位,而不要选择px为单位。
2.如果设置视图组件的字体的大小,我们选择sp,而不用dp.
|
关于颜色的设置: RGB : red green blue :范围00~ff
红色:#ff0000
绿色:#00ff00
蓝色:#0000ff
白色:#ffffff
黑色:#000000
|
完成步骤:
1.创建一个安卓工程,修改AndroidManifest.xml中的minsdkVersion.
2.完成布局文件:xxx.xml文件。 <Button ></Button> <Button />
3.完成业务逻辑:
1)在XxxActivity的onCreate方法中加载布局文件:setContentView(R.layout.xxx);
2)获取界面上对应的视图对象: findViewById(R.id.xxx)
3)在试图对象上绑定指定的监听器: button.setOnClickListener(listener);
必须重写监听器的抽象方法: onClick()
补充:
模拟器经常掉线,可以考虑的修改措施:
第1层次:reset adb
第2层次:将掉线的模拟器关闭,重新开启
第3层次:关闭掉线的模拟器,关闭eclipse,打开任务管理器将adb.exe进程删掉。然后重启Eclipse和模拟器
关于IntentFilter
- 3. Intent的使用:(创建、携带数据、读取数据)
1.创建:
显式意图: Intent intent = new Intent(Context context,Class clazz);
隐式意图:Intent intent = new Intent(String action);
2.携带数据:
intent.putExtra(String key,Xxx value)
intent.setData(Uri uri);
3.读取数据:
intent.getXxxExtra(String key);
在Intent内部维护了一个HashMap<String,Objec>
- 4. Activity的使用:(声明、启动、结束)
1.声明(如何创建一个Activity)
①创建一个继承于Activity的子类
②在AndroidManifest.xml文件中注册此组件。 <activity name="全类名" label=""> </activity>
③在res-layout-提供一个布局文件:xxx.xml
④ 在Activity的子类中重写的onCreate()中加载布局文件:setContentView(R.layout.xxx);
2.启动:
一般启动: startActivity(Intent intent)
带回调的启动: startActivityForResult(int requestCode,Intent intent)
>接收回调数据的回调方法: onActivityResult( int requestCode, int resultCode, Intent data)
3.结束:
一般结束:finish();
带结果的结果:setResult(int resultCode ,Intent intent);
finish();
TaskStack任务栈结构:
关于Activity的启动模式:LaunchMode
在AndroidManifest.xml中的<Activity>的属性中设置启动模式。
以给Button设置点击的监听为例:
方式一:提供一个接口的匿名实现类的匿名对象
btn.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
//点击button需要完成的操作
}
});
方式二:
btn.setOnClickListener(this);
接着需要当前的Activity实现View.OnClickListener接口,需要当前的Activity重写onClick(View v){}
方式三:
在布局文件中,声明<Button>时,提供一个属性:onClick= "call";
回到布局文件对应的Activity中,提供一个方法:public void call(View v){ }
方式四:提供一个接口的匿名实现类的对象
在当前的Activity中声明一个属性:
private View listener = new View.OnClickListener(){
public void onClick(View v){
//点击button需要完成的操作
}
};
然后
btn.setOnClickListener(listener);
——————————————————————————————————
考虑一下回调方法的参数的判断:
方式一:
if(v == btn1){
}else if(v == btn2){
}...
方式二:
switch(v.getId()){ //byte short char int String 枚举
case R.id.btn1:
break;
case R.id.btn2:
break;
....
}
1). 功能描述:
1) 点击”打电话”: 进入拨号界面
2) 长按”打电话”: 直接拨打电话
3) 点击”发短信”: 进入编辑短信界面
_____________________________________________
4) 长按”发短信”: 直接将短信发送出去
2). 技术点:
① 布局的搭建。在ViewGroup中还可以嵌套ViewGroup
② 给必要的视图对象设置点击或长按的监听事件
③ 如何在当前应用中调用其它应用。 需要使用隐式意图。
④ 数据的携带。putExtra(String key,Xxx value) (--->Xxx getXxxExtra(String key)) ,setData(Uri uri);
⑤ 权限的声明:需要在功能清单文件中,设置当前应用的权限。
3). 总结:
1). 实现一个简单功能的应用的步骤:
①创建一个应用,修改一下minsdkVersion
②完成布局的搭建
③回到Activity中,加载布局文件:setContentView(R.layout.xxx)
④获取并初始化视图对象 并对必要的视图对象设置监听
⑤完成监听需要做的相应的功能
2). 使用隐式意图启动系统应用的界面
首先打开要启动的某一个应用的界面A,通过logcat,使用ActivityManager进行过滤,查看打开的当前界面的信息:当前的Activity类以及所声明的包名。
其次,找到应用程序的源码,在其功能清单文件中,搜索当前的Activity,找到其声明的<intent-filter>中的action。
最后,在需要通过某个界面启动A的界面中,创建一个隐式意图,使用找到的action。启动一个新的Activity即可。
3). 权限:
<!-- 拨打电话的权限 -->
<uses-permission android:name ="android.permission.CALL_PHONE" />
<!-- 发送短信的权限 -->
<uses-permission android:name ="android.permission.SEND_SMS" />
继承树结构:
2). EditText : 可编辑的文本视图
3). Button : 按钮
4). ImageView : 图片视图
5). CheckBox : 多选框
6). RadioGroup/RadioButton : 单选框
* 1.如何触发Menu的显示?
* >OptionMenu:通过menu键触发
*
*
* >ContextMenu:通过长按某一个视图对象触发。
* 需要给视图绑定一个监听器:setOnCreateContextMenuListener(listener)
*
* 2.如何向Menu中添加MenuItem?
*
* >OptionMenu:
* 方式一:在onCreateOptionsMenu()方法中通过menu.add()方式添加
* 方式二:在res-menu下提供menu的
xml文件,在onCreateOptionsMenu()加载
xml文件
* >ContextMenu:
* 方式一:在onCreateContextMenu()方法中通过menu.add()方式添加
* 方式二:在res-menu下提供menu的
xml文件,在onCreateContextMenu()加载
xml文件
*
* 3.选择某个MenuItem时如何响应?
*
* >OptionMenu:
* 在onOptionsItemSelected()方法中处理选中的item
*
* >ContextMenu:
* 在onContextItemSelected()方法中处理选中的item
|
1). ProgressBar
a. 圆形
b. 水平
2). SeekBar
从代码角度,设置view的可见性:
1). API结构
2). AlertDialog
a. 一般的
方法链的的使用:
new AlertDialog.Builder(this)
.setTitle("")
.setMessage("")
.setPositiveButton("确定",listener)
.setNegativeButton("取消",listener)
.show();
//自动的dismiss.
b.带单选列表的
new AlertDialog.Builder( this)
.setTitle( "请选择背景颜色" )
. setSingleChoiceItems( String[] arr,listener)
.show();
//需要手动的dismiss.
c. 自定义布局的
//1.创建对应指定布局文件的View对象
final View view = View.inflate (this , R.layout.dialog_login , null);
//2.将view填充到AlertDialog中
new AlertDialog.Builder( this)
.setView(view)
.setPositiveButton( "确认" ,listener)
.setNegativeButton("取消",null)
.show();
3). ProgressDialog
a. 圆形进度
final
ProgressDialog dialog = ProgressDialog.show(
this,
"数据加载"
,"数据正在加载..."
);
//创建一个分线程(继承的方式)
new Thread(){
public
void run() {
//停留3秒钟
try {
Thread.
sleep(3000);
}
catch (InterruptedException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
//使得当前的dialog消失
dialog.dismiss();
}
}.start();
b. 水平进度
//创建一个ProgressDialog
final ProgressDialog
dialog = new
ProgressDialog(this
);
//设置其为水平的格式
dialog.setProgressStyle(ProgressDialog.
STYLE_HORIZONTAL);
//显示
dialog.show();
//创建一个分线程,模拟数据的下载(实现的方式)
new Thread(new
Runnable(){
@Override
public
void run() {
int count = 200;
//设置dialog的最大值
dialog.setMax(count);
//模拟数据的下载
for(int
i = 0;i < count;i++){
//方式一:
//dialog.setProgress(dialog.getProgress() + 1);
//方式二:
dialog.incrementProgressBy(1);
try
{
Thread.
sleep(10);
}
catch
(InterruptedException e) {
//
TODO Auto-generated catch block
e.printStackTrace();
}
}
//设置dialog消失
dialog.dismiss();
}
}).start();
4). DatePickerDialog 和 TimePickerDialog
补充:
1). 启动分线程
2). 根据id查找View对象:findViewById(int id)
>this.findViewById(int id):this代表当前的Activity对象。实际上是在Activity所加载的布局文件中找指定id的视图组件。
>XxxActivity.this.findViewById(int id):通常使用在Activity的内部类中,表示调用的是外部类XxxActivity所对应的布局文件中find指定的id的视图对象
>view.findViewById(int id):在指定的view所对应的布局文件中查找指定的id的视图对象
view的创建方式:View view = View.inflate(this,R.layout.xxx,null);
3). 更新视图
?线性布局: 用来控制其子View以水平或垂直方式展开显示
?相对布局: 用来控制其子View以相对定位的方式进行布局显示
帧布局:中的每一个子View都代表一个画面,默认以屏幕左上角作为( 0,0 )坐标,按定义的先后顺序依次逐屏显示 , 后面出现的会覆盖前面的画面
1). 视图的常用属性
layout_gravity(对外):在子view中声明此属性,指明此子view相对于父视图的相对位置
gravity(对内):①使用在EditText或者TextView中,指明其内部的文本内容当对于自己的位置
②在父视图中使用此属性,表明其内部的子view相对于自己的位置
|
2). 只针对RelativeLayout
针对于兄弟视图之间:
与父视图之间:
3). 只针对LinearLayout
1.orientation(方向) horizontal (水平方向)/ vertical(垂直方向)
2.layout_weight(权重) 我们可以设置不同子view在父View中的权重。
|
1). 理解
分类:简单视图列表 和 复杂视图列表
继承结构:
2). 使用
a. ArrayAdapter : 显示简单文本列表
b. SimpleAdpater : 显示复杂列表
c. BaseAdpater(抽象的父类): 显示复杂列表
//如何将集合中指定位置的数据装配到指定的position位置的item里面
@Override
public View getView(int
position, View convertView, ViewGroup parent) {
//Log.e("TAG", "getView() position:" + position + ",convertView :" + convertView);
if(convertView ==
null){
//创建item布局对应的View对象
convertView = View.inflate(BaseAdapterActivity.this, R.layout.
item_ba,
null);
Log.
e("TAG",
"创建新的view对象。position : "
+ position);
}
else{
Log.
e("TAG",
"复用现有的view对象。position : "
+ position);
}
//从View对象中取出需要装配数据的结构
ImageView iv_ba_icon= (ImageView) convertView.findViewById(R.id.iv_ba_icon
);
TextView tv_ba_name = (TextView) convertView.findViewById(R.id.tv_ba_name
);
TextView tv_ba_content = (TextView) convertView.findViewById(R.id.tv_ba_content
);
//从集合中取出指定位置的数据
FoodInfo foodInfo =
data.get(position);
//装配数据
iv_ba_icon.setImageResource(foodInfo.getIcon());
tv_ba_name.setText(foodInfo.getName());
tv_ba_content.setText(foodInfo.getContent());
return convertView;
}
|
3). 给ListView的Item设置监听
//给ListView设置点击的监听事件
lv_main.setOnItemClickListener( listener);
//给ListView设置长按的监听事件
lv_main.setOnItemLongClickListener(
listener
);
|
4). ListView的优化(第一层次)
ListView的优化主要针对的就是getView()方法的优化
getView()的作用:如何将集合中指定位置的数据装配到指定的position位置的item里面
优化前:如果当前的ListView一共需要显示1万条数据,那么当每次调用getView()方法时,都会创建一个View对象。效率是比较低的。
优化:假设屏幕上初始化时能显示10个item项,那么屏幕上最多可以显示11个item项。
优化以后,我们只需要最多创建11个View对象即可。后需要显示的view复用已经创建好的View对象。
样式:Style
主题:Theme
1.技术点:
1) ListView (或GridView) + Adapter (ArrayAdapter/SimpleAdapter/ BaseAdapter) + data (集合、数组) + Item Layout
2) 涉及ListView的优化,即getView()方法的优化
3) Adapter通过将内存中的数据进行装配,显示在ListView中。
内存中的数据是如何获取的?① 直接在代码中写明。 ② 通过指定的方法,调用本地文件 ③通过联网获取数据
4)ArrayAdapter处理的是List<T> 或 T[]类型的数据
SimpleAdapter处理的是List<Map<String,Object>>类型的数据
BaseAdapter处理的是List<Object> 类型的数据。通常,我们都习惯使用自己继承BaseAdapter的方式。因为更灵活。
5)给ListView设置监听
1). 位置
data/data/应用的包名/shared-prefs/xxx.xml中
2). 特点
* 1.存储的都是一些小的变量。
* 类型为:boolean float
int long String
* 2. 存储的是键值对特点的数据。而且key都为String型,value即为以上的五种类型。
* 要求存储的数据的key是不相同的。
* 3.随着应用的卸载而被删除
4.数据可以设置为私有的,只能被当前应用访问。
|
3). 相关API
1). 位置
data/data/应用的包名/files/xxx
2). 特点
* 1.存储的文件没有大小的限制。(不能超出存储空间大小)
* 2.可以存储任何格式的文件.(.
png .doc .txt .mp3)
* 3.会随着应用的卸载被删除
* 4.可以将此目录下的文件设置为私有的。
|
3). 相关API
1). 位置
路径1:storage/sdcard/Android/data/应用的包名/files/xxx
路径2:storage/sdcard/xxx
2). 特点
1.路径一中保存的数据会随着应用的卸载被删除
路径二中保存的数据不会随着应用的卸载被删除
2.存储在此路径下的文件是公共的
3.可以存储任意类型的文件
4.文件的大小没有限制,只要不超过sd卡的存储空间即可
5.权限:android.permission.WRITE_EXTERNAL_STORAGE
|
3). 相关API
比较内部文件与外部文件存储?
>文件不大,访问较为频繁,比较重要=>手机内部存储
>数据如果是私有的,不希望其它应用访问,考虑使用手机内部存储
>是否需要随着应用的卸载而被删除。不需要,使用手机外部存储的路径2的方式
应用一:
技术点:
1.GridView + Adapter
2.设置GridView的点击和长按事件
3.AlertDialog的使用
4.使用SharedPreferences存储
1). 存储的位置
>存储在远程的服务器端
2). 特点
>相较于前面的4种存储方式,远程服务器的存储不保存在本地
>不会随着应用的卸载,而被删除
3). 实现联网请求的技术
1) 使用的是Java提供的API:HttpURLConnection
1.要访问资源的路径: GET请求: http://192.168.10.165:8080/Web_server/index.jsp?username=Tom&age=10
POST请求:http://192.168.10.165:8080/Web_server/index.jsp
2. URL url = new URL(path)
3.获取连接对象: HttpURLConnection conn = url.openConnection();
4.设置参数: conn.setConnectionTimeout(); conn.setReadTimeout(); 请求方法:setRequestMethod(); setDoInput();setDoOutput()
如果是POST请求,需要填充请求参数:
conn.getOutputStream().write(byte[]);
5.连接: conn.connect();
6.获取响应码: conn.getResponseCode() == 200 404 500
7.获取服务器端发送过来的数据: conn.getInputStream() BitmapFactory.decode(InputStream is)
8.资源的关闭:流的关闭,连接的关闭:conn.disconnect();
2) android内置的API:HttpClient
1.创建了一个客户端的对象: DefaultHttpClient
2.设置请求参数: HttpConnectionParams
3.提供一个GET请求的对象/ POST请求的对象: (包含请求路径)
GET请求: http://192.168.10.165:8080/Web_server/index.jsp?username=Tom&age=10
POST请求:http://192.168.10.165:8080/Web_server/index.jsp
GET请求: new HttpGet(path)
POST请求: new HttpPost(path); 设置请求体: httpPost.setEntity();
4. 得到HttpResponse : client.execute(httpGet/ httpPost)
5. 获取响应状态行中的响应码:httpResponse.getStatusLine() .getStatusCode()
6. 获取包含响应数据的entity : httpResponse.getEntity()
7. 解析数据: EntityUtils.toString(entity,charset)
8. 使用响应数据
9.资源的关闭: client.getConnectionManager.shutDown();
3 ) 第三方框架:Volley / XUtils
1. 创建一个RequestQueue (先进先出的特点)
2. 创建请求对象: StringRequest/JsonRequest/ImageRequest (重写 onResponse(String result ) / onErrorResponse())
如果是一个POST请求,还需要重写getParams(),返回一个包含请求数据的map即可。
3.将请求对象添加到队列里: queue.add(request);
4). HTTP协议:
5). 搭建服务器端
1.解压Tomcat服务器,放在指定的路径下
2.配置环境变量(3个:path/JAVA_HOME/CATALINA_HOME)
3.如何在Eclipse中配置Tomcat的镜像
4.创建一个动态的web工程(Servlet / jsp / .html)
5.在服务器端部署web工程
6.测试:通过浏览器,可以访问已经部署好的web工程。 http://192.168.10.165:8080/Web_Project/LoginServlet?username=Tom&age=10
6).实现联网请求功能的3步:
第1步:主线程:显示提示列表
第2步:分线程:联网下载数据
第3步:主线程:更新视图
模板:
new Thread(){
public void run(){
第2步:分线程联网下载数据的操作
runOnUiThread(new Runnable(){
public void run(){
//第3步
}
});
}
}.start();
应用练习:
技术点:
1. 显示一个水平的ProgressDialog:如何创建,如何设置最大值(setMax()),如何让进度条增长( setProgress(getProgress() + len) / incrementProgressBy(len) ),消失(dismiss())
2.能够创建指定目录下的一个文件。(存储在本地: context.getFilesDir() (路径:data/data/应用包名/files/.. ) 存储在sd卡:① context.getExternalFilesDir() (路径: storage/sdcard/Android/data/应用包名/files/...) ② Environment.getExternalStorageDirectory() (路径:storage/sdcard/ )
创建一个文件的方式:File file = new File(...., "");
3.使用分线程Thread + runOnUiThread();
4.如何启动另外一个应用的Activity。
5.权限的使用:
<!-- 读写 sd卡权限 -->
<uses-permission android:name ="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 联网的权限 -->
<uses-permission android:name ="android.permission.INTERNET" />
1). 路径
data/data/应用的包名/databases/xxx.db
2). 特点
>保存具有一定结构的数据(如:手机联系人)
>会随着应用的卸载被删除
3). sqlite数据库的特点
4). 相关API
Web中的JDBC (Java DataBase Connectivity)技术:使用Java程序操作数据库的一门技术。
Driver(驱动):类似于SQLiteOpenHelper类
Connection(数据库连接):类似于SqliteDatabase类
PreparedStatement:类似于SqliteDatabase类
ResultSet(结果集):类似于Cursor类
5). Android单元测试
1.
添加配置信息
<application>
<!--使用android测试包
-->
<uses-libraryandroid:name="android.test.runner" />
</application>
<!-- android:targetPackage的值应与manifest的package的值一致-->
<instrumentationandroid:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.atguigu.t4_storage”/>
2.
编写测试类
class StudentTest extends
AndroidTestCase
|
6). 练习总结
技术点:
1.布局的设计:ListView + LinearLayout (权重:weight)
2.数据库的使用: SQLiteOpenHelper + SqliteDatabase + Cursor 结构实现对数据库的CRUD(增、删、改、查)操作。
将CRUD的相关操作封装在BlackNumberDAO类中
3.Android单元测试的使用
4.数据的显示:实际上调用的就是BlackNumberDAO类中的查询操作,将查询到的数据保存在List<BlackNumber>中,使用
Adapter进行装配
5.对于ContextMenu 和 AlertDialog的使用
6.对黑名单数据的添加、修改、删除:①一方面需要对数据库中的数据进行操作 (持久化的) ② 另一方面对内存中的集合数据进行更新
注意点: 确定具体的黑名单号码时,要区分:position 和 BlackNumber的属性id 以及数据表中的主键:_id。
如何实现线程间通信呢? (分线程如何传送数据给主线程)
方式一: Thread + runOnUiThead()
方式二: Thread + Handler + Message
方式三: AsyncTask (实现了对Thread 和 Handler的封装,提供了一个线程池)
1).作用
?可理解为线程间通讯的数据单元, 可通过message携带需要的数据
2). 对象的创建
调用Message的静态方法obtain()获取Message的一个对象。
(Message内部维护了一个消息池,对象是从消息池中获取的:可能是已经存在的message对象,也可能是新创建的)
3). 对象的使用
int what: 唯一的标识此message对象
int args1/args2:用于存储int型的数据
Object obj:用于存储object类型的数据
其它:
long when :此消息要被处理的时间
Message next: 如果在一个message中又声明另一个message,整体就构成一个对列的结构
Handler target: 处理此Message的Handler对象
Runnable callback: 每个message,都可以设置自己被处理的方式
Message sPool: 涉及到消息池的使用
1).作用
?Handler是Message的处理器,同时也负责消息的发送和移除的工作
2). 对象的创建 :
直接new: Handler handler = new Handler(){
public void handleMessage(Message msg){}
}
3). 对象的使用:
a. 发送消息
延迟的非空消息:sendMessageDelayed(Message message,long millis)
延迟的空消息: sendEmptyMessageDelayed(int what, long millis);
即时的消息:sendMessage(Message message);
即时的空消息:sendEmptyMessage(int what);
注意:延迟的消息,不是延迟发送,而是延迟处理
b. 处理消息
虽然handleMessage()方法的优先级比较低,但是是我们主要使用的方式。
c. 移除消息
?移除指定what标识的消息:removeMessages(int what)
移除所有未执行的消息: removeCallbacksAndMessages(null)
理解MessageQueue 和 Looper:(大家在编写代码时,不会显示的去使用这两个类的,但是如果谈消息机制的原理,就离不了这两个类)
1). 理解
2). 相关API
实现联网请求功能的3步:
第1步:主线程:显示提示列表 : onPreExecute();
第2步:分线程:联网下载数据 : doInBackground()
第3步:主线程:更新视图: onPostExecute()
面试题:同步和异步的区别?
1). json是什么?
2). json数据格式
3). 如何解析json?
API:
* 1. 将json格式的字符串{}转换为Java对象, 使用原生API
2. 将json格式的字符串[]转换为Java对象的List, 使用原生API
3. 将json格式的字符串{}转换为Java对象, 使用GSON
4. 将json格式的字符串[]转换为Java对象的List, 使用GSON
5. 将Java对象转换为
json字符串{}, 使用GSON
6. 将Java对象的List转换为
json字符串[], 使用GSON
1-4:将
json格式的字符串(
json对象、json数组)转换为java对象、java对象构成的List。 =>通常使用在客户端
5-6:java对象、java对象构成的List转换为
json格式的字符串(
json对象、json数组) =>通常使用在服务器端
*
|
总结:哪些位置用到了反射?(,面试题)
1.一个ActivityA中启动另外一个ActivityB时,另外的这个ActivityB对象,就是系统通过反射的方式帮我们创建的
startActivity(new Intent(this,activityB.class)); --ActivityB的全路径名已经在AndroidManifest.xml中声明过了
--拓展:进而startService()等相关的要访问的组件,都是系统帮我们创建的。
2.在使用setContentView(R.layout.activity_main);让Activity关联某一个布局文件。
布局文件中涉及到的各个标签所对应的布局本身和具体的子View的对象,也是系统帮我们自动创建的。
3. new Gson().fromJson(String json,Class clazz); 底层通过反射将json中的相关数据装配到clazz所对应的运行时类的对象中
1.何为图片的三级缓存
一级缓存:将图片数据本身保存在内存中:Map<url,Bitmap> 。其中url为加载图片的路径
真实开发中,我们使用的LruCache<String,Bitmap> 实现的,带图片缓存的自动回收机制。
好处:速度最快,节省流量
二级缓存:将图片持久化在手机文件中:保存在sd卡内。 context.getExternalFilesDir()
好处:数据可以持久化,节省流量,相较于三级缓存,速度也快
三级缓存:联网操作,通过指定的url地址,找到服务器端对应的图片资源并下载显示
好处:对于一级缓存、二级缓存中没有的数据,必须联网
2.如何实现图片的三级缓存
1)先从一级缓存中去获取指定url路径的Bitmap(Bitmap bitmap = map.get(url))
>如果bitmap != null:直接显示:imageView.setImageBitmap(bitmap);
>如果bitmap == null:相当于一级缓存中没有。考虑二级缓存
2) 在手机内部指定的路径下,查看指定的url所对应的file是否存在。
接着使用Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath);
>如果bitmap != null:直接显示:imageView.setImageBitmap(bitmap);
同时,将bitmap对象保存到一级缓存
>如果bitmap == null:相当于二级缓存中没有。考虑三级缓存
比如:url : http://192.168.56.1:8080//Web_server/images/f2.jpg
对应的手机内部文件:file : storage/sdcard/Android/data/应用的包名/files/f2.jpg
3) 通过给定的url,联网获取指定url对应的图片,以流的方式将图片数据下载。
>如果能找到指定url对应的资源:Bitmap bitmap = BitmapFactory.decodeStream(InputStream is)
①显示:imageView.setImageBitmap(bitmap);
②将图片缓存到一级缓存、二级缓存中
>如果找不到指定url对应的资源:显示加载失败的图片
3.实现图片的三级缓存过程中出现的问题 (难点)
1)现象:如果快速滑动到最后:①出现了图片的闪动问题;②发现中间快速过掉的图片也加载了,不合理
2)出现的原因:复用了convertView导致的---针对于问题1
因为每一项item都出现过,所有就自然的会去联网下载数据--针对问题2
3)针对于问题1:判断convertView是否是被复用了。
4)具体的实施:
1.在getView的时候,给每一个convertView(或者说给每一个imageView)设置一个标签,
这个标签值即为当前要加载的图片的url地址
2.在分线程联网前,先判断一下要联网下载的图片(url地址)与当前imageView的标签是否相同。
如果相同,那就联网下载图片。
如果不相同,那就取消联网下载
3.当需要给imageView设置图片显示时,判断当前imageView的标签 和马上要显示的图片对应的
url地址是否相同。
如果相同,那就将此图片显示。
如果不相同,那就不显示。但是需要将已经下载的图片缓存起来(一级缓存和二级缓存)。
|
|
关于ListView的优化:四层优化
ListView的优化,实际上就是对Adapter中的getView()的优化
1.第一层优化:复用已有的convertView对象,避免了内存的溢出
效率更高
2.问题一:除了上面复用convertView对象以外,从代码层面还有没有优化的可能性?
问题二:对于联网的应用来说,如果包含图片,那么每次都需要去联网下载图片吗?
问题三:如果联网一共获取了100000条json数据,都需要一次性获取到吗?
3.
第二层优化:
针对于问题一,我们可以创建一个ViewHolder类,让其与convertView关联起来
第三层优化:
针对于问题二:对于图片来讲,我们使用图片的三级缓存
第四层优化:
针对于问题三:使用分页
|
技术点:
1.使用FrameLayout实现组件的重叠
2. ListView + BaseAdatper的使用
3. 联网的操作: HttpURLConnection HttpClient Volley
4. JSON格式数据的解析
5. 使用异步任务(AsyncTask)实现图片的下载
6.体会一下联网的三个步骤
7.图片的三级缓存的使用
8.关于图片的闪动问题的解决
9.权限:联网的权限;写入sd卡的权限
?Activity是如何响应对其中的某个视图的触控操作呢? ----使用MotionEvent
?Activity是如何响应对手机的按键的操作呢?---使用KeyEvent
1). 事件类型:
注意:?对屏幕的任何一个操作, 系统都会自动创建一个MotionEvent对象来对应这个操作,记录用户行为
3). API:
操作事件:
事件的分发:从外到内:调用Activity的dispatchTouchEvent() --->ViewGroup 的dispatchTouchEvent()--->某个点击的view
的dispatchTouchEvent()
事件的消费:从里到外:调用绑定在某个点击的view对象的监听器上,调用监听器的onTouch() ---->调用view对象的onTouchEvent() ---->ViewGroup 的onTouchEvent() --->调用Activity的onTouchEvent()
一旦在消费的过程中,某一个方法返回true,表示消费了此事件。则不再继续向外传递。
1). 事件类型
2). API:
注意点:1.正常情况下,当我们长按某一个key时,会调用-onKeyDown() - onKeyDown()- .... - onKeyLongPress() -- onKeyDown()-
... - onKeyUp().
2.我们发现有些按键在长按时,并没有触发onKeyLongPress()方法,如何实现这个方法的调用:
1)将onKeyDown()方法返回值改为return true
2)在返回之前,调用event.startTracking()
3.一般情况下,针对于KeyEvent来讲,也就针对于onKeyUp()进行操作,对返回键(KeyEvent. KEYCODE_BACK)设置单次点击不能退
出应用的操作。
技术点:
1.通过调用MotionEvent的getRawX() 和 getRawY(),获取焦点的坐标
2.通过调用View的getLeft() getRight() getTop() getBottom() 方法,获取具体的界面上的一个view的坐标
3.通过调用View的layout(l,t,r,b)重新给view定位
4.调用子视图view的getParent()获取父视图。
针对于KeyEvent:
1.在onKeyUp()方法中修改返回值,不让其直接调用:super .onKeyUp(keyCode, event)
2.设置一个boolean型变量:第一次点击时,修改boolean型变量的值,使其第二次点击时,调用super .onKeyUp(keyCode, event)
3.发送一个延迟的空消息,将boolean变量修改为最初的值。
4.为了保证不出现内存泄漏的问题,在onDestroy()中,移除所有未处理的消息
0.组件的特征:
1)需要继承现有的类或者实现现有的接口
2)组件需要在功能清单文件中注册
3)组件的对象是由系统在一定情况下,自动创建的。
4)往往需要重写相关的方法,此方法在满足一定情况下,调用。此方法称为:回调方法
1. Service的理解:
Service是一个应用组件, 它用来在后台完成一个时间跨度比较大的工作且没有关联任何界面
1). 区别Service与Activity?
2). 区别Service与Thread?
2. Service的分类
3. Service的定义
4. Service的启动与停止
5. Service的生命周期
注意:每次startService都会调用Service的onStartCommand()
针对于绑定的方式,如果onBind()方法返回值非空,则会调用启动者(比如:activity)
中的ServiceConnection中的onServiceConnected()方法。
6. 远程Service的使用(AIDL)
1)
2)
对照着ppt实现AIDL的功能即可
7. 应用练习
应用一:本地服务
1.使用本地服务,实现在应用对应的Activity销毁时,音乐文件依然可以播放。同时,当我们再进入操作界面时,此时的
Activity是一个新的对象,但是,我们仍然可以操作之前开启的服务。
2.这里我们将音乐播放的功能,在服务里实现。
应用二:挂断电话功能
反射的使用:
//1.通过反射获取系统服务的管理器
Class clazz = Class.forName( "android.os.ServiceManager");
//2.获取其内部指定的方法
Method method = clazz.getDeclaredMethod( "getService" , String. class);
//3.调用方法:操作电话服务
IBinder iBinder = (IBinder) method.invoke(null ,Context.TELEPHONY_SERVICE );
应用三:实现黑名单电话的自动挂断
技术点:
1.对来电相应状态的监听,我们在服务中实现
2.TelephonyManager 和 PhoneStateListener 的使用
3.手机来电的三种状态:空闲状态、响铃状态、接通状态
08_四大应用组件之BroadcastReceiver
|
1). 特点和作用
2). 相关API
3). 常见广播:
1. 针对于开机广播,创建一个开机广播的接收器。配置action,提供权限
2.一旦开机,对应广播接收器的onReceive()方法就开始执行。
3.在此回调方法内,设置startService()的方法,开启黑名单电话拦截的服务
1.针对于来短信这个有序广播来说,我们创建一个对应的广播接收器。配置action,提供权限
2.针对于有序广播来说,设置最高的优先级:Integer.MAX_VALUE
3.一来短信,对应的接收器的onReceive()开始执行,短信的数据就封装在onReceive()方法形参的intent中
4.从intent中将短信号码和短信内容取出来。判断短信号码是否为黑名单号码。若是,执行abortBroadcast()方法。
09_四大应用组件之ContentProvider
|
1). 为会么要有ContentProvider?
2). ContentProvider是什么?
1). ContentProvider: 内容提供者类
2). ContentResolver: 内容解析器类 :
3). Uri: 包含一个具有一定格式的字符串所对应资源的类
4).
5). ContentUris: 操作uri的工具类
- 4. 使用ContentResolver访问ContentProvider
技术点:
1.如何启动一个带回调的Activity。 startActivityForResult() ---> setResult() ---->onActivityResult()
2.显示列表数据: ListView + BaseAdapter + List<ShopInfo> (或 List<Map<String,Object>>) + item layout
3.创建ContentResolver,访问联系人的ContentProvider.
1). View动画的分类
2). View动画的使用
1. 公用功能
2. 如何指定坐标(中心点, 起始点, 目标点)
2.1 java代码上:
2.2 xml格式:
3). 使用Drawable 动画
第1步: 在res-drawable目录下创建相应的xml格式的文件:
第2步:在具体的组件中配置:
第3步:使用具体的button设置监听的回调方法。在回调方法中:(AnimationDrawable对象只需要提供一个即可)
应用一:
技术点:
1.设置图片为整体布局的background属性,同时声明当前Activity的主题:全屏显示
2.设置旋转、缩放、透明度动画的集并作用在LinearLayout上。
3.自定义圆形进度条
4.设置动画的监听,在动画结束的时候启动一个新的Activity
5.设置不同的Activity之间切换的动画
6.将系统提供的sample应用:ApiDemos的工程导入eclipse中。
应用二:
1.布局的设置:使用到了FramLayout显示图片的叠加
2.如何实现旋转动画,同时注意设置repeatCount:设置为无限循环。当扫描完成时,需要清除动画
3.使用异步任务实现数据的扫描
4.使用Drawable动画,显示图层效果。
1). 保存和读取图片:
>将资源目录下的图片加载显示: iv.setImageResource(R.drawable.xxx);
>将手机内部文件中的某一个图片文件转换为内存中的一个Bitmap对象,并显示:
Bitmap bitmap = BitmapFactory.decodeFile(String fileAbsolutePath);
//手机内部:this.getFileDirs()对应: data/data/应用包名/files/
//手机sd卡路径1:this.getExternalFilesDirs(null)对应: storage/sdcard/Android/data/应用包名/files/
//手机sd卡路径2:Environment.getExternalStorageDirectory()对应: storage/sdcard/
File file = new File(路径,"文件名");
iv.setImageBitmap(bitmap);
>将内存中的bitmap对象保存起来:
bitmap.commpress(....,...,路径对应的输出流); //输出流: new FileOutputStream(file); openFileOutput(" ");
2)使用矩阵:Matrix
2). 自定义图形<shape>
3). 定义多状态图形图片 <selector>
a. selector+shape
接着在具体的view组件上,以background属性的方式添加上
b. selector+drawable
4). 9Patch图片:
a. 理解
b. 制作
>拖拉上和左的线条,用于将图片分成9个区域。
>默认情况下,只有1区是可以显示内容的
>拖拉下和右的线条,指定可以显示内容的区域大小
好处: 保证图片在放大以后,不失真!
技术点:
1. 9patch图片的制作
2. PopupWindow的创建,加载指定的布局,显示在指定位置,消失
3. 给ListView设置onScrollListener()
4. 设置PopupWindow显示的动画
5. 给视图对象设置监听
6. selector + shape的使用
Context
1). 用来做什么?
a. 操作应用组件
b. 操作视图对象
c. 获取应用环境全局信息
2). 实现:
Activity : 前台界面
Service : 后台服务
Application : 应用, 全局数据共享的容器
3). 两种Context对象:
Activity.this : Dialog, 视图相关的
getApplicationContext() : 如果对象的生命周期长于Activity, 必须用它
ANR
见课件
屏幕横竖屏切换
1). 如何强制只能横或竖屏?
2). 如何动态横或竖屏?
Android基础篇之Android快速入门--你必须要知道的基础
标签:
原文地址:http://blog.csdn.net/u011200604/article/details/51893754