本来昨晚想整理来着,结果竟然太累了直接睡着。。 尽管今天也比较累了,但是还是要咬牙坚持一下将这里的知识整理一下再去娱乐或者休息。。
接触android后,我们知道,非UI线程不能操控UI。 android4.0以后,主线程还不能进行联网操作。 这使得我长期以来养成的编程思路完全找不到思路了。。 因为以前我的思路都是单线程的,即我的操作要么完成,要么抛错,要么阻塞的这样一种非黑即白的情况。 通过在实训的时候,我们学习到了Handler,就是处理这样一个问题的关键。。
先整理一下Handler相关的知识:
Handler,中文释义处理器。
Handler作为一种中介者而存在于两个线程间。 它的核心类有: Handler,Message,MessageQueue,Loop。
Handler线程间通信的方式通过对象实例,也就是地址的方式。
Handler实例化在主线程中 与 其它线程中,它的使用方式是不一样的。
通常Handler的执行方式:在主线程中实例化一个Handler对象;通过 参数传递,或者 地址共享(内部类,继承关系)传递给其它线程;其它线程通过该实例对象发送信息; 信息会先到主线程的MessageQueue等待; 由Looper 按照先进后出的方式从MessageQueue中取出Message,根据Message属性分发给对应的Handler进行处理!
Message相当于一个容器,即可以包含普通消息,也可以包含对象。Message与Hander的关系是独立的。 理解上可以将Handler是对每个message处理的工作者。 也就是说,当一个Activity有较多的ui需要处理的时候,只需要定义一个Handler,然后通过Message的what属性来区别哪些是对应的操作。。 这也是推荐的做法。 还有一种就是,我当时使用的,对每个ui对象都生成一个Handler,每个Handler只对应一个Message。 在使用图中还出现了Hanler的嵌套,十分的难以理解。
对同一个Handler,内部可以有多个Message,用以标志不同的操作。 不同的Handler之间的Message是独立的。
对一个android 应用 主线程 进行断点调试的时候,经常会看到一个类和方法,Looper。 它是在其它的逻辑操作处理完后执行的语句。并且位置主线程不会因为执行完而被回收导致程序结束的。 同时它也是与Handler协作的关键。 子线程如果要用Handler,需要为线程绑定Looper。 绑定后开启loop方法,应该是在线程的结尾。
handler的作用我的理解有俩点: 一,通过handler的消息传递机制,我们可以委托其它线程做一些操作; 二,通过handler的方式,我们可以从用户视角执行代码中的任意代码片段。。。!!! 具体是这样的,一般来说,我们代码在主线程的执行主要是通过语法支撑的 众多函数 连续调用跑起来的。(其本质也就是指令)。 那么我们可以将某个片段封装长一个方法,然后通过Handler执行。。 爽歪歪! 还有一种场景,就是我们可以在代码编译后还能动态修改属性,或者方法,甚至是修改代码,插入代码等等。 也很简单,就是封装成一个方法。 至于插入的代码,我们可以这样,写好一段文本,然后调用编译的方法,最后将编译后的地址传回。。。。 这不就是spring面向切面的思想吗?? 不知道它是具体的实现时怎样的,但是我可以猜测一下,用一个注解代表代码的这个位置放了一个“Handler”,将该“Handler”的设置消息的方式以配置文件的方式开放已达到解耦的目的。 最后就能实现面向切面了。。
子线程使用Looper的步骤: Looper.prepare(); 线程逻辑; Looper.loop();
接着来了解一下基于监听的事件处理机制,与基于回调的事件处理机制与多线程的逻辑:
在早些时候,整理了一下android的两种事件处理机制,刚刚又整理了一下android的事件传递机制。 有了一些感悟与理解,特此记录:
1.事件监听的事件处理机制,与回调的事件处理机制,应该都是多线程的。事件监听时,一个线程用于不断的监听状态的改变和一些简单逻辑的处理,另一个线程负责触发中断; 回调机制时,一个线程用于发出中断,另一个远程的进程,或者线程通过调用回调接口的方法,来实现回调。
2.android的视图组建的监听以及回调的逻辑: 用户触发硬件--> 硬件产生事件发送给操作系统--> 操作系统发送给Android---> Android接收感受到事件,调用回调 ---> 通过回调的属性判断处理后是否继续往外传 ---> 若需要,则往外传---> 被管理器检测到事件,则看是否有注册监听,有则派发给相关监听器。 没有则传递给activity。
3.视图的状态回调是本身的行为,是内部的。 监听器的设置是外部的,需要单独设置。 若相应的事件回调的返回值为false,则会继续往外传给监听器。 也就是说,同一个事件,应该即可以通过状态回调执行一次状态的改变,又可以通过监听的回调实现一些其它的逻辑。 Button控件根据状态 设置
4.多点触控通过事件来识别。 当前面已经存在按下实现,再发送按下事件,就会调用多点触控的事件。。 释放的时候也是同理。。
接着整理一下,关于TextView监听的两个实用的案例:
关键类:TextWatcher,sdk官方的类。
一,在文本输入框实现删除按钮:
核心实现:setCompoundDrawableWithIntrinsicBounds(null,null,图片资源,null); 该方法应该是View提供的一个方法。
触发的事件的核心实现:new Rect().contains(event.getRawX(),event.getRawY());
二, 在文本框中实现 密码的可见与隐藏:
核心实现: new EditText().setTransformationMethod(HideReturnsTransformationMethod.getInstance());
new EditText().setTransformationMethod(PasswordTransformationMethod.getInstance());
接下来整理关于多线程的最后一个处理类,AsyncTask的相关内容:
一,android实现得异步的任务有三种: 一个是handler, 一个是 静态方法:Activity.runOnUiThread(Runnable)的使用。 还有一个就是AsyncTask。
二, AsyncTask第一次接触是在 java的 awt编程中有用到; AsyncTask 相比起Handler显得更简单,快捷。
三, 很多的第三方框架,如Volley, OkHttp, android-async-http,XUtills等都是基于AsyncTask的。
四 , AsyncTast类中的方法,有一些是主线程调用的,有一些是其它线程调用的。 核心方法包括: DoInBackground(params ...); onPostExecute(Result); 既然是在通过了多个线程调用,那么它们应该是通过回调机制实现的。
五,注意事项:Task的实例,execute方法必须在主线程实例和使用。 task只能被执行一次,否则会出现异常。
六. AsyncTast本身就代表了一个非ui线程。 但是它的实现是通过系统给实现的,所以在android层面看不到它的实现。
七. AsyancTast具有三个泛型,
它大概的实现过程:
看到Runnable,我悬着的心终于放下了。。接着调试看看结果:
最后来看一看,主线程是如何通过线程池新开一个线程:
发现内容还是比较多的,要记录的话得找个时间仔细来看看,对自己的成长还是很有必要的。 找个时间,那就明天吧。。 嗯嗯 ,是时候去海皮海皮了!!