当前位置: 代码迷 >> 综合 >> android ghost tricks(一)
  详细解决方案

android ghost tricks(一)

热度:20   发布时间:2024-01-12 05:19:08.0

平时开发的时候发现了一些小的把戏技巧。整理其中的一些向分享一下

  1.  sdk封装资源
  2. 非阻塞递归
  3. 如何获取视图大小

 

一、sdk封装资源

android的一大难题便是资源文件的绑定。如果我们为了模块化,想要将一个小的功能做成sdk的样式,那么该怎么做呢?

Java普遍的习惯是将功能打包成为一个jar包。其好处很多,解耦合。然而在android开发中,这样子做却有一个大问题。问题便是jar包形式难以提供资源。

Android官方推荐的做法是编写Android LibararyAndroid Libarary其实就是一个Android工程,所以可以像普通Android项目一样去引用各种资源。这种方式有它的好处,可包含资源,可自由修改源码。这对于内部工程来说非常合适,可是如果想将功能包装成binary版本,那么还是得依靠jar包形式了。

有没有一种封装方式,能够既提供jar包,又提供资源呢?答案是肯定的。只要在jar包中包含assets文件夹,那么引用jar包的android项目事实上也包含了该资源文件。在编译apk阶段,jar包的资源便被解压进入apkassets目录了。最终会被拷入私有文件夹data目录。

以腾讯的openapi为例。其打包的jar包中包含了assets目录。Android项目想引用资源非常简单,只消这样一句话即可:

 

TencentOpenRes.getBigLoginBtn(getAssets())
 

 

 


 

:其实jar包中可以通过JarURLConnection来提取资源。不过我觉得此种assets小把戏更符合android编程习惯,很适合用于包含资源的binary sdk情境。

二、非阻塞递归

递归的思维是:在满足退出条件之前,不断重复调用自己。

Android平台上面,通过使用Handler我们可以实现非阻塞递归。

一个同步版本的递归是这个样子的:

 

int recursion(int x){if(x==1) return 1;return x*recursion(x-1);}
 

 

非阻塞版本的递归则是这个样子的。

   

 int x;int result=1;Handler handler=new Handler();Runnable task=new Runnable() {@Overridepublic void run() {if(x==1) handler.removeCallbacks(task);result=x*x-1;x--;handler.post(task);}};void start(){x=50;//inithandler.post(task);}

 

看起来,非阻塞的递归用起来很麻烦。其实,只要把task想象成一个时间片,它穿插在UI线程中工作,分时的完成计算任务。例如:UI-Event,View-DRAW,task,UI-Event,task,task

那么,非阻塞递归在什么情况下使用呢?在配合视图工作时其实很有用。例如,计算滑动重绘视图。当滑动结束时移除重绘回调。

三、安全的获取视图大小

如果你的View设置了WRAP_CONTENT或者MATCH_PARENT。或者是通过weightRelative布局的,那么View的大小往往需要一轮全局layout才能measure得出。

举个例子,在ActivityonCreate后调用view.getMeasureHeight()也许会得到0。拦截到viewonMeasure似乎是个不错的注意。不过这太麻烦了,用继承做显得小题大做。下面介绍两种方法。

第一种:

view.post(new Runnable() {@Overridepublic void run() {System.out.println(view.getMeasuredHeight());}});

这种方法向该view的执行队列中插入了一段runnable代码。它假设了ViewmeasureHiearachy必定在我们postRunnable之前。笔者尝试分析一下源码这种做法是否安全,但因为较为复杂,所以目前还没法得出结论。下面介绍的方法相对靠谱些。

第二种:

view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {view.getViewTreeObserver().removeGlobalOnLayoutListener(this);System.out.println(view.getMeasuredHeight());}});

 

  相关解决方案