开发者社区> 小龙猫> 正文

Android学习笔记(二)

简介:
+关注继续查看

1. 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的时候,如果用

1
2
3
4
5
6
Handler handler = new Handler(){
   @Override
   public void handleMessage(Message msg){
      ……
   }
}

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

  Handler对于线程的处理并不是另外开启一个线程,而是在原有线程的基础上调用另一个Runnable的run函数。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。

2. 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类来帮助插入数据:

1
2
3
4
5
6
7
8
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.更新数据  

1
2
3
4
5
6
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.查询数据     

1
2
3
4
5
6
7
8
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数据库中存入太多的数据,因为在开发的时候可能会出现很多奇怪的问题。

3. Android程序调试

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

1
2
3
4
5
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);//调试

4. 文件下载

  1.下载文件的步骤:

  1).创建一个URL对象

1
URL url = new URL(String urlStr);

  2).创建一个HttpURLConnection

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

  3).获得一个InputStream对象

1
InputStream inputStream = urlConn.getInputStream();

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

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

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

       源代码:

1
2
3
4
5
6
7
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以后对这部分程序进行了优化,也就是说访问网络的代码不能写在主线程中了。

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

1
2
3
4
5
6
7
8
9
10
11
12
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

1
String path = Environment.getExternalStorageDirectory();

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

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

5. 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中进行声明

6. 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  

1
SAXParserFactory factory = SAXParserFactory.newInstance();

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

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

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

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

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

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

1
reader.setContentHandler(new MyContentHandler());

       //4.开始解析文件

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

6. 广播机制

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

1
2
3
4
5
<receiver android:name=”.TestReceiver”>
    <inteng-filter>
        <action androi:name=”andriod.intent.action.EDIT”/>
    </intent-filter>
</receiver>

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

1
2
3
4
5
6
class TestReceiver extends BroadcastReceiver{
    @Override
    public void onReceiver(Context context, Intent intent){
         //这里写处理流程
    }
}

       注意蓝色部分的匹配。

       而在发送方,可以使用:

1
2
3
Intent intent = new Intent();
intent.setAction(Intent.ACTION_EDIT);
TestActivity.this.sendBrodcast(intent);

       注意intent的ACTION需要匹配,否则接收不到这个消息。

       这个程序的大体流程是: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只做一次处理,如果处理过了,那么这个对象就没用了,如果再有同样的广播发送出来,那么操作系统会再生成这样一个对象来处理。


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
ECS使用感受
阿里云服务器初体验
7 0
2021年WEB全栈开发技术栈
随着新工具和技术的发展,开发人员的技术格局一直在变化。在进行了大量面试和阅读了多数的职业描述后,总结了一下 JavaScript 开发人员应该掌握的现代技术栈,或许你使用的是 VUE,或者是 React、Angular 或Svelte 等。
6 0
2021 最新 IntelliJ IDEA 详细配置步骤演示(图文版)(二)
2021 最新 IntelliJ IDEA 详细配置步骤演示(图文版)(二)
2 0
图解 JavaScript 数组方法
JavaScript 数组方法,经常用到的大概 10 个左右,在文章《JavaScript 数组操作必须熟练运用的10个方法》中用文字和代码介绍了各个方法的使用,本文就不做太多的介绍,本文将通过图解析一下常用的数组方法的功能,再补充数组的几个方法。
3 0
高校学生参加飞天加速计划
linux与服阿里云服务器ECS, 阿里云服务器为提供了强大云计算能力。并且平台有很多开发者的使用教程,让我们新手也能很快上手去开发一些网站,希望更多的学生能够加入到阿里云,学习+实战让自己变得更强。
3 0
ECS的初体验
阿里云,阿里巴巴集团旗下云计算品牌,作为全球卓越的云计算技术和服务提供商,不仅为许多企业提供了便利,还专门为学生高校准备了飞天加速计划,让更多学生能解除云、了解云、运用云。推出的学生机适合广大在校大学生、高中生甚至初中生进行学习,只需几步,就能在家轻松搭建一个属于自己的网站,简直是广大TI热爱者的福利
6 0
相亲软件开发,引入缓存后常见的问题及解决办法
相亲软件开发,引入缓存后常见的问题及解决办法
8 0
Apache Log4j2 就在身边, 搜一下项目文件,莫慌
Apache Log4j2 就在身边, 搜一下项目文件,莫慌
5 0
Web 身份验证:Cookie 与 Token | 8月更文挑战
应用开发一般都少不了身份验证,而身份验证机制的稳定性对所有应用程序都变得至关重要。具体选择何种方式进行身份验证可以根据项目及团队情况来衡量,在决定之前需要先理解WEB身份验证常见的两种方式:基于 Cookie 的身份验证和基于令牌(Token)的身份验证。
1 0
一个由“ YYYY-MM-dd ”引发的惨案 元旦来临前警惕
前言 在元旦假期到来之际,我刚好准备出去飘几天,然而在使用一些 App 的时候,竟然被我发现了一个应该是由于前端粗心而导致的 bug,在 2019.12.30 出发,结果 App 上显示的是 2020.12.30(吓得我以为我的订单下错了,此处是不是该把程序员拉去祭天了)。 鉴于可能会有程序员因此而被拉去祭天,而我以前学 Java 的时候就有留意过这个问题,所以我还是把这个问题拿出来说一下,希望能尽量避免这方面的粗心大意(毕竟这种问题也很难测出来)。
4 0
+关注
125
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载