IntelliJ IDEA 生成 serialVersionUID

serialVersionUID的作用

详见这篇文档  http://lenjey.iteye.com/blog/513736

简单来说就是,在序列化对象时,编译器会自动给对象生成一个serialVersionUID,之后任意改动这个对象都会与编译器生成的UID不匹配。如果我们显示指定了serialVersionUID,那么对象序列化之后,也可以修改这个对象。

serialVersionUID生成

我们可以任意指定serialVersionUID,如

但最好还是使用让系统按照摘要算法生成一个指纹数字。eclipse是可以自动生成的,IDEA需要简单配置一下。

IntelliJ IDEA->Preferences->Inspections界面下

Serializable class without serialVersionUID后打钩,注意上面的Profile选为Default。

(继承了Serializable的类没有serialVersionUID就会Warning)

之后光标在继承了Serializable的类名上按 ALT+ENTER键,就会出现 Add serialVersionUID field 选项,生成的UID如下

Jdom-XmlOutputter 换行(setIndent)

Jdom的XmlOutputter默认生成的文件不带换行,所有key-value对写在一行里,使用起来很不方便,XmlOutputter支持设置换行。

jdom1.0中写法如下

XmlOutputter xmlOut = new XmlOutputter("  ", true, "utf-8");

三个参数分别为,缩进(这里是两个空格),是否换行,字符编码

官方文档

jdom1.0以后不支持上面的写法,而是把三个参数剥离出来,形成了Format类

d3总结

项目原因,需要使用web绘制图表,比较靠谱的有echart和d3。

echart:应该是百度的项目,首页做的很漂亮,文档也比较全。个人感觉是一个入手较易,主要在学习怎么配参数,地图是echart的一个亮点。缺点就明显了,入手容易的肯定高度封装过,很难根据自己的需求定制化。而且使用了cavas绘图,在移动端性能不如svg。个人感觉echart适合一些时间比较紧迫,设计没那么明确的场合,直接套上echart,就已经很漂亮了。

d3:大名鼎鼎,受欢迎程度超过jquery,首页的绚丽特效让人眼花,教程的话强烈推荐http://www.ourd3js.com/wordpress/,这个教程好像出了书,叫精通D3.js,基本上把教程撸一遍就没啥大问题了。

d3的优点:用过一段d3后,感觉d3就是svg的jquery,把svg的操作封装为更易用的接口,并提供各种数据可视化的接口。所以d3很灵活,因为你可以用d3在svg中添加一个点、线、饼等等,svg性能不错。链式写法。

缺点:入手稍微慢点,不过撸一遍教程也就一下午的时间。svg的接口网上文档比较少,有些用法stackoverflow都找不到。

如果是学习d3的,推荐前面的教程网站,这里只是个人备忘录,想到哪里说到哪里的流水账,记录那些让人眼前一亮或者眼前一黑的点,以及几个开发中反复查询的用法。

好了,出发

1.

首先,你要在一个dom中添加svg,需要两个参数,width和height,一般我是这么给的

踩坑:需求在指定操作后才绘制该图标,dom display:none的时候,clientWidth和clientHeight是0,所以svg等dom display正常后再添加。

接下来最好设置一下svg的padding,用来应付后面出现的各种文字绘制超出不显示,UI修改等灵细操作。

因为svg直接传的都是px,所以需要根绝屏幕做一下自适应,size_1920函数如下:

坐标轴:

图标中用到最多的是坐标轴,使用坐标轴首先要设定比例尺,目前共用到了4种比例尺

线性比例尺

domain中设置数据的min/max,range中设置svg实际位置。

备注:svg是以左上角为原点的,而常规视角中原点是左下角,所以这里的range起止位置是 svgHeight-0,即起始位置是下边缘y=svgHeight,终止位置是上边缘y=0。这一点需要谨记,后面有许多计算x、y位置的,y的位置总要反着想。其他比例尺也是一样的。

离散比例尺

or

时间比例尺

时间比例尺适用于一些以时间为坐标轴的情况

备注:比如这里是今天到明天,第二天nextDay的算法,就用秒,其他都不行。UTC时间一定要注意,所有时间都改成UTC时间,所有get一律要加UTC。

颜色比例尺

这是个比较特殊的比例尺,不是用来画坐标轴的,而是把颜色均匀分割,category10,category20等等都有,填一个index,输出一个色值。在有些d3的版本中,颜色比例尺没用放在scale里面。

坐标轴

可能还有更多种类的比例尺,目前还没有接触,下面就开始生成坐标轴数据。

几个常用参数

scale,必要参数,把比例尺填进去

orient,非必填,刻度相对坐标轴的位置 top bottom left right

ticks,非必填,刻度个数 注:ticks只是参考,最终生成刻度个数以数据为准,比如数据需要25个刻度,但ticks填了17,那d3就没办法了,会生成一个d3生成的刻度个数中选跟17最接近的。

innerTickSize,非必填,内刻度高,默认是6。 注:这里设置了innerTickSize是整个svg的高度,和y轴innerTickSize设置整个svg的宽配合行程网格效果,正常的坐标轴就再画一个,注意高度计算时错开

outerTickSize,非必填,外刻度高

tickFormat,非必填,刻度值,默认为空  注:这是一个数据绑定参数,即根据数据生成不同的值

tickPadding,非必填,刻度文字与坐标轴的间距

真正的绘制

 

给svg中添加g元素,call绑定坐标轴数据,attr就是给g元素添加各种属性,class(是不是很熟悉),transform。 注:svg中没有top left  margin等属性,大的位移使用transform。

曲线

坐标轴绘制完后,就是曲线的绘制,先生成曲线绘制函数

曲线绘制函数参数

x、y就是根据数据来计算坐标,这里是比例尺大显身手的地方。

interpolate,线段怎么弯曲,讲的最好的是这个地址

http://www.oxxostudio.tw/articles/201411/svg-d3-02-line.html

注:basis曲线保证了优美,没保证曲线与数据的一致,像我这种人是完全无法接受的。

绘制曲线

这一行代码解读一下就是选择所有class是data-line的元素,然后给它绑定数据。data-line哪里来的?这里涉及到d3中一个概念,update  enter  exit

selectAll得到的元素跟数据相比,有三种可能,元素个数 大于/小于/等于数据个数。

数据超出元素个数的部分叫enter,比如第一次绘制时,所有元素都属于paths.enter

paths元素比较简单直接,基本上只需要给一个属性d就能画出来了,d可以用前面的曲线函数直接生成。

stroke,线条颜色,这里可以用颜色比例尺 d3.scale.category10(i)

fill就是填充颜色,paths填充的是一个面。

不超出的部分叫update,即需要更新的部分,paths.update可以看到,也可以直接更新数据,这里是数据驱动的最直观表现

数据少于元素个数的部分叫exit,一般exit只有一个用法

到这里,一个坐标轴差不多出来了,但,是不是少了点啥,对,UED最喜欢的灵魂一击,动画。

曲线进入/更新的时候要动画怎么办

d3的动画很好写

增加 transition ease 和 delay即可,transition前后是动画的起始和结束状态。

绘制一个圆

矩形

半圆角矩形是用path生成的,顶部圆角矩形

topRoundRect和rightRoundRect乍一看完全搞不懂,这里讲的比较详细https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths,仔细观察下,就是

M  起始x y坐标

h 纵移

v 横移

a 比较复杂 前两个参数是圆角的x y radius

中间三个参数 001是三个flag,只能是0/1 圆角矩形都是001

第一个代表弧线角度是否要大于180

第二个代表正角度还是负角度

第三个代表正方向还是反方向

z是合拢

最后两个参数是终止的x y位置

当前了,还有更多的L C S等等,这里不研究了

文字

到这里,d3绘制的套路差不多都熟悉了,append data enter transform attr,拿来画个饼图吧!

生成饼图数据

查看一下this.pieData,你会发现数据增加了 startEngle 和 endEngle

注:饼图默认会按大小排序,如果不需要排序,增加一个sort(null)即可

弧线函数

饼图动画不能使用d了,要使用attrTween

简单的饼图动画

高级饼图动画,自己计算delay的时间,让饼一点一点出来

往饼图中间添加一个圆点

注:centriodData和Angle是钝/锐角的计算提出来,是因为在某些低配机子上,偶现绑定计算错误。

画一个折线

到这里,一般的坐标轴、饼图已经难不倒了,而且自己想添加什么就添加什么,无非就是计算x、坐标,d3就是一堆图形函数,帮你计算坐标而已,那还有什么新东西吗?假如UED说想要阴影,光效,这里介绍一下svg里面一个很牛叉的东西,filter

实话说,这个东西我也只是到抄过来调参的地步,比如dx dy。理解上只知道特效输出为result,下一个特效的in是这个result,其他也是一问三不知,而且看了之后着实没有深入了解下去的想法,简直就是手写Photoshop。

下面是几个介绍filter的地址,留下以备不时之需

1.https://www.w3.org/TR/SVG/filters.html

2.https://www.smashingmagazine.com/2015/05/why-the-svg-filter-is-awesome/

3.https://jorgeatgu.github.io/svg-filters/

 

 

 

 

d3['default'] is undefined

使用Babel引入d3,即import d3 from 'd3',使用时出现undefined的错误,调试后发现

var _d3 = __webpack_require__(164);

var _d32 = _interopRequireDefault(_d3);

var fill = _d32['default'].schemeCategory20;

_d3有schemeCategory20,d32['default']是undefined,

_interopRequireDefault是什么鬼?

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

就是根据__esModule 的一个if else,__esModule又是什么?

这里有一篇比较具体的解释 http://ryerh.com/javascript/2016/03/27/babel-module-implementation.html

简单来说,default就是我们在class后面写的 export default xxx

翻一翻源码,d3的default是true,但没有export default

 

相关链接:__esModule true in build/d3.js?

Improve docs: ES6 usage example

从这两个链接中,找到了d3的正确用法

import * as d3 from 'd3'

import文档

就是说,把d3的所有模块导出,给d3这个作用域

调试来看,就是

var _d3 = __webpack_require__(164);

var d3 = _interopRequireWildcard(_d3);

可以看到,用了import as后

从_interopRequireDefault转变为_interopRequireWildcard

也就是*替换了default

另外,必须再说一下,d3没有default,但d3的插件不一定没有

比如我使用的d3-cloud,还是要用import cloud from 'd3-cloud'

chart.js 绘制雷达图

chart.js是一个很newblity的图标库,支持各种图(柱状、曲线、饼图、雷达图等等),使用起来也很简单,这里先奉上官方文档一份 http://www.bootcss.com/p/chart.js/docs/。

chart.js使用canvas绘制,缺点就是移动端性能有点差(或者是我入门太浅)。

官方文档介绍的不甚详细,这里给一个可以成功的example。

雷达图

1.引入chart.js

1).<script>标签引入    逼格太低

2).npm install chart.js 后,var Chart = require('chart.js')    逼格一般

3).npm install chart.js,使用gulp,import Chart from 'chart.js'  逼格目前最高

2.html文件中,一个canvas元素是必须的

style比较简单,就不写css了

3.创建一个图标,只需要new一个chart对象就可以了

需要两个参数,canvas的context,以及config

主要问题在于config,暂时未能完全了解

Android-aidl传输parceble数据错误

写了一个service,使用AIDL跨进程调用时出现问题,service这边写的数据是正确的,client端拿到的是默认值,都是0.

找了下,

http://stackoverflow.com/questions/24615317/android-aidl-and-service-and-activity-parceable-seems-to-be-passing-default-clas

因为 in  out写反了。

in表示这个参数是入参,会被这个method读,但不会写。out意味着这个method会写但不读。inout表示会读也会写。

in/out/inout从字面意思上很好理解,要记住,它们是修饰参数,in/out都是相对于当前method的。

Android-获取内存,当前/总cpu信息

内存信息中最有用的就是PSS了,还有各种零碎的,在android.os.Debug中可以直接拿到MemeryInfo

 

cpu信息分两类,总的cpu使用率,取proc/stat的数据,这个样子

取到之后解析,拿到使用时间和空闲时间

隔一段时间后,再取一次数据,即可得到cpu使用时间

当前进程的cpu使用率计算方法和总的相似,只不过路径变成了proc/<pid>/stat

解析数据代码如下,如果不计算子进程时间则只用toks[13]和toks[14]

取到之后除以总的cpu时间,即

通过jni获得应用Icon(getApplicationIcon)

jni获得应用icon有两步

1.在java端写一个方法,通过包名获取appIcon,返回byte[]

native初始化时,获取这个method,同时拿到VM和全局context

jobject mBzAppContext;
JavaVM *m_appContext_VM = NULL;

mAppContext = env->NewGlobalRef(thiz);
env->GetJavaVM(&m_appContext_VM);

FIND_CLASS(clazz, "com/xx/xx/xx");
if (clazz == NULL) {
loge("class not exist!!");
}

GET_METHOD_ID(gAppGlobalCallMethod.getAppIcon, clazz,
"getAppIcon", "(Ljava/lang/String;)[B");
if (gAppGlobalCallMethod.getAppIcon == NULL) {
loge("method get fail!!");
}

(Ljava/lang/String;)[B 指入参是String,回参是jbyteArray

2.调用jni函数,拿到byte[],转成char*

void readAppIcon(const char* packageName)
{
if (m_appContext_VM == NULL) {
loge("m_appContext_VM null");
return;
}
if (mAppContext == NULL) {
loge("mAppContext null");
return;
}
if (gAppGlobalCallMethod.getAppIcon== NULL) {
loge("gAppGlobalCallMethod.getAppIcon null");
return;
}
CHECK_JVM_THREAD(m_appContext_VM);
if (error) {
loge("check jvm thread error");
return;
}
jstring jPackageName = env->NewStringUTF(packageName);
jbyteArray jbarray = (jbyteArray)env->CallObjectMethod(mBzAppContext, gAppGlobalCallMethod.getAppIcon, jPackageName);

if (jbarray == nullptr) {
logi("getAppIcon null");
} else {
len = (int)env->GetArrayLength (jbarray);
char *data = (char*)env->GetByteArrayElements(jbarray, 0);
// 这里就把appicon拿到并转成了char*,注意释放data

env->ReleaseByteArrayElements(jbarray, data, 0);
}
if (attached) {
m_appContext_VM->DetachCurrentThread();
}
}

 

AndroidStudio 更改jar包编译顺序优先于android.jar,使用@hide api

使用@hide 的api,可以通过反射,但反射速度慢,且使用不方便。

@hide的api,在编译的时候有问题,如果能编译成功,是可以调用的。那么问题来了,如何编译成功?

可以修改android源码,去掉@hide,编译生成该模块的framework.jar。Eclipse中直接引入该jar包在android.jar前即可。AndroidStudio就比较麻烦,需要做两步。

1.引入jar包,这个网上有无数方法,不表。注意设置compile->provide,gradle文件如下:

原因就是我们只需要编译成功,不需要把这个包打到系统。

这时候在系统自动生成的iml文件中,可以看到一排orderEntry标签 <orderEntry>,也就是我们引用的所有jar包信息,把framework的jar包放到orderEntry的第一位,也就是

前面,这时候IDE就不报错了。

不过只是表象,方便我们写代码自动补全而已。而且iml文件是自动生成的,每次重启IDE都要重新改一下。

2.真正的编译需要在工程的gradle中增加编译选项

找到

在repositores同级增加

Xbootclasspath/p:是Java编译的寻址优先设置,先找缺省路径还是全路径

不确定路径怎么填的,可以使用绝对路径,如

编译通过

Tips:

1.有时候@hide的api编译过了,其他地方又报错。查看一下报错的api,看看是不是对android版本有要求,framework.jar编译最好用较新的编译环境。

2.不要做过多的其他尝试,这两步绝对可以解决问题。

calling startactivity() from outside of an activity context requires the flag_activity_new_task flag. Is this really what you want?

今天遇到一个错误,莫名戳中笑点,好贴心好长的提示。

原因:使用application startActivity,必须使用FLAG_ACTIVITY_NEW_TASK,因为新起来的Activity没办法和application放到一个task中,必须用FLAG_ACTIVITY_NEW_TASK让新启动的ACTIVITY独占一个TASK。