Android应用开发之所有动画使用详解

1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让全面说说Android的动画,所以今天来一发Android应用的各种Animation大集合。英文厉害的请直接移步参考Android Developer。 Android系统提供了很多丰富的API去实现UI的2D与3D动画,最主要的划分可以分为如下几类: View Animation: 视图动画在古老的Android版本系统中就已经提供了,只能被用来设置View的动画。 Drawable Animation: 这种动画(也叫Frame动画、帧动画)其实可以划分到视图动画的类别,专门用来一个一个的显示Drawable的resources,就像放幻灯片一样。 Property Animation: 属性动画只对Android 3.0(API 11)以上版本的Android系统才有效,这种动画可以设置给任何Object,包括那些还没有渲染到屏幕上的对象。这种动画是可扩展的,可以让你自定义任何类型和属性的动画。 可以看见,当前应用程序开发涉及的主要动画也就这三大类,我们接下来以类别为基础来慢慢展开说明。 【工匠若水 http://blog.csdn.net/yanbober 转载请注明出处。点我开始Android技术交流】 2 View Animation(视图动画)使用详解 2-1 视图动画概述 视图动画,也叫Tween(补间)动画可以在一个视图容器内执行一系列简单变换(位置、大小、旋转、透明度)。譬如,如果你有一个TextView对象,您可以移动、旋转、缩放、透明度设置其文本,当然,如果它有一个背景图像,背景图像会随着文本变化。 补间动画通过XML或Android代码定义,建议使用XML文件定义,因为它更具可读性、可重用性。 如下是视图动画相关的类继承关系: java类名 xml关键字 描述信息 AlphaAnimation <alpha> 放置在res/anim/目录下 渐变透明度动画效果 RotateAnimation <rotate> 放置在res/anim/目录下 画面转移旋转动画效果 ScaleAnimation <scale> 放置在res/anim/目录下 渐变尺寸伸缩动画效果 TranslateAnimation <translate> 放置在res/anim/目录下 画面转换位置移动动画效果 AnimationSet <set> 放置在res/anim/目录下 一个持有其它动画元素alpha、scale、translate、rotate或者其它set元素的容器 通过上图和上表可以直观的看出来补间动画的关系及种类了吧,接下来我们就详细一个一个的介绍一下各种补间动画。 2-2 视图动画详细说明 可以看出来Animation抽象类是所有补间动画类的基类,所以基类会提供一些通用的动画属性方法,如下我们就来详细看看这些属性,关于这些属性详细官方解释翻墙点击我或者翻墙点击我。 2-2-1 Animation属性详解 xml属性 java方法 解释 android:detachWallpaper setDetachWallpaper(boolean) 是否在壁纸上运行 android:duration setDuration(long) 动画持续时间,毫秒为单位 android:fillAfter setFillAfter(boolean) 控件动画结束时是否保持动画最后的状态 android:fillBefore setFillBefore(boolean) 控件动画结束时是否还原到开始动画前的状态 android:fillEnabled setFillEnabled(boolean) 与android:fillBefore效果相同 android:interpolator setInterpolator(Interpolator) 设定插值器(指定的动画效果,譬如回弹等) android:repeatCount setRepeatCount(int) 重复次数 android:repeatMode setRepeatMode(int) 重复类型有两个值,reverse表示倒序回放,restart表示从头播放 android:startOffset setStartOffset(long) 调用start函数之后等待开始运行的时间,单位为毫秒 android:zAdjustment setZAdjustment(int) 表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal 也就是说,无论我们补间动画的哪一种都已经具备了这种属性,也都可以设置使用这些属性中的一个或多个。 ...

2015年8月13日 · 8 分钟 · 天边的星星

AndroidStudio快捷键

Ctrl+G / Ctrl+Alt+Shift+G:查询变量或者函数或者类在哪里被使用或被调用,后者是前者的复杂表现,可以选择查询范围等。 Alt+H:查找功能,全局查找 F4:查看类继承关系 F2:查看文档说明(函数使用说明) Ctrl+E:查看最近打开过的文件 Ctrl+Shift+E:查看最近编辑过的文件 double Shift:全局查找,这个查看和Alt+H稍稍有些不同,这个是全局文件查找,到文件名称层面。 Ctrl+Shift+R:快速定位到你所想打开的文件。 Alt+↑:光标所在位置那行代码往上移动 Alt+↓:光标所在位置那行代码往下移动 Ctrl+D:删除光标所在位置那行代码 Ctrl+X:剪切光标所在位置那行代码 Alt+Shift+↓/Ctrl+C:复制光标所在行代码到下一行 Ctrl+O:快捷查找当前类中的函数,变量 Ctrl+Shift+R:修改名称 Alt+Enter:导入包 Alt+←:后退,定位到上个查看或者编辑的地方 Alt+→:往前定位,比如你定位到上个点后,想回去,就可以用这个快捷键 Ctrl+/:当行注释,反注释再按一次即可 Ctrl+Shift+/:模块注释,反注释再按一次即可,注意这边的”/“不能用小键盘的 Ctrl+Shift+小键盘/:折叠代码(Ctrl+Shift+小键盘*这个不灵了,今天没空了,后面会针对这个问题做解决,并更新上来),当然笔记本没小键盘,你可以自己改快捷键 Ctrl+Alt+S:打开settings界面 Ctrl+Alt+Shift+S:打开Project Structure界面 Alt+Shift+X:运行(Run) Alt+Shift+D:调试运行(Debug) Ctrl+F9:编译工程 Ctrl+Shift+K:push文件到Server(git) Debug类快捷键 F5:但不调试进入函数内部。 F6:但不调试不进入函数内部。 F7:由函数内部返回调用处。 F8:执行到下一个断点,没断点则执行完成。 Action Mac OSX Win/Linux 注释代码(//) Cmd + / Ctrl + / 注释代码(/**/) Cmd + Option + / Ctrl + Shift + / 格式化代码 Cmd + Option + L Ctrl + Alt + L 清除无效包引用 Option + Control + O Alt + Ctrl + O 查找 Cmd + F Ctrl + F 查找+替换 Cmd + R Ctrl + R 上下移动代码 Option + Shift + Up/Down Alt + Shift + Up/Down 删除行 Cmd + Delete Ctrl + Y 扩大缩小选中范围 Option + Up/Down Ctrl + W/Ctrl + Shift + W 快捷生成结构体 Cmd + Option + T Ctrl + Alt + T 快捷覆写方法 Ctrl + O Ctrl + O 快捷定位到行首/尾 Cmd + Left/Right Ctrl + Left/Right 折叠展开代码块 Cmd + Plus,Minus Ctrl + Plus/Minus 折叠展开全部代码块 Cmd + Shift + Plus,Minus Ctrl + Shift + Plus,Minus 文件方法结构 Cmd + F12 Ctrl + F12 查找调用的位置 Ctrl + Option + H Ctrl + Alt + H 大小写转换 Cmd + Shift + U Ctrl + Shift + U ...

2015年8月7日 · 2 分钟 · 天边的星星

Android编程心得-在Assets文件夹中放入.sql文件实现创建SQlite表的操作

当我们在使用SQLiteOpenHelper时,经常使用db.execSQL(String sql)方法写入对应语句实现创建表的操作,这样的确可以实现业务逻辑。与此同时还有一种更灵活的方法,从assets文件夹下读取对应的.sql文件,然后创建表。 1.首先在工程的assets文件夹下,添加对应的.sql文件 2.配置一个Configuration类,用于保存固定路径变量 **[java]** [view plain](http://blog.csdn.net/yangqicong11/article/details/21396437#)[copy](http://blog.csdn.net/yangqicong11/article/details/21396437#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/240525)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/240525/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">public</span> <span class="keyword">class</span> Configuration { - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String DB_PATH = <span class="string">&#8220;schema&#8221;</span>; - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String DB_NAME = <span class="string">&#8220;test.db&#8221;</span>; - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DB_VERSION = <span class="number">1</span>; - - } ...

2015年8月7日 · 2 分钟 · 天边的星星

Android库Volley的使用介绍

Android Volley 是Google开发的一个网络lib,可以让你更加简单并且快速的访问网络数据。Volley库的网络请求都是异步的,你不必担心异步处理问题。 Volley的优点: 请求队列和请求优先级 请求Cache和内存管理 扩展性性强 可以取消请求 下载和编译volley.jar 需要安装git,ant,android sdk clone代码: git clone https://android.googlesource.com/platform/frameworks/volley 编译jar: android update project -p . ant jar 添加volley.jar到你的项目中 不过已经有人将volley的代码放到github上了: https://github.com/mcxiaoke/android-volley,你可以使用更加简单的方式来使用volley: Maven format: jar <span class="tag"><<span class="title">dependency</span>></span> <span class="tag"><<span class="title">groupId</span>></span>com.mcxiaoke.volley<span class="tag"></<span class="title">groupId</span>></span> <span class="tag"><<span class="title">artifactId</span>></span>library<span class="tag"></<span class="title">artifactId</span>></span> <span class="tag"><<span class="title">version</span>></span>1.0.6<span class="tag"></<span class="title">version</span>></span> <span class="tag"></<span class="title">dependency</span>></span> Gradle format: jar compile 'com.mcxiaoke.volley:library:1.0.6' Volley工作原理图 {.fancybox} 创建Volley 单例 使用volley时,必须要创建一个请求队列RequestQueue,使用请求队列的最佳方式就是将它做成一个单例,整个app使用这么一个请求队列。 <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AppController</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>{ <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = AppController.class .getSimpleName(); <span class="keyword">private</span> RequestQueue mRequestQueue; <span class="keyword">private</span> ImageLoader mImageLoader; <span class="keyword">private</span> <span class="keyword">static</span> AppController mInstance; <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span>() { <span class="keyword">super</span>.onCreate(); mInstance = <span class="keyword">this</span>; } <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> AppController <span class="title">getInstance</span>() { <span class="keyword">return</span> mInstance; } <span class="keyword">public</span> RequestQueue <span class="title">getRequestQueue</span>() { <span class="keyword">if</span> (mRequestQueue == <span class="keyword">null</span>) { mRequestQueue = Volley.newRequestQueue(getApplicationContext()); } <span class="keyword">return</span> mRequestQueue; } <span class="keyword">public</span> ImageLoader <span class="title">getImageLoader</span>() { getRequestQueue(); <span class="keyword">if</span> (mImageLoader == <span class="keyword">null</span>) { mImageLoader = <span class="keyword">new</span> ImageLoader(<span class="keyword">this</span>.mRequestQueue, <span class="keyword">new</span> LruBitmapCache()); } <span class="keyword">return</span> <span class="keyword">this</span>.mImageLoader; } <span class="keyword">public</span> <T> <span class="keyword">void</span> <span class="title">addToRequestQueue</span>(Request<T> req, String tag) { <span class="comment">// set the default tag if tag is empty</span> req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); getRequestQueue().add(req); } <span class="keyword">public</span> <T> <span class="keyword">void</span> <span class="title">addToRequestQueue</span>(Request<T> req) { req.setTag(TAG); getRequestQueue().add(req); } <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">cancelPendingRequests</span>(Object tag) { <span class="keyword">if</span> (mRequestQueue != <span class="keyword">null</span>) { mRequestQueue.cancelAll(tag); } } } 另外,你还需要一个Cache来存放请求的图片: ...

2015年8月6日 · 6 分钟 · 天边的星星

Android Paint之 setXfermode PorterDuffXfermode 讲解,androidsetxfermode

转载来自: http://blog.csdn.net/tianjian4592 前面关于paint的方法讲解里,讲到 setXfermode 就截止了,原因有两个: 那篇文章已经太长了,我自己都看不下去了; 2. setXfermode 在paint 里占有至关重要的地位; 基于以上两个原因,我们一起来看看这个方法有何妙用。 首先我们还是来看看关于这个方法的说明: /** * Set or clear the xfermode object. - 设置或清除xfermode对象; * Pass null to clear any previous xfermode. - 传递null以清除任何以前的xfermode。 * As a convenience, the parameter passed is also returned. - 为方便起见,也返回传递的参数。 * * @return xfermode */ public Xfermode setXfermode(Xfermode xfermode) { int xfermodeNative = 0; if (xfermode != null) xfermodeNative = xfermode.native_instance; native_setXfermode(mNativePaint, xfermodeNative); mXfermode = xfermode; return xfermode; } 这个方法传进一个 Xfermode 对象,而打开 Xfermode 发现里面没有提供任何可用的构造函数或方法,ctrl +T 看到它有三个子类: ...

2015年8月6日 · 8 分钟 · 天边的星星

Android 快速开发系列 ORMLite 框架最佳实践

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39122981,本文出自【张鸿洋的博客】 上一篇已经对ORMLite框架做了简单的介绍:Android ORMLite 框架的入门用法~~本篇将介绍项目可能会使用到的一些用法,也为我们的使用ORMLite框架总结出一个较合理的用法。 通过上一篇的了解,我们使用ORMLite,需要自己写一个DatabaseHelper去继承OrmLiteSqliteOpenHelper,下面我们首先给出一个我认为比较靠谱的Helper的写法: 1、DatabaseHelper **[java]** [view plain](http://blog.csdn.net/lmj623565791/article/details/39122981#)[copy](http://blog.csdn.net/lmj623565791/article/details/39122981#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/465469)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/465469/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.zhy.zhy_ormlite.db; - - <span class="keyword">import</span> java.sql.SQLException; - <span class="keyword">import</span> java.util.HashMap; - <span class="keyword">import</span> java.util.Map; - - <span class="keyword">import</span> android.content.Context; - <span class="keyword">import</span> android.database.sqlite.SQLiteDatabase; - - <span class="keyword">import</span> com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; - <span class="keyword">import</span> com.j256.ormlite.dao.Dao; - <span class="keyword">import</span> com.j256.ormlite.support.ConnectionSource; - <span class="keyword">import</span> com.j256.ormlite.table.TableUtils; - <span class="keyword">import</span> com.zhy.zhy_ormlite.bean.Article; - <span class="keyword">import</span> com.zhy.zhy_ormlite.bean.Student; - <span class="keyword">import</span> com.zhy.zhy_ormlite.bean.User; - - <span class="keyword">public</span> <span class="keyword">class</span> DatabaseHelper <span class="keyword">extends</span> OrmLiteSqliteOpenHelper - { - <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String TABLE_NAME = <span class="string">&#8220;sqlite-test.db&#8221;</span>; - - <span class="keyword">private</span> Map<String, Dao> daos = <span class="keyword">new</span> HashMap<String, Dao>(); - - <span class="keyword">private</span> DatabaseHelper(Context context) - { - <span class="keyword">super</span>(context, TABLE_NAME, <span class="keyword">null</span>, <span class="number">4</span>); - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onCreate(SQLiteDatabase database, - ConnectionSource connectionSource) - { - <span class="keyword">try</span> - { - TableUtils.createTable(connectionSource, User.<span class="keyword">class</span>); - TableUtils.createTable(connectionSource, Article.<span class="keyword">class</span>); - TableUtils.createTable(connectionSource, Student.<span class="keyword">class</span>); - } <span class="keyword">catch</span> (SQLException e) - { - e.printStackTrace(); - } - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onUpgrade(SQLiteDatabase database, - ConnectionSource connectionSource, <span class="keyword">int</span> oldVersion, <span class="keyword">int</span> newVersion) - { - <span class="keyword">try</span> - { - TableUtils.dropTable(connectionSource, User.<span class="keyword">class</span>, <span class="keyword">true</span>); - TableUtils.dropTable(connectionSource, Article.<span class="keyword">class</span>, <span class="keyword">true</span>); - TableUtils.dropTable(connectionSource, Student.<span class="keyword">class</span>, <span class="keyword">true</span>); - onCreate(database, connectionSource); - } <span class="keyword">catch</span> (SQLException e) - { - e.printStackTrace(); - } - } - - <span class="keyword">private</span> <span class="keyword">static</span> DatabaseHelper instance; - - <span class="comment">/**</span> - <span class="comment"> * 单例获取该Helper</span> - <span class="comment"> * </span> - <span class="comment"> * @param context</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> DatabaseHelper getHelper(Context context) - { - context = context.getApplicationContext(); - <span class="keyword">if</span> (instance == <span class="keyword">null</span>) - { - <span class="keyword">synchronized</span> (DatabaseHelper.<span class="keyword">class</span>) - { - <span class="keyword">if</span> (instance == <span class="keyword">null</span>) - instance = <span class="keyword">new</span> DatabaseHelper(context); - } - } - - <span class="keyword">return</span> instance; - } - - <span class="keyword">public</span> <span class="keyword">synchronized</span> Dao getDao(Class clazz) <span class="keyword">throws</span> SQLException - { - Dao dao = <span class="keyword">null</span>; - String className = clazz.getSimpleName(); - - <span class="keyword">if</span> (daos.containsKey(className)) - { - dao = daos.get(className); - } - <span class="keyword">if</span> (dao == <span class="keyword">null</span>) - { - dao = <span class="keyword">super</span>.getDao(clazz); - daos.put(className, dao); - } - <span class="keyword">return</span> dao; - } - - <span class="comment">/**</span> - <span class="comment"> * 释放资源</span> - <span class="comment"> */</span> - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> close() - { - <span class="keyword">super</span>.close(); - - <span class="keyword">for</span> (String key : daos.keySet()) - { - Dao dao = daos.get(key); - dao = <span class="keyword">null</span>; - } - } - - } 1、整个DatabaseHelper使用单例只对外公布出一个对象,保证app中只存在一个SQLite Connection , 参考文章:http://www.touchlab.co/2011/10/single-sqlite-connection/ ...

2015年8月5日 · 10 分钟 · 天边的星星

Android使用UncaughtExceptionHandler捕获全局异常

Android系统的“程序异常退出”,给应用的用户体验造成不良影响。为了捕获应用运行时异常并给出友好提示,便可继承UncaughtExceptionHandler类来处理。通过Thread.setDefaultUncaughtExceptionHandler()方法将异常处理类设置到线程上即可。 1、异常处理类,代码如下: **[java]** [view plain](http://blog.csdn.net/hehe9737/article/details/7662123#)[copy](http://blog.csdn.net/hehe9737/article/details/7662123#) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">public</span> <span class="keyword">class</span> CrashHandler <span class="keyword">implements</span> UncaughtExceptionHandler { - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = <span class="string">&#8220;CrashHandler&#8221;</span>; - <span class="keyword">private</span> <span class="keyword">static</span> CrashHandler INSTANCE = <span class="keyword">new</span> CrashHandler(); - <span class="keyword">private</span> Context mContext; - <span class="keyword">private</span> Thread.UncaughtExceptionHandler mDefaultHandler; - - <span class="keyword">private</span> CrashHandler() { - } - - <span class="keyword">public</span> <span class="keyword">static</span> CrashHandler getInstance() { - <span class="keyword">return</span> INSTANCE; - } - - <span class="keyword">public</span> <span class="keyword">void</span> init(Context ctx) { - mContext = ctx; - mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); - Thread.setDefaultUncaughtExceptionHandler(<span class="keyword">this</span>); - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> uncaughtException(Thread thread, Throwable ex) { - <span class="comment">// if (!handleException(ex) && mDefaultHandler != null) {</span> - <span class="comment">// mDefaultHandler.uncaughtException(thread, ex);</span> - <span class="comment">// } else {</span> - <span class="comment">// android.os.Process.killProcess(android.os.Process.myPid());</span> - <span class="comment">// System.exit(10);</span> - <span class="comment">// }</span> - System.out.println(<span class="string">&#8220;uncaughtException&#8221;</span>); - - <span class="keyword">new</span> Thread() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> run() { - Looper.prepare(); - <span class="keyword">new</span> AlertDialog.Builder(mContext).setTitle(<span class="string">&#8220;提示&#8221;</span>).setCancelable(<span class="keyword">false</span>) - .setMessage(<span class="string">&#8220;程序崩溃了&#8230;&#8221;</span>).setNeutralButton(<span class="string">&#8220;我知道了&#8221;</span>, <span class="keyword">new</span> OnClickListener() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onClick(DialogInterface dialog, <span class="keyword">int</span> which) { - System.exit(<span class="number"></span>); - } - }) - .create().show(); - Looper.loop(); - } - }.start(); - } - - <span class="comment">/**</span> - <span class="comment"> * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑</span> - <span class="comment"> *</span> - <span class="comment"> * @param ex</span> - <span class="comment"> * @return true:如果处理了该异常信息;否则返回false</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> handleException(Throwable ex) { - <span class="keyword">if</span> (ex == <span class="keyword">null</span>) { - <span class="keyword">return</span> <span class="keyword">true</span>; - } - <span class="comment">// new Handler(Looper.getMainLooper()).post(new Runnable() {</span> - <span class="comment">// @Override</span> - <span class="comment">// public void run() {</span> - <span class="comment">// new AlertDialog.Builder(mContext).setTitle(&#8220;提示&#8221;)</span> - <span class="comment">// .setMessage(&#8220;程序崩溃了&#8230;&#8221;).setNeutralButton(&#8220;我知道了&#8221;, null)</span> - <span class="comment">// .create().show();</span> - <span class="comment">// }</span> - <span class="comment">// });</span> - - <span class="keyword">return</span> <span class="keyword">true</span>; - } - } 2、线程绑定异常处理类 ...

2015年8月5日 · 2 分钟 · 天边的星星

Android studio使用Annotations框架

首页创建Android studio项目 在项目的build.gradle中添加如下代码(如此简单) buildscript { repositories { mavenCentral() } dependencies { // replace with the current version of the Android plugin classpath ‘com.android.tools.build:gradle:1.2.3’ // the latest version of the android-apt plugin classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.4’ } } repositories { mavenCentral() mavenLocal() } apply plugin: ‘com.android.application’ apply plugin: ‘android-apt’ def AAVersion = ‘3.3.2’//这个是Annotations的版本号,这个可以去Annotations官网查看,也可以在Android studio中Jcenter或者mavenCentral中查找最新版本号 dependencies { compile fileTree(include: [‘*.jar’], dir: ‘libs’) compile ‘com.android.support:appcompat-v7:22.2.0’ apt “org.androidannotations:androidannotations:AAVersion” compile “org.androidannotations:androidannotations-api:AAVersion” } apt { arguments { androidManifestFile variant.outputs[0].processResources.manifestFile // if you have multiple outputs (when using splits), you may want to have other index than 0 ...

2015年7月17日 · 2 分钟 · 天边的星星

Android实现推送方式解决方案

** 本文介绍在Android中实现推送方式的基础知识及相关解决方案。推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息。这种推送功能是好的一面,但是也会经常看到很多推送过来的垃圾信息,这就让我们感到厌烦了,关于这个我们就不能多说什么了,毕竟很多商家要做广告。本文就是来探讨下Android中实现推送功能的一些解决方案,也希望能够起到抛砖引玉的作用。^_^** ** 1.推送方式基础知识: ** 在移动互联网时代以前的手机,如果有事情发生需要通知用户,则会有一个窗口弹出,将告诉用户正在发生什么事情。可能是未接电话的提示,日历的提醒,或是一封新的彩信。推送功能最早是被用于Email中,用来提示我们新的信息。由于时代的发展和移动互联网的热潮,推送功能更加地普及,已经不再仅仅用在推送邮件了,更多地用在我们的APP中了。 当我们开发需要和服务器交互的应用程序时,基本上都需要获取服务器端的数据,比如《地震应急通》就需要及时获取服务器上最新的地震信息。要获取服务器上不定时更新的信息,一般来说有两种方法:第一种是客户端使用Pull(拉)的方式,就是隔一段时间就去服务器上获取一下信息,看是否有更新的信息出现。第二种就是 服务器使用Push(推送)的方式,当服务器端有新信息了,则把最新的信息Push到客户端上。这样,客户端就能自动的接收到消息。 虽然Pull和Push两种方式都能实现获取服务器端更新信息的功能,但是明显来说Push方式比Pull方式更优越。因为Pull方式更费客户端的网络流量,更主要的是费电量,还需要我们的程序不停地去监测服务端的变化。 在开发Android和iPhone应用程序时,我们往往需要从服务器不定的向手机客户端即时推送各种通知消息。我们只需要在Android或IPhone的通知栏处向下一拉,就展开了Notification Panel,可以集中一览各种各样通知消息。目前IOS平台上已经有了比较简单的和完美的推送通知解决方案,我会在以后详细介绍IPhone中的解决方案,可是Android平台上实现起来却相对比较麻烦。 最近利用几天的时间对Android的推送通知服务进行初步的研究,也希望能和大家共同探讨一下。 ** 2. 几种常见的解决方案实现原理:** 1)轮询(Pull)方式:应用程序应当阶段性的与服务器进行连接并查询是否有新的消息到达,你必须自己实现与服务器之间的通信,例如消息排队等。而且你还要考虑轮询的频率,如果太慢可能导致某些消息的延迟,如果太快,则会大量消耗网络带宽和电池。 2)SMS(Push)方式:在Android平台上,你可以通过拦截SMS消息并且解析消息内容来了解服务器的意图,并获取其显示内容进行处理。这是一个不错的想法,我就见过采用这个方案的应用程序。这个方案的好处是,可以实现完全的实时操作。但是问题是这个方案的成本相对比较高,我们需要向移动公司缴纳相应的费用。我们目前很难找到免费的短消息发送网关来实现这种方案。 3)持久连接(Push)方式:这个方案可以解决由轮询带来的性能问题,但是还是会消耗手机的电池。IOS平台的推送服务之所以工作的很好,是因为每一台手机仅仅保持一个与服务器之间的连接,事实上C2DM也是这么工作的。不过刚才也讲了,这个方案存在着很多的不足之处,就是我们很难在手机上实现一个可靠的服务,目前也无法与IOS平台的推送功能相比。 Android操作系统允许在低内存情况下杀死系统服务,所以我们的推送通知服务很有可能就被操作系统Kill掉了。 轮询(Pull)方式和SMS(Push)方式这两个方案也存在明显的不足。至于持久连接(Push)方案也有不足,不过我们可以通过良好的设计来弥补,以便于让该方案可以有效的工作。毕竟,我们要知道GMail,GTalk以及GoogleVoice都可以实现实时更新的。 3.第一种解决方案:C2DM云端推送功能。 在Android手机平台上,Google提供了C2DM(Cloudto Device Messaging)服务,起初我就是准备采用这个服务来实现自己手机上的推送功能,并将其带入自己的项目中。 Android Cloud to Device Messaging (C2DM)是一个用来帮助开发者从服务器向Android应用程序发送数据的服务。该服务提供了一个简单的、轻量级的机制,允许服务器可以通知移动应用程序直接与服务器进行通信,以便于从服务器获取应用程序更新和用户数据。C2DM服务负责处理诸如消息排队等事务并向运行于目标设备上的应用程序分发这些消息。关于C2DM具体使用过程,大家可以去查阅相关的资料,在这里先让我们了解下大致方案情况。 下面是C2DM操作过程示例图: 但是经过一番研究发现,这个服务存在很大的问题: 1)C2DM内置于Android的2.2系统上,无法兼容老的1.6到2.1系统; 2)C2DM需要依赖于Google官方提供的C2DM服务器,由于国内的网络环境,这个服务经常不可用,如果想要很好的使用,我们的App Server必须也在国外,这个恐怕不是每个开发者都能够实现的; 3) 不像在iPhone中,他们把硬件系统集成在一块了。所以对于我们开发者来说,如果要在我们的应用程序中使用C2DM的推送功能,因为对于不同的这种硬件厂商平台,比如摩托罗拉、华为、中兴做一个手机,他们可能会把Google的这种服务去掉,尤其像在国内就很多这种,把Google这种原生的服务去掉。买了一些像什么山寨机或者是华为这种国产机,可能Google的服务就没有了。而像在国外出的那些可能会内置。 有了上述几个方面的制约,导致我最终放弃了这个方案,不过我想利用另外一篇文章来详细的介绍C2DM的框架以及客户端和App Server的相应设置方法,可以作为学习资源让我们有个参考的资料。 即然C2DM无法满足我们的要求,那么我们就需要自己来实现Android手机客户端与App Server之间的通信协议,保证在App Server想向指定的Android设备发送消息时,Android设备能够及时的收到。 ** 4. **第二种解决方案:MQTT协议实现Android推送功能。 采用MQTT协议实现Android推送功能也是一种解决方案。MQTT是一个轻量级的消息发布/订阅协议,它是实现基于手机客户端的消息推送服务器的理想解决方案。 wmqtt.jar 是IBM提供的MQTT协议的实现。我们可以从这里(https://github.com/tokudu/AndroidPushNotificationsDemo)下载该项目的实例代码,并且可以找到一个采用PHP书写的服务器端实现(https://github.com/tokudu/PhpMQTTClient)。 架构如下图所示: ** wmqtt.jar** 是IBM提供的MQTT协议的实现。我们可以从如下站点下载(http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg24006006)它。我们可以将该jar包加入自己的Android应用程序中。 ** 5.**第三种解决方案:RSMB实现推送功能。 Really Small Message Broker (RSMB) ,他是一个简单的MQTT代理,同样由IBM提供,其查看地址是:http://www.alphaworks.ibm.com/tech/rsmb。缺省打开1883端口,应用程序当中,它负责接收来自服务器的消息并将其转发给指定的移动设备。 SAM是一个针对MQTT写的[PHP库](http://pecl.php.net/package/sam/download/0.2.0)。我们可以从这个[http://pecl.php.net/package/sam/download/0.2.](http://pecl.php.net/package/sam/download/0.2.)[](http://pecl.php.net/package/sam/download/0.2.0)地址下载它. send_mqtt.php是一个通过POST接收消息并且通过SAM将消息发送给RSMB的PHP脚本。 ** 6. **第四种解决方案:XMPP协议实现Android推送功能。 这是我希望在项目中采用的方案,因为目前它是开源的,对于其简单的推送功能它还是能够实现的。我们可以修改其源代码来适应我们的应用程序。 ...

2015年7月10日 · 1 分钟 · 天边的星星

Android自定义控件

开发自定义控件的步骤: 1、了解View的工作原理 2、 编写继承自View的子类 3、 为自定义View类增加属性 4、 绘制控件 5、 响应用户消息 6 、自定义回调函数 一、View结构原理 Android系统的视图结构的设计也采用了组合模式,即View作为所有图形的基类,Viewgroup对View继承扩展为视图容器类。 View定义了绘图的基本操作 基本操作由三个函数完成:measure()、layout()、draw(),其内部又分别包含了onMeasure()、onLayout()、onDraw()三个子方法。具体操作如下: 1、measure操作 measure操作主要用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数: (1)onMeasure(),视图大小的将在这里最终确定,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。 2、layout操作 layout操作用于设置视图在屏幕中显示的位置。在view中定义为final类型,要求子类不能修改。layout()函数中有两个基本操作: (1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来; (2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的; 3、draw操作 draw操作利用前两部得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。子类也不应该修改该方法,因为其内部定义了绘图的基本操作: (1)绘制背景; (2)如果要视图显示渐变框,这里会做一些准备工作; (3)绘制视图本身,即调用onDraw()函数。在view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的显示(比如TextView在这里实现了绘制文字的过程)。而对于ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的,其包含了多个子view,而子View已经实现了自己的绘制方法,因此只需要告诉子view绘制自己就可以了,也就是下面的dispatchDraw()方法; (4)绘制子视图,即dispatchDraw()函数。在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法; (5)如果需要(应用程序调用了setVerticalFadingEdge或者setHorizontalFadingEdge),开始绘制渐变框; (6)绘制滚动条; 从上面可以看出自定义View需要最少覆写onMeasure()和onDraw()两个方法。 二、View类的构造方法 创建自定义控件的3种主要实现方式: 1)继承已有的控件来实现自定义控件: 主要是当要实现的控件和已有的控件在很多方面比较类似, 通过对已有控件的扩展来满足要求。 2)通过继承一个布局文件实现自定义控件,一般来说做组合控件时可以通过这个方式来实现。 注意此时不用onDraw方法,在构造广告中通过inflater加载自定义控件的布局文件,再addView(view),自定义控件的图形界面就加载进来了。 3)通过继承view类来实现自定义控件,使用GDI绘制出组件界面,一般无法通过上述两种方式来实现时用该方式。 三、自定义View增加属性的两种方法: 1)在View类中定义。通过构造函数中引入的AttributeSet 去查找XML布局的属性名称,然后找到它对应引用的资源ID去找值。 案例:实现一个带文字的图片(图片、文字是onDraw方法重绘实现) ![](http://common.cnblogs.com/images/copycode.gif) publicclassMyViewextendsView {privateString mtext;privateintmsrc;publicMyView(Context context) {super(context); }publicMyView(Context context, AttributeSet attrs) {super(context, attrs);intresourceId = 0;inttextId = attrs.getAttributeResourceValue(null, “Text”,0);intsrcId = attrs.getAttributeResourceValue(null, “Src”, 0); mtext=context.getResources().getText(textId).toString(); msrc=srcId; } @OverrideprotectedvoidonDraw(Canvas canvas) { ...

2015年7月10日 · 1 分钟 · 天边的星星