使用bat自动处理dumpsys meminfo内存信息

Android内存查看有两种方法,procrank 和 dumpsys meminfo,procrank计算GPU内存不准确,所以选择meminfo指令。

但meminfo需要一遍一遍的敲命令,而且结果比较乱,那能不能有批处理工具呢?答案是肯定的。

MemoryLeakToolRobin Hu编写的一款用于监测Android进程内存使用情况的脚本工具,简称为MLT。具体使用方法请参考

http://hubingforever.blog.163.com/blog/static/171040579201243071752744/

这里不再赘述(CSDN下载要10分,痛心啊!)。

整套工具使用起来很简单,有图形界面。

1.在config.bat中配置包名

2.根据需要运行各种工具。

一般的Android开发已经够用了。如果你对这一套bat有兴趣或者想自定义输出或者运行出了问题,那么请往下看。

我遇到的问题是,我在非标准的Android上运行了dumpsys meminfo,输出结构跟Android不一致,所以没有得到我想要的结果。那就需要改造脚本。

getMemoryState.bat

核心是这一句

adb shell "dumpsys meminfo %curProcessName%" >%meminfoFile%

在shell下执行 dumpsys meminfo %curProcessName%指令并将结果输出到%meminfoFile%

%%是bat语法,通过set 定义一个变量

如 set test=1,通过%test%来引用它

curProcessName和meminfoFile是在第一个步骤config.bat中配置的。

这样我们就拿到了一个meminfo文件,我这里的输出是这样的(非标准):

meminfo

修改后的处理脚本

FOR /F "skip=5 tokens=1,2,3,4,5,6,7,8" %%i in (%meminfoFile%) do (

if !cnt! EQU 0 (
   set NativePSS=!NativePSS!%slipChar%%%k
echo NativePSS:%%k
)
if !cnt! EQU 3 (
   set GfxDev=!GfxDev!%slipChar%%%k
echo GfxDev:%%k
)
if !cnt! EQU 5 (
   set SoMap=!SoMap!%slipChar%%%k
rem set SoPrivateDirty=!SoPrivateDirty!%slipChar%%%l
rem set SoPrivateClean=!SoPrivateClean!%slipChar%%%m
)
if !cnt! EQU 8 (
   set UnknownPSS=!UnknownPSS!%slipChar%%%j
echo UnknownPSS:%%j
rem set UnknownSize=!UnknownSize!%slipChar%%%l
rem set UnknownAllocated=!UnknownAllocated!%slipChar%%%l
rem set UnknownFree=!UnknownFree!%slipChar%%%l
)
if !cnt! EQU 9 (
   set TotalPSS=!TotalPSS!%slipChar%%%j
echo TotalPSS:%%j
rem set TotalPrivateDirty=!TotalPrivateDirty!%slipChar%%%k
rem set TotalPrivateClean=!TotalPrivateClean!%slipChar%%%l
)
set /a cnt+=1

)
FOR /F "skip=5 tokens=1,2,3,4,5,6,7,8" %%i in (%meminfoFile%)

这一句是逐行读取文件,参数

skip=n 跳过n行

tokens 将要处理的列

还有一个参数delims,分隔符,默认是空格

%%i,可以理解为对应前面的tokens,从i开始,ijklmn这样的顺序使用,如你想用第二列的数据,就是%%j。

 

bat学习:

1.rem是注释

2.set 定义变量  %%引用变量 !!也是引用变量  (有什么区别?)

3.将文件清空 echo. >%path%,其实就是重写这个文件。(如何修改文件中某一行某一列内容?)

4.ren 修改文件名

5.set变量时,设置失败。需要开启延迟

Setlocal enabledelayedexpansion

之后启用变量引用符号 !!

6.检查str是否包含substr

if not "!str!" == "!str:substr=!"

str:substr= 表示将str中的substr置为空。

7.得到一个长路径的文件名

call :getname %path%

:getname
set outName=%~nx1

8.延时

延时有很多方法,最方便的一种是

设置延时6秒

@ping 127.0.0.1 -n 6 >nul

不精确

 

WebStorm下配置less环境

Webstorm是一个很优秀的js IDE。今天打算学习less的时候,创建一个less文件后发现webstorm提示是否AddWatcher,点开后发现是一个自动编译less文件的工具,可惜不能直接使用,需要简单配置一下。

所有资料来自于

https://www.jetbrains.com/webstorm/help/transpiling-sass-less-and-scss-to-css.html。

洋洋洒洒一大坨,读起来有点费劲。实际操作了一下,发现简单的要命。

首先,你要装好node环境,没装的请自行百度。

1.View-ToolWindows-Terminal

2.输入 npm install -g less

搞定。

 

再次打开AddWatcher窗口,你就发现所有选项已经自动填好了。

less文件左边出现了一个小箭头,点开看到了css文件,完全同步。

JS获得element的index

获得某个element在parent中的index。

jquery提供了index接口,可以直接拿到。

如果没有jquery的话,

将document查询到的HTML Collection转为Array,

然后使用Array的index接口拿到index。

var ItemList = Array.prototype.slice.call( document.getElementsByClassName("item"));

var _currentFocus = document.getElementsByClassName("item focus")[0];
var _position = ItemList.indexOf(_currentFocus);

使用CMake(windows vs2015)

学习使用CMake,简单记录一下学到的东西:

CMake使用自己的语法对工程进行配置,方便在各个平台编译。

windows上,安装了CMake后,有gui界面,操作起来很方便。

1.打开gui,选择源码目录(对应${PROJECT_SOURCE_DIR})

2.选择生成目录,最好是${PROJECT_SOURCE_DIR}/build,防止生成文件跟源码搞到一起。

点击configure,偶尔需要两次。configure完工后,去build目录下已经可以看到VS工程文件,打开就可以慢慢调了。

 

CMake要求不多,编译目录下需要有CMakeList.txt,CMake根据CMakeList酌句执行。

这里贴一个用到的CMakeList.txt,并简单注释(目前理解还不够,仅仅是配置对应了vs的哪一项)

cmake_minimum_required(VERSION 2.8)
#工程名
project(projectName)
#输出
message("project source dir: ${PROJECT_SOURCE_DIR}")
#添加编译选项 -D为预编译选项
set(CMAKE_C_FLAGS "-fshort-wchar -fPIC -DHAVE_CONFIG_H -O0 -DNDEBUG")
set(CMAKE_CXX_FLAGS "-std=c++11 -fshort-wchar -frtti -fPIC -fexceptions -O0 -DNDEBUG" )
#同上
add_definitions(-D_WINDOWS_PLATFORM)

#下面是一些CMake的编程语法 set用的最多,就是设置变量 类似于 +=
set(DIR_LIST src src/utils
)

foreach(DIR ${DIR_LIST})
#message("dir:${DIR}")
#查找当前目录下所有的源文件并保存在SRC中
aux_source_directory(${DIR} SRC)
#message("src:${SRC}")
set(SRC_LIST ${SRC_LIST} ${SRC})
endforeach(DIR)

set(SRC_LIST ${SRC_LIST} 
demo/windows/main.cpp
)
#message("srclist:${SRC_LIST}")

#add_subdirectory(${PROJECT_SOURCE_DIR}/deps/curlcpp)

#添加到头文件
include_directories(
${PROJECT_SOURCE_DIR}/demo/windows/include
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/src/
)

#附加库目录
link_directories(${PROJECT_SOURCE_DIR}/demo/windows/libs/)
#使用SRC_LIST中的文件生成可执行文件hello
add_executable(hello ${SRC_LIST} )
#附加依赖项
target_link_libraries(hello OpenGL32 GLU32)

下面是一篇极好的CMake学习文档,CMake practice

 

fatal error LNK1112: 模块计算机类型“X86”与目标计算机类型“x64”冲突-解决

编译项目,遇到了这个问题

查了很多地方,解决方案是:

1.右键项目,属性,最顶端,配置为x64或者x86(如果没有该选项就新建)

2.链接器-高级,目标计算机选为一致的

运行还是会报这个错误

最后发现

3.链接器-命令行

最底部有一条指令,修改为一致的机型就可以了

Sqlite常规操作 add update select

用到了数据库,花了好长时间才搞定,把遇到的问题记录一下,sqlite语法:

select,最简单的语句

select * from table where condition

add

add中有两个需求

1.没有表的时候创建表

create table if not exists

2.如果存在则更新,不存在就插入

insert or replace into table ()values()

这里需要配合 primary key,用unique会报错

3.update

update table set x = x where condition

 

多次遇到 near syntax error,这些肯定是语法拼写错误,请仔细检查。

 

CSS:position、float

之前写css,一直是把position:absolute当做android的FrameLayout用的,其他类似。

后来看了下面的文章,满面羞愧。

这些基础的东西,还是要了解透彻的,一直不求甚解的搞下去,自己都不知道做的什么,为什么会出现这种错误,希望能从下面的内容中,总结出一个类似于Androidlayout的规则。

关于position看下面的文章就够了

http://blog.csdn.net/chen_zw/article/details/8741365

css属性大全

http://css.doyoe.com/

这里主要记一下看完自己的理解:

文档流

首先需要了解什么是文档流,可以理解为方块布局,从上到下,从左到右的布局方式就是文档流。

1.margin和padding是占用文档流的,也就是说,layout函数一定是这么写的

element.margin + elment.width/height +element.padding = dom真正占用的空间。

position:static很容易理解,完全遵循文档流。

position:relative 有点特殊,本身遵循文档流,但可以在文档流中使用top left bottom right设置偏移,偏移不遵循文档流。需要注意的是,后面的dom会按照relative元素不偏移来排列。layout函数中完全可以把relative按照static先处理,最后在当前位置进行偏移。

注:relative static无父辈时以body为参考;

position:absolute 脱离文档流,使用top left bottom right设置偏移,偏移参照为父辈最近的非static元素(之前一直认为absolute参照window,深刻检讨)。

注:absolute无父辈时以html为参考。

1、body默认有9个px的margin

2、absolute的元素没有设置top、left时,默认是文档流的位置,会造成设置了absolute,看起来没有效果的现象。

position:fixed fixed以window为参考(即不管你怎么scroll,位置都不会变),设置偏移。

float:absolute会屏蔽掉float,其他的可以共存。

float不遵循文档流。

clear:clear是配合float使用的。意思是把dom的哪边给清除掉。

如clear:both,意思是两边都不许浮动。

如果我来写 html的layout,

1.dom tree static,relative的按照文档流布局,relative单独处理下偏移,完全不影响文档流。

fixed很简单粗暴。

2.处理absolute float

absolute屏蔽float

absolute需要寻找父辈非static元素直到html,比较蛋疼。这个webkit在渲染的时候会把absolute的元素单独出来一层。

float是浮动排版,按文档流布局就差不多。

当然,css3还有更多的排版方式,上面几种已经基本够用,如果还要学习的话就是box了。

JS-call apply bind

经常碰到JS中的这三兄弟,记一下他们的用法和区别。

1.改变函数上下文

2.就算不为了改变,但JS那坑爹的作用域下,也为了能够明确知道函数上下文

(为什么要改变请参考JS的作用域链)

区别:

call与apply

call与apply用法很相似,区别就是一个是一个一个传参数,一个是传一个参数数组

fun().call(object, p1, p2);

fun().apply(object, [p1,p2]);

或者经常直接继承父函数参数

fun().apply(object, arguments);

call和apply都会立刻执行,只是改变了fun()里面的this

bind不会立刻执行,bind会返回一个指定上下文的函数

var fun1 = fun().bind(object, p1, p2); //参数传递跟call一样

bind最适合作为回调函数使用,尤其是setTimeout

func(function(){}.bind(this));

我们知道,setTimeout的回调函数上下文会被置为window(use strict下是null),在setTimeout中没办法使用原有实例,bind就可以了

setTimeout(function(){}.bind(this), 1000);

JS-使用canvas绘制动画

HTML5中提供了transform transition等动画方式,已经能够满足绝大部分动画需求。

但在移动端,使用Transform等还是会出现不流畅的情况,比如背景上一个无限循环的动画,不管是使用setInterval 还是捕捉每次的AnimationEnd来实现,都会有一定的问题,因为我们设定的延时还是动画时间都不能得到保证,并且会影响页面性能。

优化是无尽的,所以学习使用Canvas

使用Canvas能做什么?

1.知道/控制每帧的绘制

2.预加载img来绘制

3.canvas保证了性能

如何使用Canvas?

http://www.w3school.com.cn/html5/html_5_canvas.asp

W3C等有canvas的简单介绍,使用Canvas的基本步骤就是

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");

拿到canvas标签的dom,调用dom的getContext接口拿到Canvas类,就可以使用canvas的各种接口了

Canvas接口手册:http://www.w3school.com.cn/tags/html_ref_canvas.asp

canvas简单使用

1.绘制矩形

cxt.fillStyle="#FF0000";
cxt.fillRect(0,0,150,75);

2.绘制线

cxt.moveTo(10,10);
cxt.lineTo(150,50);
cxt.lineTo(10,50);
cxt.stroke();

3.绘制圆形

cxt.fillStyle="#FF0000";
cxt.beginPath();
cxt.arc(70,18,15,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();

4.绘制渐变

var grd=cxt.createLinearGradient(0,0,175,50);
grd.addColorStop(0,"#FF0000");
grd.addColorStop(1,"#00FF00");
cxt.fillStyle=grd;
cxt.fillRect(0,0,175,50);

5.绘制图

var img=new Image()
img.src="flower.png"
cxt.drawImage(img,0,0);

这些绘制组合使用基本上可以满足我们的一般绘制需求。

绘制动画基本流程

But,如果要绘制动画,还需要配合另一个神接口,

requestAnimationFrame

requestAnimationFrame的用法请自行google。大概原理就是,requestAnimationFrame需要传入一个函数,浏览器每绘制一帧都会通过requestAnimationFrame来调用这个函数。通常,我们把这个函数命名为step,在step中,放入我们的draw函数(这里与Android的draw流程很类似,不过Android更方便些)。

draw与requestAnimationFrame绑定

this.show = function() {
    var step = function() {
        this.draw();
        this.animationId = requestAnimationFrame(step.bind(this));
    };
    this.animationId = requestAnimationFrame(step.bind(this));
    this.element.style.visibility = "visible";
};

解绑(这里把绑定与show/hide放到了一起)

this.hide = function() {
    cancelAnimationFrame(this.animationId);
    this.element && (this.element.style.visibility = "hidden");
};

draw函数

this.draw = function() {
    this.flash++;
    this.context.clearRect(0, 0, this.element.width, this.element.height);
    this.rect0.update();
    this.rect0.draw(this.context);
};

draw函数中我们把绘制分为两步,一步是update(和Android类比就是在这里做mesure,确定View中各个元素的位置),第二步是绘制。

子View中实现各自的update和draw

需要注意的是,Canvas的使用宽高默认为300 150,我们设定的宽高只会对Canvas进行缩放。

update-动画曲线

使用css动画时,可以方便的给一个动画曲线,比如easeinout等,使用canvas绘制就需要我们不断的update绘制范围。

this.update = function() {
    if (!this.isAnimating) {
        return;
    }
    this.t += 0.05;
    switch (this.direction) {
        case "right":
            this.x = easeInOutQuint(this.t) * 70;
            break;
        case "down":
            this.y = easeInOutQuint(this.t) * 70;
            break;
        case "left":
            this.x = (1 - easeInOutQuint(this.t)) * 70;
            break;
        case "up":
            this.y = (1 - easeInOutQuint(this.t)) * 70;
            break;
    }
    if (this.t >= 1) {
        this.nextDirection();
        this.t = 0;
    }
};

在update里面,我们完成让一个矩形以指定动画曲线在四个方向转圈的位移。

缓动函数就负责返回位移的值

下面的easeInOutQuint按照步进返回值

var easeInOutQuint = function (t) {
    return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
};

更高明的做法,比如Jquery中,以时间为参数

function easeOutBounce(progress, currentTime, begin, change, duration) {
    if ((currentTime/=duration) < (1/2.75)) {
        return change*(7.5625*currentTime*currentTime) + begin;
    } else if (currentTime < (2/2.75)) {
        return change*(7.5625*(currentTime-=(1.5/2.75))*currentTime + .75) + begin;
    } else if (currentTime < (2.5/2.75)) {
        return change*(7.5625*(currentTime-=(2.25/2.75))*currentTime + .9375) + begin;
    } else {
        return change*(7.5625*(currentTime-=(2.625/2.75))*currentTime + .984375) + begin;
    }
}

draw就比较简单了

this.draw = function(ctx) {
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, 70, 70);
};