[Java]项目Java文件相似度检测工具

为了排查项目中重复文件(代码),制作了Java文件相似度检测工具。

本工具基于项目https://dickgrune.com/Programs/similarity_tester/

使用方法:

其中 -i 表示相似度阈值,默认90,即90以上相似度的结果才会打印出来。开发者可根据结果,对项目进行重构。

注:目前jar仅支持win平台,java文件的相似度比较,源码地址:https://github.com/legendmohe/simcode

[Android] apk方法数量,类数量对比工具

为了方便比较两个版本间类的数量,方法的数量的变化,现提供工具dex-method-diff。

使用方法:

其中–mapping是可选项,例如:

源码:

https://github.com/legendmohe/dex-method-counts

[Android] Preloader 预加载框架

简介

Preloader是一个用于异步加载数据的工具。它提供同步或者异步的获取结果回调。
适当地使用可让业务层获取数据的时间点提前。

使用例子

以简单activity跳转的例子为例,从MainActivity跳转到SubActivity。其中SubActivity的完整
显示需要发起一次请求,获取到结果后显示在中央的textView。

利用Preloader,我们可以在MainActivity发起跳转的时候开始请求,在SubActivity需要的时候将结果取出。
这样子可以把获取结果的时间点提前,起到加速显示SubActivity的作用。

代码如下所示:

  • MainActivity:

  • SubActivity:

注意事项

  • 可通过PreloadTask.setGetResultTimeout设置异步获取结果的超时时间,默认为30秒。
  • 如果PreloadTask.isClearWhenGetResult()==false,那么需要使用者自己调用Preloader.clear方法来释放预加载task,
    否则预加载task将在第一次成功获取结果后被释放(无法再次通过Preloader.getResult取结果)
  • 对于同一个preloadResult对象,可多次调用get(),互不影响。

源码

https://github.com/legendmohe/Preloader

[Android] 列表预加载工具类DataPreloader

DataPreloader用于实现列表数据预加载需求。注意这里的预加载是指预加载数据项的详细信息(例如预拉取视频列表里面某些视频的播放地址等),不是指预先拉取更多的列表项。

概念说明

  • 加载窗口preload window:即需要发起预加载的项目的index区间
  • 焦点:即当前外围逻辑所关心的中心点的index,决定了区间的中心

该工具类引入加载窗口的概念(由upperPosition和LowerPosition组成的闭区间),外围调用triggerPreload()传入当前焦点的index,该工具类即回调哪些index离开了加载窗口和哪些index进入了加载窗口(即窗口的变化情况)。外围可以根据回调来进行加载或取消加载。

使用说明

详见代码和注释如下所示:

使用例子如下所示:

注意: 合理设置区间的upper和lower。例如用于列表预加载时,可只设置upperBound,而lowerBound设置为0,那么该工具类只会回调后面的数据,不会回调前面的数据

源码:https://gist.github.com/legendmohe/651cd418054a53f64bdd105f67265f15

[Android] 如何计算View的Size

** 注:本文参考链接How Android caculates view size

本文例子如下所示:

过程

计算view大小的过程可以分为以下几个步骤:

  1. 确定view想要的size(LayoutParams)
  2. 确定parent view的情况(MeasureSpec)
  3. 在parent view的限制下,根据view的LayoutParams,确定view的大小

参数

LayoutParams

LayoutParams用于view表示想要的size的模式。有以下三种:

  1. FILL_PARENT / MATCH_PARENT (-1)
    view的size和parent view的size一样大
  2. WRAP_CONTENT(-2)
    view的size仅包裹其内容即可
  3. 指定的值(>0)
    view的size为指定的size大小

MeasureSpec

MeasureSpec表示当前view的“约束”(在onMeasure中传入)。约束含模式mode和数值size,当前view根据mode来决定如何看待其中的size。

mode

mode有三种,如下所示:

  1. UNSPECIFIED
    对当前view的size没有约束
  2. EXACTLY
    当前view的bounds(可以理解成“可以使用的范围”)为确定的size,也可以理解成parent view希望当前view(有强制的意味)使用给定的size
  3. AT_MOST
    当前view的大小不可超过指定的size

可以利用MeasureSpec的getMode取出具体值.

size

size为8个byte的int值,mode放在前2个bit中。这里可以利用MeasureSpec的getSize取出size的具体值。

onMeasure过程

view通过onMeasure确定自己的大小。确定自己的大小时,需要的东西有:

  1. 约束MeasureSpec
  2. 自己的LayoutParams
  3. 如果有child view,那么需要获取child view的大小

最终确定当前view的size分别为:

  1. measureWidth
  2. measureHeight

single view

以前面例子中的TextView为例,其onMeasure中传入的MeasureSpec为:

  1. Width
    mode:EXACTLY size:parentContentWidth(LinearLayout的宽-padding)
  2. Height
    mode:AT_MOST size:parentContentHeight(LinearLayout的高-padding)

注:这里先不解释为什么MeasureSpec是这样的。

TextView的LayoutParams为:

  1. Width
    MATCH_PARENT
  2. Height
    WRAP_CONTENT

然后TextView根据约束和LayoutParams确定自己的大小,包括但不限于以下过程:

  1. 设置宽度为parentContentWidth,考虑margin确定字符可用范围
  2. 根据字符高度和字体设置(根据是否超过parentContentWidth确定是否换行)等计算字符所占的高度(没有限制)。
  3. 设置measureWidth和measureHeight

ViewGroup

以前面例子中的LinearLayout为例,假设该LinearLayout为Activity中的root layout其onMeasure中传入的MeasureSpec为:

  1. Width
    mode:EXACTLY size:parentContentWidth(LinearLayout的parent view的宽-padding)
  2. Height
    mode:AT_MOST size:parentContentHeight(LinearLayout的parent view的高-padding)

RelativeLayout的LayoutParams为:

  1. Width
    MATCH_PARENT
  2. Height
    WRAP_CONTENT
  3. Orientation
    vertical

然后LinearLayout根据约束和LayoutParams确定自己的大小,包括但不限于以下过程:

  1. 确定child view的排列方式
  2. 确定TextView的size
  3. 确定ImageView的size
  4. 根据自身的设置,设置measureWidth和measureHeight

要确定child view的size,就要调用child view的onMeasure,传入合适的MeasureSpec,表明parent view对child的约束。

根据parent view的不同module和child view的不同LayoutParams,有如下规则:

  1. 当parent view的mode是EXACTLY时:
child layout mode size
exact size EXACTLY childSize Child wants a specific size.
MATCH_PARENT EXACTLY parentContentSize Child wants to be parent’s size.
WRAP_CONTENT AT_MOST parentContentSize Child wants to determine its own size. It can not be bigger than parent.
  1. 当parent view的mode是AT_MOST时:
child layout mode size
exact size EXACTLY childSize Child wants a specific size
MATCH_PARENT AT_MOST parentContentSize Child wants to be parent’s size, but parent’s size is not fixed. Constrain child to not be bigger than parent.
WRAP_CONTENT AT_MOST parentContentSize Child wants to determine its own size, but it can not be bigger than parent.
  1. 当parent view的mode是UNSPECIFIED时:
child layout mode size
exact size EXACTLY childSize Child wants a specific size.
MATCH_PARENT UNSPECIFIED can not decide yet Child wants to be parent’s size. Child will decide its own size later.
WRAP_CONTENT UNSPECIFIED can not decide yet Child wants to be its own size. Child will decide its own size later.

以例子中的TextView为例:

  1. LinearLayout的width mode为EXACTLY,TextView的width layout param为MATCH_PARENT
  2. LinearLayout的height mode为AT_MOST,TextView的height layout param为WRAP_CONTENT

所以TextView的onMeasure会被传入:

  1. Width
    mode:EXACTLY size:parentContentWidth(LinearLayout的宽-padding)
  2. Height
    mode:AT_MOST size:parentContentHeight(LinearLayout的高-padding)

TextView可以根据上述约束计算自己的大小。ImageView同理。最后LinearLayout根据ImageView和TextView的大小计算自己的大小。注意这里没有weight的设置,所以onMeasure只运行一次。

如上述有错,请留言告知。

[Android] 一种优化view inflate耗时的方法

注:此方法会有内存泄漏(context)泄漏。

做项目的过程中,发现一种一种优化view inflate耗时的方法,思路是预先将view inflate出来备用,用的时候直接取出来,同时再生成下一个(要考虑屏幕方向)。代码如下所示:

用法大概如下所述:
1. 在适当的地方调用push方法。
2. 在使用view的时候,使用类似如下的代码: