- 浏览: 973525 次
- 性别:
- 来自: 山西
文章分类
最新评论
-
白小默:
你好 可以提供下源码DEMO吗,不知为何,我导出来的excel ...
jxls 使用模板文件导出生成excel -
zkzqzzz:
博主威武!
让微信二维码扫描您的APK -
zkzqzzz:
感谢博主 原来那些类都不是必须的 或者自己写!!博主真棒 ...
抢红包插件实现原理浅析 -
zkzqzzz:
博主 请问你的其他类在哪里呢?
抢红包插件实现原理浅析 -
zkzqzzz:
其他类在哪呢?
抢红包插件实现原理浅析
前言
学习android一段时间了,为了进一步了解android的应用是如何设计开发的,决定详细研究几个开源的android应用。从一些开源应用中吸收点东西,一边进行量的积累,一边探索android的学习研究方向。这里我首先选择了jwood的 Standup Timer 项目。本文将把研究的内容笔记整理,建立一个索引列表。
关键词
Android.os.Handler涉及较多的知识点,我把一些关键词列举在下面,将主要介绍Handler:
android.os.Handler
Handler在android里负责发送和处理消息。它的主要用途有:
1)按计划发送消息或执行某个Runnanble(使用POST方法);
2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程)
默认情况下,Handler接受的是当前线程下的消息循环实例(使用Handler(Looper looper)、Handler(Looper looper, Handler.Callback callback)可以指定线程),同时一个消息队列可以被当前线程中的多个对象进行分发、处理(在UI线程中,系统已经有一个Activity来处理了,你可以再起若干个Handler来处理)。在实例化Handler的时候,Looper可以是任意线程的,只要有Handler的指针,任何线程也都可以sendMessage。Handler对于Message的处理不是并发的。一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的(handleMessage()方法里不应该有耗时操作,可以将耗时操作放在其他线程执行,操作完后发送Message(通过sendMessges方法),然后由handleMessage()更新UI)。
倒计时程序
利用Timer 编写一个倒计时程序,程序使用Timer和TimerTask来完成倒计时,同时使用sendMessages方法发送消息,然后在HanleMessage里更新UI。
Activity布局:
Layout
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/txt" /> <Button android:id="@+id/btnStartTime" android:text="开始计时" android:layout_width="80dip" android:layout_height="wrap_content" ></Button> <Button android:id="@+id/btnStopTime" android:text="停止计时" android:layout_width="80dip" android:layout_height="wrap_content" /> <SeekBar android:id="@+id/SeekBar01" android:layout_width="match_parent" android:layout_height="wrap_content"></SeekBar> </LinearLayout>
这里使用TextView 来显示倒计时的时间变化,两个按钮用于控制时间的开始和停止。SeekBar主要是用于查看线程是否被阻塞(阻塞时无法拖动)。
onCreate
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txt = (TextView) findViewById(R.id.txt); btnStart = (Button) findViewById(R.id.btnStartTime); btnStop = (Button) findViewById(R.id.btnStopTime); Log.d("ThreadId", "onCread:" + String.valueOf(Thread.currentThread().getId())); myHandler = new Handler(this); btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); }
在onCreate方法中初始化元素个元素,myHandler = new Handler(this); 调用的是 Handler(Handler.Callback callback)构造函数,在回调方法callback中对发送来的消息进行处理(这样我们就不必使用内部类的写法来 重写HandleMessage()方法了),因此Activity必须实现 android.os.Handler.Callback 接口。我们还在将onCreate 方法的ThreadId 记录在了Log中用以和消息发送、处理时所作的线程进行比较。
发送消息
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStartTime: startTimer(); break; case R.id.btnStopTime: timer.cancel(); break; } } private synchronized void startTimer() { timer = new Timer(); // TimerTask updateTimerValuesTask = new TimerTask() { // @Override // public void run() { // updateTimerValues(); // } // // }; //自定义的CallBack模式。Task继承自TimerTask Task updateTimerValuesTask = new Task(this); timer.schedule(updateTimerValuesTask, 1000, 1000); } //执行耗时的倒计时任务。 private void updateTimerValues() { total--; Log.d("ThreadId", "send:" + String.valueOf(Thread.currentThread().getId())); Message msg=new Message(); Bundle date = new Bundle();// 存放数据 date.putInt("time", total); msg.setData(date); msg.what=0; myHandler.sendMessage(msg); //另一种写法 // Message msg=myHandler.obtainMessage(); // Bundle date = new Bundle();// 存放数据 // date.putInt("time", total); // msg.setData(date); // msg.what=0; // msg.sendToTarget(); } @Override public void TaskRun() { updateTimerValues(); }
实现Button按钮的事件处理以此进入倒计时操作。这里使用的Timer 来执行定时操作(其实我们完全可以另起一个线程)。Task类继承了TimerTask类,里面增加了一个任务处理接口来实现回调模式,应此Activity需要实现该回调的接口 ITaskCallBack(这样做是因为我比较不喜欢内部类的编写方法)。
ICallBack接口和Task类
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->public interface ITaskCallBack { void TaskRun(); } public class Task extends TimerTask { private ITaskCallBack iTask; public Task(ITaskCallBack iTaskCallBack) { super(); iTask=iTaskCallBack; } public void setCallBack(ITaskCallBack iTaskCallBack) { iTask=iTaskCallBack; } @Override public void run() { // TODO Auto-generated method stub iTask.TaskRun(); } }
这是Java的回调函数的一般写法。
实现CallBack
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> /** * 实现消息处理 */ @Override public boolean handleMessage(Message msg) { switch(msg.what) { case 0: Bundle date=msg.getData(); txt.setText(String.valueOf(date.getInt("time"))); Log.d("ThreadId", "HandlerMessage:" + String.valueOf(Thread.currentThread().getId())); Log.d("ThreadId", "msgDate:" + String.valueOf(date.getInt("time"))); break; } return false; }
可以看到 实现 android.os.Handler.Callback 接口,其实就是对handleMessage()方法进行重写(和内部类的一个区别是,内部类的返回值是Void)。
运行结果
可以看到在onCreate 方法中线程的ID是1(UI线程) 这与 HandlerMessage 进行消息处理时是所作的线程ID是一样的,而消息发送的线程ID则为8非UI线程。
使用Threadle进行实现
Activity类
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> public class ThreadHandlerrActivity extends Activity implements Callback, OnClickListener { private TextView txt; private Button btnStart, btnStop; private Handler myHandler; private TimerThread timerThread; private int Total=30; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txt = (TextView) findViewById(R.id.txt); btnStart = (Button) findViewById(R.id.btnStartTime); btnStop = (Button) findViewById(R.id.btnStopTime); Log.d("ThreadId", "onCread:" + String.valueOf(Thread.currentThread().getId())); myHandler = new Handler(this); btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); } /** * 实现消息处理 */ @Override public boolean handleMessage(Message msg) { switch(msg.what) { case 0: Bundle date=msg.getData(); txt.setText(String.valueOf(date.getInt("time"))); Log.d("ThreadId", "HandlerMessage:" + String.valueOf(Thread.currentThread().getId())); Log.d("ThreadId", "msgDate:" + String.valueOf(date.getInt("time"))); break; } return false; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStartTime: //自定义的线程 timerThread=new TimerThread(myHandler,60); timerThread.start(); break; case R.id.btnStopTime: timerThread.stop(); //timerThread.destroy(); break; } } }
自定义的线程类
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->** * 自定义的线程类,通过传入的Handler,和Total 定期执行耗时操作 * @author linzijun * */ public class TimerThread extends Thread { public int Total=60; public Handler handler; /** * 初始化构造函数 * @param mhandler handler 用于发送消息 * @param total 总周期 */ public TimerThread(Handler mhandler,int total) { super(); handler=mhandler; Total=total; } @Override public void run() { while(true) { Total--; if(Total<0) break; try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message msg=new Message(); Bundle date = new Bundle();// 存放数据 date.putInt("time", Total); msg.setData(date); msg.what=0; Log.d("ThreadId", "Thread:" + String.valueOf(Thread.currentThread().getId())); handler.sendMessage(msg); } super.run(); } }
这里继承了Thread类,也可以直接实现 Runnable接口。
关于POST
Post的各种方法是把一个Runnable发送给消息队列,它将在到达时进行处理。
POST
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> public class PostHandler extends Activity implements OnClickListener, Runnable { private TextView txt; private Button btnStart, btnStop; private Handler myHandler; private Timer timer; private int total = 60; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main); txt = (TextView) findViewById(R.id.txt); btnStart = (Button) findViewById(R.id.btnStartTime); btnStop = (Button) findViewById(R.id.btnStopTime); Log.d("ThreadId", "onCread:" + String.valueOf(Thread.currentThread().getId())); myHandler = new Handler() { @Override public void handleMessage(Message msg) { switch(msg.what) { case 0: Bundle date=msg.getData(); txt.setText(String.valueOf(date.getInt("time"))); Log.d("ThreadId", "HandlerMessage:" + String.valueOf(Thread.currentThread().getId())); Log.d("ThreadId", "msgDate:" + String.valueOf(date.getInt("time"))); break; } } }; btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStartTime: //myHandler.post(this); myHandler.postDelayed(this, 1000); break; case R.id.btnStopTime: break; } } @Override public void run() { while(true) { total--; if(total<0) break; try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message msg=new Message(); Bundle date = new Bundle();// 存放数据 date.putInt("time", total); msg.setData(date); msg.what=0; Log.d("ThreadId", "POST:" + String.valueOf(Thread.currentThread().getId())); myHandler.sendMessage(msg); Log.d("ThreadId", "Thread:" + String.valueOf(Thread.currentThread().getId())); } } }
使用POST的方式 是将Runnable 一起发送给处理的线程(这里为UI),如果Runnable的操作比较耗时的话那线程将进入阻塞状态。可以看到先运行 Runnable的Run方法 然后在进入 HandleMessage() 。我还尝试了另一种写法,将TimerThreadPOST过去,运行结果是一样的。
代码
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->package zijunlin.me; import java.util.Timer; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class PostHandler extends Activity implements OnClickListener, Runnable { private TextView txt; private Button btnStart, btnStop; private Handler myHandler; private Timer timer; private int total = 60; private TimerThread timerThread; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main); txt = (TextView) findViewById(R.id.txt); btnStart = (Button) findViewById(R.id.btnStartTime); btnStop = (Button) findViewById(R.id.btnStopTime); Log.d("ThreadId", "onCread:" + String.valueOf(Thread.currentThread().getId())); myHandler = new Handler() { @Override public void handleMessage(Message msg) { switch(msg.what) { case 0: Bundle date=msg.getData(); txt.setText(String.valueOf(date.getInt("time"))); Log.d("ThreadId", "HandlerMessage:" + String.valueOf(Thread.currentThread().getId())); Log.d("ThreadId", "msgDate:" + String.valueOf(date.getInt("time"))); break; } } }; btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStartTime: //myHandler.post(this); //myHandler.postDelayed(this, 1000); timerThread=new TimerThread(myHandler,60); myHandler.post(timerThread); break; case R.id.btnStopTime: break; } } @Override public void run() { while(true) { total--; if(total<0) break; try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message msg=new Message(); Bundle date = new Bundle();// 存放数据 date.putInt("time", total); msg.setData(date); msg.what=0; Log.d("ThreadId", "POST:" + String.valueOf(Thread.currentThread().getId())); myHandler.sendMessage(msg); Log.d("ThreadId", "Thread:" + String.valueOf(Thread.currentThread().getId())); } } }
可以说POST的各种方法主要是用于 “按计划发送消息或执行某个Runnanble(使用POST方法)”。
参考文献
发表评论
-
Android客户端代码保护技术-完整性校验
2018-01-08 17:10 1317由于Android系统固有的缺陷、Android应用分发 ... -
android开发中手动v2签名实现方法
2018-01-08 10:31 1121用v2签名前要进行v1签名或zipalign。 1. z ... -
webview支持LocalStorage本地存储
2017-03-31 10:30 1396//允许JavaScript执行 ... -
七步配置phonegap+cordova+ionic开发环境
2016-12-19 16:21 727本文讲的是Android混合 ... -
梆梆加固破解
2016-10-13 09:01 1575本文假设你已经使用过梆梆加固,手头至少有个一个通过梆梆加固后 ... -
android zxing 扫描二维码 横屏转竖屏
2016-09-14 15:41 0Zxing 竖屏切换 Android 在google上下 ... -
封装Volley使Volley的每个请求都自动保存和发送Cookie
2016-09-14 10:57 0思路很简单,每次请求获取到服务器返回的response就解 ... -
Android二维码ZXing扫描区域大小的调整,提高扫描速度
2016-09-14 10:48 2681Zxing本身默认的扫图区域最大只有 360*480 ... -
解决Android二维码扫描ZXing竖屏拉伸变长闪退扫描区域小等问题
2016-09-14 10:42 1296Android 基于google Zxing实现二维码、条形 ... -
Android平台下利用zxing实现二维码开发
2016-09-14 09:25 519现在走在大街小巷都能看到二维码,而且最近由于项目需要,所以研 ... -
Zxing扫描二维码
2016-09-14 09:24 697摘要 android Zxing扫描二维码 横竖屏 ... -
Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
2016-09-14 09:18 546转载请注明出处:http://blog.csdn.net/x ... -
React Native应用部署/热更新-CodePush最新集成总结
2016-08-02 11:06 610本文出自《React Native学习笔记》系列文章。 ... -
让微信二维码扫描您的APK
2016-07-27 11:26 1554二维码深入人心,很多App都在官网挂出了可以扫描下载apk的 ... -
Activity类的runOnUiThread方法
2016-07-22 10:40 803[javascript] view plain c ... -
Can't create handler inside thread that has not called Looper.prepare()
2016-07-22 10:24 664错误信息:在Android开发中,如果在一个Thread中启 ... -
Android编程之解决android-support-v4打包问题
2016-07-21 09:27 585如果工程引入了android-support-v4的jar类 ... -
Android 编程下的代码混淆之(android-support-v4.jar)
2016-07-21 09:24 426项目在代码混淆过程中如果引用了第三方 Jar 包,需要在混淆 ... -
phoneGap可行性分析
2016-07-20 16:25 5431 移动应用现状 移动应用产品往往常 ... -
梆梆SDKs详细分析(1) - 防界面劫持SDK
2016-07-20 10:23 818前言 前段时间,国外知名的安全公司fireeye发 ...
相关推荐
【Android Handler机制】是Android应用程序中用于线程间通信的核心组件,它与Looper和Message紧密配合,实现消息的发送、处理以及线程间的同步。在Android应用开发中,尤其是涉及到UI更新时,Handler机制显得尤为...
在Android开发中,`Handler`、`Message`和`Looper`是实现线程间通信的重要机制,特别是当需要在主线程(UI线程)和工作线程之间传递数据时。本示例“Android Handler传值的demo”将帮助我们深入理解这一机制。 `...
在“androidHandler测试的demo”中,我们可以预期包含以下内容: 1. 创建自定义`Handler`子类:这个子类可能重写了`handleMessage(Message msg)`方法,根据`msg.what`的值执行不同的操作,比如更新UI元素或执行特定...
在Android开发中,Handler、Looper和Message是实现线程间通信的重要组件,它们共同构建了Android的消息处理机制。本文将详细分析Android Handler消息处理的顺序,以及如何利用这些组件进行异步操作。 首先,理解...
【标题】"老罗android Handler综合练习 图文混排 服务器端源代码"涉及的是Android应用开发中的关键知识点,主要集中在Handler机制、图文混排以及服务器端的数据交互。Handler是Android系统中用于线程间通信的重要...
由于Android的单线程模型,直接在后台线程更新UI是不允许的,这时就需要用到Handler、Looper和Message机制来实现跨线程通信,特别是用于模拟进度条更新,让用户体验更加友好。本篇文章将深入探讨如何使用Android ...
在Android开发中,`Handler`是一个至关重要的组件,它用于处理与线程通信相关的任务,尤其是在主线程(UI线程)和工作线程之间。`Handler`、`Looper`和`Message`三者共同构成了Android的消息传递机制。下面将详细...
# Android Handler解析 在Android应用开发中,保持应用程序的响应性是至关重要的。为了实现这一目标,我们需要确保UI线程不会被阻塞。通常来说,将耗时的任务(如网络请求、复杂计算等)放到后台线程执行可以提高UI...
在Android开发中,`Handler`、`Looper`和`Message`是实现线程间通信的重要组件,特别是用于主线程(UI线程)与其他工作线程之间的交互。标题“android handler的一些测试”暗示我们将探讨`Handler`如何在多线程环境...
Android Handler类详解 Android Handler类详解 Android Handler类详解 Android Handler类详解
### Android Handler运行原理详解 #### 一、引言 在Android开发中,线程间通信是非常重要的技术之一,其中Handler机制被广泛应用于实现主线程与子线程之间的数据交互。Handler机制不仅简单易用,而且功能强大,是...
Android Handler机制的工作原理详析 Android Handler机制是Android系统中的一种消息机制,负责处理应用程序中的消息处理和线程之间的通信。Handler机制的工作原理可以分为以下几个部分:Looper、MessageQueue、...
Handler是Android中的一个类,它用于在不同的线程之间发送和处理消息。通常,我们使用Handler配合Looper和Message来实现在主线程(UI线程)中执行后台任务的结果。Looper是消息队列的循环器,它不断检查消息队列并...
在Android开发中,`Handler` 是一个至关重要的组件,它涉及到多线程、UI更新以及消息传递机制。本文将深入探讨 `Handler` 的工作原理,分析其如何在不同线程间进行通信,并通过实例代码来展示其具体用法。 ### ...
在Android系统中,Handler、Looper和Message构成了一个用于线程间通信的重要机制。这个机制使得UI线程可以处理来自其他线程的消息,从而避免了直接在非UI线程操作UI组件,防止应用出现ANR(Application Not ...
在Android开发中,Handler是一种非常重要的组件,它与线程通信密切相关,特别是在更新UI和处理异步任务时。本文将深入探讨如何利用Handler构建一个图片浏览器,并结合计时器(Timer)来实现特定功能。 首先,理解...
Android Handler机制解析 Android Handler机制是Android系统中的一种机制,用于处理线程之间的通信和消息传递。在Android系统中,Handler机制是基于Java的线程机制来实现的。下面将对Android Handler机制进行详细的...
在Android应用开发中,Handler是实现线程间通信的关键组件,尤其在涉及到UI更新时,它的作用尤为重要。本文将深入探讨“Android Handler定时更新UI”的相关知识点,以及如何使用CounterDemo来实现这一功能。 首先,...
【Android Handler 使用详解】 Handler 是 Android 平台中用于处理线程间通信的关键组件,尤其在涉及 UI(用户界面)更新时,它扮演着至关重要的角色。在 Android 应用程序启动时,系统会默认创建一个主线程,也...
在Android开发中,`Handler`、`Thread`、`Toast`、`消息队列`以及`线程`是实现UI交互和异步处理的关键概念。本文将深入探讨这些概念,并结合给定的"Android Handler 线程 示例代码"进行详细讲解。 首先,我们来看`...