大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
Android事件处理的两种模型
濂溪网站建设公司创新互联,濂溪网站设计制作,有大型网站制作公司丰富经验。已为濂溪上千提供企业网站建设服务。企业网站搭建\成都外贸网站建设要多少钱,请找那个售后服务好的濂溪做网站的公司定做!
UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理。
对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事件监听器;对于基于回调的事件处理而言,主要做法是重写Android组件特定的回调函数,Android大部分界面组件都提供了事件响应的回调函数,我们主要重写它们就行。
一 基于监听器的事件处理
相比于基于回调的事件处理,这是更具“面向对象”性质的事件处理方式。在监听器模型中,主要涉及三类对象:
1)事件源Event Source:产生事件的来源,通常是各种组件,如按钮,窗口等。
2)事件Event:事件封装了界面组件上发生的特定事件的具体信息,如果监听器需要获取界面组件上所发生事件的相关信息,一般通过事件Event对象来传递。
3)事件监听器Event Listener:负责监听事件源发生的事件,并对不同的事件做相应的处理。
基于监听器的事件处理机制是一种委派式Delegation的事件处理方式,事件源将整个事件委托给事件监听器,由监听器对事件进行响应处理。这种处理方式将事件源和事件监听器分离,有利于提供程序的可维护性。
举例:
View类中的OnLongClickListener监听器定义如下:(不需要传递事件)
public interface OnLongClickListener {
boolean onLongClick(View v);
}
View类中的OnLongClickListener监听器定义如下:(需要传递事件MotionEvent)
public interface OnTouchListener {
boolean onTouch(View v, MotionEvent event);
}
二 基于回调的事件处理
相比基于监听器的事件处理模型,基于回调的事件处理模型要简单些,该模型中,事件源和事件监听器是合一的,也就是说没有独立的事件监听器存在。当用户在GUI组件上触发某事件时,由该组件自身特定的函数负责处理该事件。通常通过重写Override组件类的事件处理函数实现事件的处理。
举例:
View类实现了KeyEvent.Callback接口中的一系列回调函数,因此,基于回调的事件处理机制通过自定义View来实现,自定义View时重写这些事件处理方法即可。
public interface Callback {
// 几乎所有基于回调的事件处理函数都会返回一个boolean类型值,该返回值用于
// 标识该处理函数是否能完全处理该事件
// 返回true,表明该函数已完全处理该事件,该事件不会传播出去
// 返回false,表明该函数未完全处理该事件,该事件会传播出去
boolean onKeyDown(int keyCode, KeyEvent event);
boolean onKeyLongPress(int keyCode, KeyEvent event);
boolean onKeyUp(int keyCode, KeyEvent event);
boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
}
三 比对
基于监听器的事件模型符合单一职责原则,事件源和事件监听器分开实现;
Android的事件处理机制保证基于监听器的事件处理会优先于基于回调的事件处理被触发;
某些特定情况下,基于回调的事件处理机制会更好的提高程序的内聚性。
四 基于自定义监听器的事件处理流程
在实际项目开发中,我们经常需要自定义监听器来实现自定义业务流程的处理,而且一般都不是基于GUI界面作为事件源的。这里以常见的app自动更新为例进行说明,在自动更新过程中,会存在两个状态:下载中和下载完成,而我们的程序需要在这两个状态做不同的事情,“下载中”需要在UI界面上实时显示软件包下载的进度,“下载完成”后,取消进度条的显示。这里进行一个模拟,重点在说明自定义监听器的事件处理流程。
4.1)定义事件监听器如下:
public interface DownloadListener {
public void onDownloading(int progress); //下载过程中的处理函数
public void onDownloaded(); //下载完成的处理函数
}
4.2)实现下载操作的工具类代码如下:
public class DownloadUtils {
private static DownloadUtils instance = null;
private DownloadUtils() {
}
public static synchronized DownloadUtils instance() {
if (instance == null) {
instance = new DownloadUtils();
}
return instance;
}
private boolean isDownloading = true;
private int progress = 0;
// 实际开发中这个函数需要传入url作为参数,以获取服务器端的安装包位置
public void download(DownloadListener listener) throws InterruptedException {
while (isDownloading) {
listener.onDownloading(progress);
// 下载过程的简单模拟
Thread.sleep(1000);
progress += 10;
if (progress = 100) {
isDownloading = false;
}
}
// 下载完成
listener.onDownloaded();
}
}
4.3)最后在main函数中模拟事件源:
public class DownloadUI {
public static void main(String[] args) {
try {
DownloadUtils.instance().download(new MyDownloadListener());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static class MyDownloadListener implements DownloadListener {
@Override
public void onDownloading(int progress) {
System.out.println("下载进度是:" + progress);
}
@Override
public void onDownloaded() {
System.out.println("下载完成");
}
}
}
之前我们学会了if函数,if函数可以跟很多函数嵌套起来使用,今天我们就一起来看看if函数与AND函数嵌套的例题是如何实现的。
AND函数一般用来检验一组数据是否都满足条件。因此本例实现利用AND函数配合if函数进行成绩评定,即各项成绩都达标时显示"合格”,否则显示“不合格”
1.选中E2单元格,在编辑栏中输入公式=if(AND(b60,c260,d60),"合格",“不合格”),按回车键,即可判断B2、C2、D2单元格的值是否达标,如果都达标,利用if函数显示“合格”;如有一项未达标,利用if函数显示“不合格”。
2.选中E2单元格,向下拖动进行公式填充,可实现快速判断其他人员考评结果,如图所示。
今日的学习内容到此结束你学会了么?祝你每天开心,每天进步点点。
public int getIntExtra(Stringname, int defaultValue)
Since:API Level 1
Retrieve extended data from the intent.
Parameters
name
The name of the desired item.
defaultValue
the value to be returned if no value of the desired type is stored with the given name.
Returns
the value of an item that previously added with putExtra() or the default value if none was found.
以上是getIntExtra()函数在android开发文档中的定义。 该函数的主要功能是从一个键值对中取出一个整型的数据,第一个参数Stringname是数据的键,第二个参数defaultValue是数据的值。 最终该函数讲从intent对象中取出的数据返回。
------------------------------------------
public Intent putExtra(Stringname, int value)
Since:API Level 1
Add extended data to the intent. The name must include a package prefix, for example the app com.android.contacts would use names like "com.android.contacts.ShowAll".
Parameters
name
The name of the extra data, with package prefix.
value
The integer data value.
Returns
Returns the same Intent object, for chaining multiple calls into a single statement.
该函数的功能是给intent对象绑定一个数据,同样地,该数据也是以键值对的形式存储的。第一个参数Stringname是数据的键,第二个参数defaultValue也是数据的值。当intent对象被某个对象接收后,就可以从该intent对象中的StringName键取出对应的Value值,从而达到传递数据的功能。第一个函数getIntExtra()就是取整型数据的一个方法,除此以外还有很多取数据的方法,例如getIntArrayExtra()、getFloatExtra()、getExtras()等等。
总之,看Android相对应的SDK开发文档,是你学习安卓的最有益老师。
希望对你有所帮助,谢谢。
一、函数功能说明
pthread_cond_timedwait 等待一个条件变量,或者超时就会返回
POSIX有两种时钟类型
1、CLOCK_REALTIME: 系统范围内的实时时钟,是个时钟,可以通过命令等方式修改该系统时间.
2、CLOCK_MONOTONIC:系统起机时到现在的时间,不能被设置和修改.
pthread_cond_timedwait()在没有设置条件变量属性的时候,默认用的是CLOCK_REALTIME时间,
因此在极端情况下会出现实际等待的时间与设置的超时时间不同。
所以,对于linux的超时等待功能,最好是使用CLOCK_MONOTONIC进行实现,并且通过pthread_condattr_setclock实现。
而对于android系统而言,是不支持pthread_condattr_setclock,通过验证可以采用函数pthread_cond_timedwait_monotonic实现。
下面直接给出代码的实现功能。
二、超时等待功能
[cpp] view plain copy
#include stdio.h
#include string.h
#include pthread.h
#include sys/time.h
#include sys/times.h
#include unistd.h
#include time.h
static pthread_mutex_t s_mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
void PthreadAttr_Init(void);
unsigned long long getSysTime(void);
void waitTimeout(void);
void PthreadAttr_Init(void)
{
#if defined(ANDROID)
#else
pthread_condattr_t cattr;
int iRet = -1;
iRet = pthread_condattr_init(cattr);
if (iRet != 0)
{
return;
}
pthread_mutex_init(s_mut, NULL);
pthread_condattr_setclock(cattr, CLOCK_MONOTONIC);
pthread_cond_init(s_cond, cattr);
pthread_condattr_destroy(cattr);
#endif
return;
}
void waitTimeout(void)
{
unsigned long long ullbefore = getSysTime();
unsigned long long ullafter = 0;
#if defined(ANDROID)
#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) // 支持ANDROID下NDK的编译,采用相对时间
struct timespec outtime;
memset(outtime, 0x00, sizeof(struct timespec ));
clock_gettime(CLOCK_MONOTONIC, outtime);
outtime.tv_sec += 2;
pthread_mutex_lock(s_mut);
pthread_cond_timedwait_monotonic(s_cond,s_mut, outtime);
pthread_mutex_unlock(s_mut);
ullafter = getSysTime();
printf("####01 interval[%lld] ms\n", ullafter - ullbefore);
#else //支持ANDROID下NDK的编译,采用绝对时间
struct timeval now;
struct itmespec outtime;
gettimeofday(now, NULL);
outtime.tv_sec = now..tv_sec + 3;
outtime.tv_nsec = now.tv_usec * 1000;
pthread_mutex_lock(s_mut);
pthread_cond_timedwait(s_cond, s_mut, outtime);
pthread_mutex_unlock(s_mut);
ullafter = getSysTime();
printf("####02 interval[%lld] ms\n", ullafter - ullbefore);
#endif
#else // 支持LINUX下的编译,采用绝对时间
struct timespec outtime;
memset(outtime, 0x00, sizeof(struct timespec ));
clock_gettime(CLOCK_MONOTONIC, outtime);
outtime.tv_sec += 4;
pthread_mutex_lock(s_mut);
pthread_cond_timedwait(s_cond, s_mut, outtime);
pthread_mutex_unlock(s_mut);
ullafter = getSysTime();
printf("####03 interval[%lld] ms\n", ullafter - ullbefore);
#endif
return;
}
unsigned long long getSysTime(void)
{
unsigned long long milliseconds = 0;
struct tms t_tmsTime;
clock_t t_CurTime;
static int s_clks_per_sec = 0;
if (s_clks_per_sec == 0)
{
s_clks_per_sec = sysconf(_SC_CLK_TCK);
}
if (s_clks_per_sec == 0)
{
return 0;
}
t_CurTime = times(t_tmsTime);
if (1000 % s_clks_per_sec == 0)
{
milliseconds = (1000 /s_clks_per_sec)*(unsigned long long )t_CurTime;//换算成毫秒
}
else
{
milliseconds = 1000 * (unsigned long long )t_CurTime/s_clks_per_sec;//换算成毫秒
}
return milliseconds;
}
int main(void)
{
PthreadAttr_Init();
waitTimeout();
return 0;
}
编译命令:
gcc test_ptthrad_conf_timewait_monotonic.c -o test_ptthrad_conf_timewait_monotonic -lpthread -lrt
linux下的测试结果:
####03 interval[4010] ms
一、对于Android和ios我们要执行不同的操作,下面是判断系统的js代码
// alert(ismobile(1)); 1表示Android,0表示ios
function ismobile(test){
var u = navigator.userAgent, app = navigator.appVersion;
if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){
if(window.location.href.indexOf("?mobile")lt;0){
try{
if(/iPhone|mac|iPod|iPad/i.test(navigator.userAgent)){
return '0';
}else{
return '1';
}
}catch(e){}
}
}else if( u.indexOf('iPad') gt; -1){
return '0';
}else{
return '1';
}
}
二、js调用app端函数,下面是js代码
if(ismobile(1)==1){
Android.setTypeActivity(id,type,href);
}else{
jsToios(id,type,href);
}
setTypeActivity是Android端定义的函数,jsToios是ios端定义的函数,括号里是js端传递的参数。
三、至于js端怎样获取app端的数据,只需在js端提供给app端函数名字,在通知app端调用即可
四、还有一种方法可以不通过app的方法将数据传递给另一个页面,那就是通过URL的方式
在本页面将数据拼接在ip后面
在另外一个页面通过下面方法获取URL后的参数
function GetRequest() {
var url = location.search; //获取url中"?"符后的字串
var theRequest = new Object();
if (url.indexOf("?") != -1) {
var str = url.substr(1);
strs = str.split("");
for(var i = 0; i strs.length; i ++) {
theRequest[strs[i].split("=")[0]]=decodeURIComponent(strs[i].split("=")[1]);
}
}
return theRequest;
}
// 获取URL参数
var Request = new Object();
Request = GetRequest();
var name;
name = Request['name'];
Android Studio 会自动添加 BuildConfig 类,这个类有一个字段叫 DEBUG,它的值根据当前的编译方式自动生成,编译方式为 debug 时值为 true,release 时值为 false。所以可以根据这个特点在函数中添加 if (BuildConfig.DEBUG) 类来实现类似的功能,一个比较常见的例子是自定义 Log 类,使得在 debug 时输出 log,release 时不输出:
public void d(String tag, String message) { if (BuildConfig.DEBUG) { Log.d(tag, message);
}
}