Android学习笔记(二)_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > Android学习笔记(二)

Android学习笔记(二)

 2013/8/18 19:28:26  玲龙雨  博客园  我要评论(0)
  • 摘要:Handler的使用1.Handler类是android.os下的一个类,handler.post(Runnabler)可以将一个线程添加到消息队列中;handler.postDelay(Runnabler,longdelayTime)在延迟delayTime毫秒后,将线程添加到消息队列中;handler.removeCalbacks(Runnabler)将队列中挂起的Runnable移出。2.Handler.obtainMessage()可以获得一条消息
  • 标签:笔记 android 学习 学习笔记 android学习笔记

Handler的使用

       1.Handler类是android.os下的一个类,handler.post(Runnable r)可以将一个线程添加到消息队列中;handler.postDelay(Runnable r, long delayTime)在延迟delayTime毫秒后,将线程添加到消息队列中;handler.removeCalbacks(Runnable r)将队列中挂起的Runnable移出。

       2.Handler.obtainMessage()可以获得一条消息,这个消息有两个整型的参数arg1和arg2,利用它可以传递消息。在创建Handler的时候,如果用

  Handler handler = new Handler(){

         @Override

         public void handleMessage(Message msg){

                ……

         }

  }

  来创建的话,该handler可以从消息队列(MessageQueue)中取出消息并在handleMessage方法中处理。而在另一个地方,也可以使用handler.sendMessage(Message msg)来向消息队列中发送消息。

  Handler对于线程的处理并不是另外开启一个线程,而是在原有线程的基础上调用另一个Runnable的run函数。thread.html" target="_blank">HanlderThread类实现了Looper来处理消息队列的功能,这个类由Android操作系统提供。利用该类,可以使用getLooper()(在使用getLooper()方法之前,必须调用该类的start()方法,否则这个Looper是null)方法来获取这个Looper,之后,将这个Looper以参数的形式传递给Handler的构造函数,此时这个Handler的handleMessage()方法就可以由另一个线程来处理了,就不会阻塞Activity。

       可以把Bundle看作一个特殊的Map,只是它的键固定为String类型,值也只有几种基本的数据类型。

       在使用Message传递数据的时候,发送之前可以使用Message.obj来传递一个数据,这个数据是一个Object即可。处理消息的时候,也可以使用Message.obj来获取,此时需要向下转型。如果需要传递大量数据,可以使用Message.setData(Bundle data)。

       Message.sendToTarget();方法可以讲这个message发送给创建这个Message的Handler,在这个Handler里面可以接收该Message。

SQLite的使用

       1. SQLiteOpenHelper类的使用

    public abstract class SQLiteOpenHelper类中有几个函数:

    onCreate(SQLiteDatabase db);当数据库第一次创建的时候调用这个方法

    onOpen(SQLiteDatabase db);当数据库被打开的时候调用这个方法

    onUpgrade(SQLiteDatabase db);当数据库需要升级的时候调用这个方法

    getReadableDatabase();获得可以读的数据库

    getWritbaleDatabase();获得可以写的数据库

       我们一般继承这个类,然后调用构造函数(父类没有默认构造函数)。数据库的版本为整数,从1开始,每次升级数据库版本的时候,这个值依次递增。当发现这个值变化的时候,就意味着数据库已经进行了版本升级。

       使用SQLiteDatabase.execSQL(String sql)来执行SQL语句。

       2.adb工具的使用

可以使用adb工具(在cmd中输入adb即可,在这之前需要为它配置环境变量,在sdk/platform-tools下面,另一个就是要保证模拟器AVD是打开的,否则会报错)来查看数据库中的变化:

       adb shell:进入Linux命令行(android操作系统是以Linux为核心的)

       ls –l:以完整的形式显示文件和文件夹

       cd data:进入data

       cd data:再进入data

       这里面有很多文件夹(以应用程序的包名命名),每一个应用程序都有一个文件夹

       cd com.example.sqlite3:进入我们当前的应用程序

       创建数据库后,这里面会多一个叫databases的文件夹

       cd databases:进入这个文件夹,这里面可以看到刚刚创建的数据库

       sqlite3 mydb:使用SQLite打开数据库mydb

       然后就可以像Mysql一样使用数据库了:

       select * from table_name;……

       3.插入数据

       使用ContentValues类来帮助插入数据:

  ContentValues values = new ContentValues();

  values.put(“id”,1);//第一个参数为列名,第二个参数为列的值

  values.put(“name”,”alvis”);

  //DatabaseHelper类继承于SQLiteOpenHelper类

  DatabaseHelper dbHelper = new DatabaseHelper(MainActivity.this,”mydb”);

  //得到一个数据库对象

  SQLiteDatabase db = dbHelper.getWritableDatabase();

  db.insert(“user”,null,values);//调用insert方法插入数据。

  insert方法的第一个参数为表名,第二个直接填null即可。第三个为带有数据的ContentValues对象。

  4.更新数据

  DatabaseHelper dbHelper = new DatabaseHelper(MainActivity.this,”mydb”);

  //得到一个数据库对象

  SQLiteDatabase db = dbHelper.getWritableDatabase();

  ContentValues values = new ContentValues();

  values.put(“name”,”alvis”);

  db.update(“user”,values,”id=?”,new String[]{“1”});//这里使用占位符来设置参数

  整个这几句其实就组成了一句话:

  update user set name=’alvis’ where id=1;

  update方法第一个参数是要更新的表名,第二个参数是带有要更新值的ContentValues对象,第三个参数是where字句的条件(可以有多个),第四个参数为where字句的值,类型为String[]。

       5.查询数据

              DatabaseHelper dbHelper = new DatabaseHelper(MainActivity.this,”mydb”);

              SQLiteDatabase db = dbHelper.getWritableDatabase();

              Cursor cursor = db.query(“user”, new String[]{“id”,”name”}, ”id=?”, new String[]{“1”},null,null,”id” );

              while(cursor.moveToNext()){

                     //这里处理获得的数据

                     String result = cursor.getString(cursor.getColumnIndex(“name”));

                     System.out.println(result);

              }

       cursor.moveToNext()方法有两个作用: 将游标下移看是否有下一条记录,有就返回true,否则返回false,就是说把指针移到下一个位置的同时还判断是否还有值。

       query方法的参数依次为(后面三个参数均为字符串):

表名,查询的字段,查询条件,条件的参数,groupBy,having,orderBy

其实就是把一条select语句分解成了很多部分。

       使用cursor获取数据的时候,参数一定要是要查询所在列的索引,这个索引可以通过cursor.getColumn(String columnName)来获得,于是就有了上面的写法。

       建议不要太多的依赖于数据库,也不要在SQLite数据库中存入太多的数据,因为在开发的时候可能会出现很多奇怪的问题。

Android程序调试

       可以使用Log类来输出调试信息:

       Log.i(String tag,String message);//Info级别的

       Log.v(String tag,String message);//致命的

       Log.w(String tag,String message);//警告

       Log.e(String tag,String message);//错误

       Log.d(String tag,String message);//调试

文件下载

  1.下载文件的步骤:

  1).创建一个URL对象

  URL url = new URL(String urlStr);

  2).创建一个HttpURLConnection

  HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();

  3).获得一个InputStream对象

  InputStream inputStream = urlConn.getInputStream();

  然后就可以使用流操作读取这个inputStream了

  4).访问网络的权限:在Manifest.xml中声明:

  <uses-permission android:name="android.permission.INTERNET"/>

       源代码:

       class DownloadMP3Listener implements OnClickListener{

              @Override

              public void onClick(View v) {

                     HttpDownloader httpDownloader = new HttpDownloader();

                     int status = httpDownloader.downFile("http://192.168.2.104:8080/source/ yiwangeshebude.mp3", "Download", "一万个舍不得.mp3");

              }

       }

       错误:android.os.NetworkOnMainThreadException

  这个异常大概意思是在主线程访问网络时出的异常。 Android在4.0之前的版本 支持在主线程中访问网络,但是在4.0以后对这部分程序进行了优化,也就是说访问网络的代码不能写在主线程中了。

  解决办法:重新开启一个线程去跑网络相关的代码。

  class DownloadMP3Listener implements OnClickListener{

              @Override

              public void onClick(View v) {

                     new Thread(){      //重新开启一个线程去访问网络

                            @Override

                            public void run(){

                                   HttpDownloader httpDownloader = new HttpDownloader();

                          int status = httpDownloader.downFile("http://192.168.2.104:8080/source/ yiwangeshebude.mp3", "Download", "一万个舍不得.mp3");

                            }

}.start();

                }

         }

       2.访问SD卡

       1).得到当前设备SD卡的目录:一般就是 /SDCARD

              String path = Environment.getExternalStorageDirectory();

       2).在Manifest.xml文件中设置访问SD卡的权限(和application标签同级)

              <uses-permission android:name="android.permission.INTERNET"/>

ContentProvider初步

       1.每一个ContentProvider都有一个公共的URI,这个URI表示这个ContentProvider所提供的数据。Android提供的ContentProvider都在android.provider包中。

       2.ContentProvider所提供的函数:

       query():查询             insert():插入                    update():更新

   delete():删除            getType():得到数据类型  onCreate():创建时的回调函数

  3.实现ContentProvider的过程:

       1).定义一个CONTENT_URI常量

       2).定义一个类,继承ContentProvider类

       3).实现query,insert,update,delete,getType和onCreate方法

       4).在AndroidManifest.xml中进行声明

XML文件解析

       ContentHandler接口

       ContentHandler是Java类包中一个特殊的SAX接口,位于org.xml.sax包中,该接口封装了一些对事件处理的方法,当XML解析器开始解析XML输入文档时,它会遇到某些特殊的事件,比如文档的开头和结束、元素的开头和结束、以及元素中的字符数据等事件。当遇到这些事件时,XML解析器会调用ContentHandler接口中相应的方法来响应该事件。

       ContentHandler接口的方法有以下几种:

       void startDocument()

       void endDocument()

       void startElement(String uri,String localName,String qName,Attributes atts)

       void endElement(String uri,String localName,String qName)

       void characters(char[] ch,int start,int length)读取到中间的字符的时候调用

       通常的处理流程如下:

       1).创建事件处理程序

       2).创建SAX解析器

       3).将事件处理程序分配给解析器

       4).对文档进行解析,将每个时间发送给处理程序

       如下面的例子

   //1.创建一个SAXParserFactory

       SAXParserFactory factory = SAXParserFactory.newInstance();

       //2.通过这个factory获得一个XMLReader

       XMLReader reader = factory.newSAXParser().getXMLReader();

       //3.为XMLReader设置内容处理器

       //注意这个方法的参数是一个ContentHander,但是由于ContentHandler里面的

       //方法太多,因此这里使用适配器模式,MyContentHandler是继承于DefaultHandler

   //的,而DefaultHandler实现了ContentHanlder接口。

       reader.setContentHandler(new MyContentHandler());

       //4.开始解析文件

       reader.parse(new InputSource(new StringReader(xml)));

广播机制

       如果要监听某一类事件,则需要在Manifest.xml文件中声明:

       <receiver android:name=”.TestReceiver”>

              <inteng-filter>

                     <action androi:name=”andriod.intent.action.EDIT”/>

              </intent-filter>

       </receiver>

  同时接收方需要继承BroadcastReceiver类,并复写onReceiver方法:

       class TestReceiver extends BroadcastReceiver{

    @Override

    public void onReceiver(Context context, Intent intent){

                       //这里写处理流程

    }

       }

       注意蓝色部分的匹配。

       而在发送方,可以使用:

       Intent intent = new Intent();

       intent.setAction(Intent.ACTION_EDIT);

       TestActivity.this.sendBrodcast(intent);

       注意红色的部分需要匹配,否则接收不到这个消息。

       这个程序的大体流程是:TestActivity广播了一个action为ACTION_EDIT的 intent,TestReceiver因为继承了BroadcastReceiver,因此是一个广播的接收器,但是至于接不接收由TestActivity广播的intent,就要看在Manifest.xml文件中对TestReceiver的配置了。

在Manifest.xml文件中对于TestReceiver的配置里,<intent-filter>的<action>标签指明了TestReceiver监听的哪种action,只有当TestActivity广播的intent中的action和这里的action相同的时候,才会接收到,此时会生成一个TestReceiver,并调用该类的onReceiver方法。

       注意:TestReceiver只做一次处理,如果处理过了,那么这个对象就没用了,如果再有同样的广播发送出来,那么操作系统会再生成这样一个对象来处理。

发表评论
用户名: 匿名