Android基础篇之Android快速入门--你必须要知道的基础

Android快速入门

  • 1. 搭建开发环境
>解压压缩文件,得到:①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.


  • 3. 四个文件目录结构:
     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的
              



  • 4. 三个应用开发工具
     1). ADB: 调试工具
          


     2). DDMS: eclipse中的debug调试工具:
      


     3). Log: 日志工具类
          



  • 5. 尺寸
       


结论:
1.如果给视图组件设置具体的长度或者宽度时,我们要选择使用dp为单位,而不要选择px为单位。
2.如果设置视图组件的字体的大小,我们选择sp,而不用dp.



  • 6.关于颜色

    关于颜色的设置: RGB : red  green  blue :范围00~ff
    红色:#ff0000
    绿色:#00ff00
    蓝色:#0000ff
    白色:#ffffff
    黑色:#000000




  • 7. 相关API:
         




  • 8. 应用练习:    


完成步骤:
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和模拟器






02_四大应用组件之Actvity

  • 1. Activity的理解:



  • 2. Intent的理解

关于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();

  • 5. Activity的生命周期
  



  • 6. TaskStack和lauchMode
     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;
....
}


  • 7. 应用练习:  打电话与发短信
          
     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" />




     

03_用户界面(上)

  • 1. UI的理解  
继承树结构:


  • 2.UI事件的理解

  • 3. 常用的UI组件
  • 3.1. 简单UI组件
     1). TextView : 文本视图
          

     2). EditText : 可编辑的文本视图
          

     3). Button : 按钮
           

     4). ImageView : 图片视图

     5). CheckBox : 多选框
          

     6). RadioGroup/RadioButton : 单选框
          


  • 3.2. 菜单Menu    

 * 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

    


  • 3.3. 进度条
     1). ProgressBar
          a. 圆形
               

          b. 水平
               

     2). SeekBar
          

从代码角度,设置view的可见性:


  • 3.4. 对话框    
     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). 更新视图      
         














03_用户界面(下)

  • 3. 常用的UI布局(三种)
     •线性布局: 用来控制其子View以水平或垂直方式展开显示

     •相对布局: 用来控制其子View以相对定位的方式进行布局显示

     帧布局:中的每一个子View都代表一个画面,默认以屏幕左上角作为( 0,0 )坐标,按定义的先后顺序依次逐屏显示 , 后面出现的会覆盖前面的画面

  • 4. 常用的视图标签的属性
     1). 视图的常用属性

          

 layout_gravity(对外):在子view中声明此属性,指明此子view相对于父视图的相对位置
 gravity(对内):①使用在EditText或者TextView中,指明其内部的文本内容当对于自己的位置
                ②在父视图中使用此属性,表明其内部的子view相对于自己的位置
         
     2). 只针对RelativeLayout
          针对于兄弟视图之间:
  与父视图之间:
     
              
     3). 只针对LinearLayout
          
1.orientation(方向) horizontal (水平方向)/ vertical(垂直方向)
2.layout_weight(权重)  我们可以设置不同子view在父View中的权重。

               

  • 5. ListView的使用
     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对象。
      


  • 6. style和Theme
样式:Style

主题:Theme


  • 7. 练习
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设置监听 





04_数据存储(上)

  • 1. Android中的数据存储方式:(五种)
         

          

  • 2. SharedPrefrence存储
      1). 位置
          data/data/应用的包名/shared-prefs/xxx.xml中
     2). 特点
         
 * 1.存储的都是一些小的变量。
 *   类型为:boolean float int long String
 * 2. 存储的是键值对特点的数据。而且key都为String型,value即为以上的五种类型。
 *    要求存储的数据的key是不相同的。
 * 3.随着应用的卸载而被删除
   4.数据可以设置为私有的,只能被当前应用访问。

     3). 相关API
          
     

  • 3. 手机内部文件存储
     1). 位置
         data/data/应用的包名/files/xxx
     2). 特点
          
 * 1.存储的文件没有大小的限制。(不能超出存储空间大小)
 * 2.可以存储任何格式的文件.(. png  .doc .txt   .mp3)
 * 3.会随着应用的卸载被删除
 * 4.可以将此目录下的文件设置为私有的。

     3). 相关API
          


  • 4. 手机外部文件存储(sd卡的存储)
     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存储


       

04_数据存储(下)

  • 6. 远程服务器存储
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" />


04_数据存储(中)

  • 5. Sqlite数据库存储
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的值应与manifestpackage的值一致-->

<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。









05_消息机制与异步任务

  • 1. 消息机制的引入

          如何实现线程间通信呢?  (分线程如何传送数据给主线程)
    方式一: Thread + runOnUiThead()
    方式二:  Thread + Handler + Message
    方式三:   AsyncTask (实现了对Thread 和 Handler的封装,提供了一个线程池)


  • 2. Message的使用 :  
          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:  涉及到消息池的使用

    

  • 3. Handler的使用 : 

          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:(大家在编写代码时,不会显示的去使用这两个类的,但是如果谈消息机制的原理,就离不了这两个类)


     

  • 4. 消息机制的原理
   
   
     


      

  • 5. AsyncTask的使用
          1). 理解
    

          2). 相关API
     


  • 6. AsyncTask的基本原理
      

实现联网请求功能的3步:
   第1步:主线程:显示提示列表 : onPreExecute();
   第2步:分线程:联网下载数据 :  doInBackground()
   第3步:主线程:更新视图: onPostExecute()


面试题:同步和异步的区别?



  • 7. Json数据格式和解析
          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所对应的运行时类的对象中


  • 8. 图片的三级缓存技术

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关联起来

第三层优化:
针对于问题二:对于图片来讲,我们使用图片的三级缓存

第四层优化:
针对于问题三:使用分页



  • 9. 应用练习
         
技术点:
1.使用FrameLayout实现组件的重叠
2. ListView + BaseAdatper的使用
3. 联网的操作:  HttpURLConnection  HttpClient   Volley
4. JSON格式数据的解析
5. 使用异步任务(AsyncTask)实现图片的下载
6.体会一下联网的三个步骤
7.图片的三级缓存的使用
8.关于图片的闪动问题的解决
9.权限:联网的权限;写入sd卡的权限





06_事件机制

  • 1. 提出问题?

•Activity是如何响应对其中的某个视图的触控操作呢? ----使用MotionEvent
•Activity是如何响应对手机的按键的操作呢?---使用KeyEvent


  • 2. 屏幕触控(MotionEvent)机制
1). 事件类型:


2). 事件发生的顺序:
 

注意:•对屏幕的任何一个操作, 系统都会 自动创建一个MotionEvent对象来对应这个操作,记录用户行为
3). API:
    
     

操作事件:
     事件的分发:从外到内:调用Activity的dispatchTouchEvent() --->ViewGroup 的dispatchTouchEvent()--->某个点击的view
                         的dispatchTouchEvent()
     事件的消费:从里到外:调用绑定在某个点击的view对象的监听器上,调用监听器的onTouch() ---->调用view对象的onTouchEvent() ---->ViewGroup 的onTouchEvent() --->调用Activity的onTouchEvent()
      一旦在消费的过程中,某一个方法返回true,表示消费了此事件。则不再继续向外传递。

4). 事件分发和处理流程
     

     
     

  • 3. 按键(KeyEvent)机制
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)设置单次点击不能退
               出应用的操作。



  • 4. 应用练习
  • 1)
技术点:
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()中,移除所有未处理的消息





07_四大应用组件之Service

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. 理论概述
1). 特点和作用
     

2). 相关API
      

3). 常见广播:
      


  • 2. 发送广播
     

     

  •  3. 注册广播接收器
         

          

  • 4. 应用练习
  
          1. 针对于开机广播,创建一个开机广播的接收器。配置action,提供权限
          2.一旦开机,对应广播接收器的onReceive()方法就开始执行。
          3.在此回调方法内,设置startService()的方法,开启黑名单电话拦截的服务
   
          1.针对于来短信这个有序广播来说,我们创建一个对应的广播接收器。配置action,提供权限
          2.针对于有序广播来说,设置最高的优先级:Integer.MAX_VALUE
          3.一来短信,对应的接收器的onReceive()开始执行,短信的数据就封装在onReceive()方法形参的intent中
          4.从intent中将短信号码和短信内容取出来。判断短信号码是否为黑名单号码。若是,执行abortBroadcast()方法。









09_四大应用组件之ContentProvider

  • 1. 理解
1). 为会么要有ContentProvider?

2). ContentProvider是什么?
     

  • 2. 相关API:
1). ContentProvider: 内容提供者类
 


2). ContentResolver: 内容解析器类 : 
     


3). Uri: 包含一个具有一定格式的字符串所对应资源的类
     


4). 
     


5). ContentUris: 操作uri的工具类
    

  • 3. 自定义ContentProvider
   



  • 4. 使用ContentResolver访问ContentProvider
     


  • 5. 应用练习
技术点:
1.如何启动一个带回调的Activity。 startActivityForResult()  ---> setResult() ---->onActivityResult()
2.显示列表数据: ListView + BaseAdapter + List<ShopInfo>  (或 List<Map<String,Object>>) + item layout
3.创建ContentResolver,访问联系人的ContentProvider.





















 

10_动画

  • 1. 理解
      


  • 2. 使用动画
1). View动画的分类
     
2). View动画的使用
     1. 公用功能
          

     2. 如何指定坐标(中心点, 起始点, 目标点)
      2.1 java代码上:
          
      2.2 xml格式:
            

3). 使用Drawable 动画
  第1步:  在res-drawable目录下创建相应的xml格式的文件:
第2步:在具体的组件中配置:
第3步:使用具体的button设置监听的回调方法。在回调方法中:(AnimationDrawable对象只需要提供一个即可)
     


  • 3. 应用练习
应用一:
技术点:
1.设置图片为整体布局的background属性,同时声明当前Activity的主题:全屏显示
2.设置旋转、缩放、透明度动画的集并作用在LinearLayout上。
3.自定义圆形进度条
4.设置动画的监听,在动画结束的时候启动一个新的Activity
5.设置不同的Activity之间切换的动画
6.将系统提供的sample应用:ApiDemos的工程导入eclipse中。

应用二:
 
1.布局的设置:使用到了FramLayout显示图片的叠加
2.如何实现旋转动画,同时注意设置repeatCount:设置为无限循环。当扫描完成时,需要清除动画
3.使用异步任务实现数据的扫描
4.使用Drawable动画,显示图层效果。


























11_图像处理

  • 1. 理解
       

      

  • 2. 操作图片
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区是可以显示内容的
>拖拉下和右的线条,指定可以显示内容的区域大小
     好处: 保证图片在放大以后,不失真!



  • 3. 自定义图形(自定义View)


  • 4. 应用练习
技术点:
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). 如何动态横或竖屏?


















评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值