hammer崔的程序世界

我的生涯一片无悔,我想起那个午夜在灯泡下的抠代码,那是我逝去的青春!


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

  • 搜索
close

android基础:内存泄漏

发表于 2017-02-20   |   分类于 android   |  

本文主要探讨,如何避免内存泄漏,以及内存泄漏的发现与分析。

ES6语法:apply、call、compose函数、柯里化函数

发表于 2016-12-13   |   分类于 ES6   |  

参考文章

JavaScript 函数式编程 (ES6)

JavaScript柯里化

浅析 JavaScript 中的 函数 currying 柯里化

JS中的call()和apply()方法

apply与call的区别

区分apply与call只有一句话

foo.call(this, arg1,arg2,arg3) == foo.apply(this, arguments)==this.foo(arg1, arg2, arg3)

call,apply都是Function.prototype(prototype是javascript的原型模式)的方法,是JavaScript引擎的内在实现,意味着每个Function对象实例,就是每个方法都有call,apply属性。

  • 相同点:作用完全相同
  • 不同点:传递参数不同,call传递参数序列,apply传递数组

this指代上下文对象,是指每个实例的this,代码在该this内执行。

当this为null时,指向全局对象,意思是调用一个函数时,不是一个具体对象的方法

arguments

使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们,意味着能以数组的形式,遍历函数的所有参数。

举个栗子

1
2
3
4
5
6
7
componentDidMount() {
this.testArguments(1,2,3,4,5,6);
}
testArguments(){
console.log("arguments",[].slice.call(arguments));
//arguments=[1,2,3,4,5,6]
}

柯里化curry

简单的说柯里化就是通过传入函数所需的部分参数,将一个函数分割为多个的一种技术。或者叫分部传参数求解。

柯里化允许你将一个函数转换为一些列函数,在经常调用一个相同参数的函数时,柯里化是很好的解决方案。

举个例子

1
2
3
4
5
6
7
8
9
function multiplier(x, y){
if(y===undefined){
return function(z){
return x * z;
}
}else{
return x*y;
}
}

利用闭包特性,函数会保留之前的传递的x

multiplier(3, 4) == multiplier (3)(4)

一个典型的柯里化函数

1
2
3
4
5
6
7
8
9
10
11
12
componentDidMount() {
...
var reciprocal = this.curry(divider,1);
reciprocal(2);
}
curry(func) {
var fixedArgs = [].slice.call(arguments,1);
return function() {
var args = fixedArgs.concat([].slice.call(arguments));
return func.apply(null, args);
};
}

执行reciprocal(2)相当于执行了this.curry(divider,1)(2),下面来重点讲解执行过程。

  1. this.curry执行[].slice.call(arguments,1),去掉传入的第一个参数即divider函数,返回fixedArgs,此时

fixedArgs=[1]

  1. 继续执行返回匿名函数,同时传入变量2
  2. 执行匿名函数,fixedArgs.concat([].slice.call(arguments)),将现在的变量arguments和之前的变量合并,返回args
  3. 使用apply执行第一个参数就是divider函数,参数是上一步拼接好的args函数
  4. 返回结果,完毕。

ES6语法:三个点参数

发表于 2016-12-12   |   分类于 ES6   |  

rest参数

ES6 引入 rest 参数(形式为“…变量名”)

  • rest参数中的变量代表一个数组
  • 函数的length属性,不包括rest参数
  • rest参数后不能再有其他参数,否则报错
1
2
3
4
// 报错
function f(a, ...b, c) {
// ...
}

与箭头函数结合

1
2
3
4
const numbers = (...nums) => nums;

numbers(1, 2, 3, 4, 5)
// [1,2,3,4,5]

扩展运算符

1
2
3
4
// ES6的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2); //arr1=[0,1,2,3,4,5]

扩展运算符也可以与解构赋值结合起来,用于生成数组。
但是只能放在参数的最后一位

1
2
3
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]

扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符

1
2
3
4
5
6
7
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);

let arr = [...map.keys()]; // [1, 2, 3]

react-native基础:redux学习2-实战篇

发表于 2016-12-03   |   分类于 react-native basis   |  

导航

react-native基础:redux学习1-理论篇

react-native基础:redux学习2-实战篇

本篇blog是在对redux理论知识有了足够了解后,做的实战架构。

实战

安装需要用到的库

1
2
3
4
5
npm install --save redux
npm install --save react-redux
npm install --save redux-devtools
npm install --save redux-thunk
npm install --save redux-logger

react绑定库跟开发者工具
redux
react-redux
redux-devtools

异步action构造器redux-thunk

日志工具
redux-logger

基础用法 同步的action

引入支持

1
2
import { createStore } from 'redux'
import { Provider, connect } from 'react-redux'

将根组件包装进<Provider>

1
2
3
4
5
6
7
8
9
10
11
//reducer函数,所有的
function reducer(state={},action){
}
let store = createStore(todoApp);

render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)

通过 react-redux 提供的 connect() 方法将包装好的组件连接到Redux。尽量只做一个顶层的组件,或者 route 处理

任何一个从 connect() 包装好的组件都可以得到一个 dispatch 方法作为组件的 props,以及得到全局 state 中所需的任何内容。 connect() 的唯一参数是 selector。

1
2
3
4
5
6
7
8
9
10
const PageContainer = connect()(PageContainer);

let store = createStore(todoApp);

render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)

高价用法 异步action

如何把action creator跟网络请求结合起来呢。

redux-thunk:一个搭建异步action的构造器。
其作用就是把一些比较复杂的动作(例如这里用到的异步操作)封装到一个action中去。

通过使用指定的 middleware,action creator 除了返回 action 对象外还可以返回函数。这时,这个 action creator 就成为了 thunk。

当 action creator 返回函数时,这个函数会被 Redux Thunk middleware 执行。这个函数并不需要保持纯净;它还可以带有副作用,包括执行异步 API 请求。这个函数还可以 dispatch action,就像 dispatch 前面定义的同步 action 一样。

注意dispatch定义:通过 store.dispatch() 将 action 传到 store

使用 ES6 计算属性语法,使用 Object.assign() 来简洁高效地更新 state的值

1
return Object.assign({}, state, newState);

注意事项

  • fetch
    当我们在react-native版本可以直接使用这个强大的网络操作API,当时在react-web中大多数浏览器不支持,建议使用[isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch.所以我考虑还是在web项目使用jQuery,最稳妥。
1
2
// 每次使用 `fetch` 前都这样调用一下
import fetch from 'isomorphic-fetch'

react-native基础:global全局变量和持久化

发表于 2016-12-02   |   分类于 react-native basis   |  

如何实现react-native的全局变量呢

参考网上的答案,使用global,类似于web的window,
比如
global.isBeat = true,
全局就知道这是一个测试版

如何做持久化存储呢

推荐react-native-storage

  • 支持react-native(AsyncStorage,简单的异步的持久化的key-value存储系统)
  • 支持浏览器(localStorage)
  • es6语法,promise异步读取,使用jest进行单元测试

推荐new出来的Storage给global,这样我们就能全局使用了。
比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var storage = new Storage({
// 最大容量,默认值1000条数据循环存储
size: 1000,

// 存储引擎:对于RN使用AsyncStorage,对于web使用window.localStorage
// 如果不指定则数据只会保存在内存中,重启后即丢失
storageBackend: AsyncStorage,

// 数据过期时间,默认一整天(1000 * 3600 * 24 毫秒),设为null则永不过期
defaultExpires: 1000 * 3600 * 24,

// 读写时在内存中缓存数据。默认启用。
enableCache: true,

}

global.storage = storage;

保存 读取 删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// 使用key来保存数据。这些数据一般是全局独有的,常常需要调用的。
// 除非你手动移除,这些数据会被永久保存,而且默认不会过期。
storage.save({
key: 'loginState', // 注意:请不要在key中使用_下划线符号!
rawData: {
from: 'some other site',
userid: 'some userid',
token: 'some token'
},

// 如果不指定过期时间,则会使用defaultExpires参数
// 如果设为null,则永不过期
expires: 1000 * 3600
});

// 读取
storage.load({
key: 'loginState',

// autoSync(默认为true)意味着在没有找到数据或数据过期时自动调用相应的sync方法
autoSync: true,

// syncInBackground(默认为true)意味着如果数据过期,
// 在调用sync方法的同时先返回已经过期的数据。
// 设置为false的话,则始终强制返回sync方法提供的最新数据(当然会需要更多等待时间)。
syncInBackground: true
}).then(ret => {
// 如果找到数据,则在then方法中返回
// 注意:这是异步返回的结果(不了解异步请自行搜索学习)
// 你只能在then这个方法内继续处理ret数据
// 而不能在then以外处理
// 也没有办法“变成”同步返回
// 你也可以使用“看似”同步的async/await语法

console.log(ret.userid);
this.setState({ user: ret });
}).catch(err => {
//如果没有找到数据且没有sync方法,
//或者有其他异常,则在catch中返回
console.warn(err.message);
switch (err.name) {
case 'NotFoundError':
// TODO;
break;
case 'ExpiredError':
// TODO
break;
}
})

// --------------------------------------------------

// 获取某个key下的所有id
storage.getIdsForKey('user').then(ids => {
console.log(ids);
});

// 获取某个key下的所有数据
storage.getAllDataForKey('user').then(users => {
console.log(users);
});

// !! 清除某个key下的所有数据
storage.clearMapForKey('user');

// --------------------------------------------------

// 删除单个数据
storage.remove({
key: 'lastPage'
});
storage.remove({
key: 'user',
id: '1001'
});

// !! 清空map,移除所有"key-id"数据(但会保留只有key的数据)
storage.clearMap();

react-native基础:redux学习1-理论篇

发表于 2016-11-29   |   分类于 react-native basis   |  

导航

react-native基础:redux学习1-理论篇

react-native基础:redux学习2-实战篇

理论

本篇blog主要讲解redux的一些理论,以及第三方的组件库和其优秀的解决思路,所谓理论现行。

我在查阅了大量参考文章和blog后,有感于大部分文章都侧重于讲某个点,而没有系统的让初学者从0开始对redux进行理解,所以写下了这篇总结。

当然我们首先还是要站在巨人的肩膀,需要预先阅读一下文档,我起初读完以下文档也是萌萌哒,直到对所有的知识串起来思考,才有恍然大悟的感觉。首先是Redux 中文文档,然后是深入到源码:解读 redux 的设计思路与用法,以及React-Native With Redux,最后如果对redux的基础知识有了初步了解,可以看下这个讨论帖这段时间研究了下Redux,写写自己对它的感觉。

Flex与Redux的关系

Redux是遵循了单向数据流Flex的设计,但是做了流程的简化。

Redux是javascript状态容器,提供可预测化的状态管理,可以构建一致化的应用,除了和React一起用外,还支持其他界面库,体积小(只有2kb)而且没有任何依赖。Redux由Flux演变而来,但是避开了Flux的复杂性,上手快,使用简单,而且社区活跃,是目前主流的Flux数据流框架(学习Redux可以参考Redux中文文档)

Redux总览

在 Redux 的[源码目录][redux-src] src/,我们可以看到如下文件结构:

1
2
3
4
5
6
7
8
├── utils/
│ ├── warning.js # 打酱油的,负责在控制台显示警告信息
├── applyMiddleware.js
├── bindActionCreators.js
├── combineReducers.js
├── compose.js
├── createStore.js
├── index.js # 入口文件
  • store: 应用中所有的state都以一个对象树的形式储存在一个单一的store中,state就是每个component里都存在的状态集合,你也可以理解为java类的属性和方法。
  • action: 惟一改变 state 的办法是触发 action,一个描述发生什么的对象。它是 store 数据的唯一来源。
  • reducers:为了描述 action 如何改变 state 树,你需要编写 reducers。
  • compose:没有依赖,是个纯函数,实现函数的层级合并,从右开始。
  • createStore:创建store的函数。参数是(reducer,初始化state,中间件),返回store
  • combineReducers(reducers):可以合并不同的reducer,便于不同功能的reducer进行分支化管理
  • bindActionCreators(actionCreators,dispacth):实现自动dispatch

§ action

action本质是是一个包含type属性的普通对象,type是它的key也是识别码。改变state必须dispatch一个action。

一般用法component的state其实是从props传递的,以propsMaptoState形式存储在store中。

高阶用法包括selector绑定,这是为了解决全局变化而对store的state做了最小化拆分

  • 存储最小的可能变化state
  • 提高效率,除非一个参数发生改变,否则不会重新计算
  • selector是可组合的,一个selector可以导出给其他selector使用

§ reducer

指明如何更新state,reducer 本质是一个一function,接收旧state 和 action,返回新的 state,我们叫nextState,也就是说每次返回的都是新的state,而不是旧state的副本。reducer返回啥,state就被替换成啥。

思考:这样就能实现数据的回滚了,比如执行redo,undo操作了。

§ store

Store 就是把它们联系到一起的对象。Store 有以下职责:

  • 维持应用的 state;
  • 提供 getState() 方法获取 state;
  • 提供 dispatch(action) 方法更新 state;
  • 通过 subscribe(listener) 注册监听器。

一个Redux应用只能有一个单一的store

§ compose

主要的作用是让代码更优雅,如下:

1
2
3
4
var re1 = func3(func2(func1(0)));
//替换为
var re2 = Redux.compose(func3, func2, func1)(0);
//是不是更优雅了

§ creteStore(reducer,initalState,enhaner)

经常的用法是创建store,并给store添加中间件

1
2
3
4
5
6
7
8
9
10
11
12
const finalCreateStore = Redux.compose(
中间件1,
中间件2,
中间件3
)(createStore)

const store = finalCreateStore(reducer);
//执行流程是
//reducer作为参数传递给函数createStore,返回store
//store作为参数传递给函数中间件3,返回store
//store作为参数传递给函数中间件2,返回store
//store作为参数传递给函数中间件1,返回store

§ combineReducers(reducers)

无论应用的状态树多复杂,都可以通过逐层下分,来管理对应部分的state,如下图

1
2
3
4
5
6
7
8
                                 aReducer(a_value, action) -------------------- a_value
↗ ↘
rootReducer(state, action) —→∑ ↗ b1Reducer(b1_value, action) ------ b1_value ↘ nextState
↘—→∑ b_value ↗
↘ b2Reducer(b2_value,action) ----- b2_value ↗


注:左侧表示 dispatch 分发流,∑ 表示 combineReducers;右侧表示各实体 reducer 的返回值,最后汇总整合成 nextState

无论dispatch哪个action,都会流通所有的reducer

这也是为何 reducer 必须返回其对应的 state 的原因。否则整合状态树时,该 reducer 对应的键值就是 undefined

§ bindActionCreators(actionCreators,diapatch)

把我们手动的action的dispatch过程变成了自动.

⊙ Redux 与传统后端 MVC 的对照

Redux 传统后端 MVC
store 数据库实例
state 数据库中存储的数据
dispatch(action) 用户发起请求
action: { type, payload } type 表示请求的 URL,payload 表示请求的数据
reducer 路由 + 控制器(handler)
reducer 中的 switch-case 分支 路由,根据 action.type 路由到对应的控制器
reducer 内部对 state 的处理 控制器对数据库进行增删改操作
reducer 返回 nextState 将修改后的记录写回数据库

第三方辅助类组件库

§ redux-actions

专门为redux准备的,flux standard action的工具集。

什么是flux standard action?

简称fsa,

1
2
3
4
5
6
7
{
type: 'ADD_TODO',
payload: {
text: 'Do something.'
}

}

出错时

1
2
3
4
5
{
type: 'ADD_TODO',
payload: new Error(),
error: true
}

type必须的,payload可选的,error可选的,meta可选的
判断一个action是否是flux standard action

1
2


createAction(type, payloadCreator = Identity, ?metaCreator)

  • 参数type:就是action的type,一般是string,
  • 参数payloadCreator:就是payload生成器,类型只能是function,undefined,或者null,

createAction是一个Action生成器,返回一个Flux Standard Action,这个Action的payLoad的值就是payloadCreator的返回值

举例:

1
2
3
4
5
let increment = createAction('INCREMENT', amount => amount);
expect(increment(42)).to.deep.equal({
type: 'INCREMENT',
payload: 42
});

好处是如果payload是一个Error对象(new TypeError),react-actions就能自动把Action.error = true

举例:

1
2
3
4
5
6
7
8
const increment = createAction('INCREMENT');

const error = new TypeError('not a number');
expect(increment(error)).to.deep.equal({
type: 'INCREMENT',
payload: error,
error: true
});

createAction也能返回它的type,然后作为type传参给handleAction或者handleActions使用

  • 作为参数在handleAction中使用
  • 作为object key 在handleActions中使用

handleAction(type, reducer | reducerMap = Identity, defaultState)

包装一个reducer,这个reducer仅能处理一个,确定type的、flux标准的action。

  • 参数type:就是一个action的type
  • 参数reducer:就是reducer函数,用来处理传递的action里的payload和state,然后返回新的state
  • 参数defaultState,当reducer收到的参数是undefined时,就返回defaultState

handleActions(reducerMap, defaultState)

  • 参数reduerMap:就是一个action type为key,reducer为value的键值对。
  • 参数defaultState:

把大量使用handleAction创建的reducer合并

§ Reselect

Reselect是一个第三方库,解决数据冗余的问题。这个问题是怎么产生的呢?
首先:原本store中的state是通过props,数据一级一级的传递,在 render 中处理,避免了状态判断的问题,即拿到的数据总是最新的,缺点就是每次重新计算。

然后:一层层传递的数据,每个层级组件都要用,一旦原始数据被污染了,需要保存多份原始数据的处理结果,数据的冗余就出现了。

解决方案:
Container component 模式很,就是每个组件connect自己所需要的数据.

reselect的三个特性

  • Selectors can compute derived data, allowing Redux to store the minimal possible state.(Selectors可以计算派生数据,允许Redux存储最小可用state)
  • Selectors are efficient. A selector is not recomputed unless one of its arguments change.(Selectors是高效的。除非其中一个参数发生更改,否则不会重新计算Selectors)
  • Selectors are composable. They can be used as input to other selectors.(Selectors是可组合的,也可以作为input给其他Selectors使用)

React-Redux容器组件与展示组件分离的开发思想

这个在Redux 中文文档中有详细跟直观的讲解。
通俗来讲就是,一个Redux应用切成两部分来管理数据流

  • Container:容器组件

    -在这里使用redux,控制分发需要向下传递的state,action创建函数
    
  • View:展示组件

    -我们要展示数据的的view,以及触发action的操作
    

参考文献

Redux 中文文档

React-Native With Redux

深入到源码:解读 redux 的设计思路与用法

这段时间研究了下Redux,写写自己对它的感觉。

Redux 简明教程

react-native学习路线

发表于 2016-11-26   |   分类于 react-native basis   |  

react-native是Facebook推出的跨平台开发技术,使用JavaScript代码,目前是es6。主要涉及知识点flexbox(弹性工具盒)布局,flux来管理数据流动

初级阶段

  • es6语法
    • promis
    • async,waite
    • lodash:是具有一致接口,模块化,高性能等特性的JavaScript工具库。
  • npm安装,react-native安装,环境搭建
  • 了解Props,State
  • 学习样式jxs,flexbox
  • 学习导航器

进阶阶段

  • es6语法
    • 三个点参数用法(rest参数,spread操作符)
    • 异步函数(Promise,Async)
    • array操作(join,conact,map…)
    • babel(es6转译es5)
    • Object.assign(obj,…):扩展操作
    • 柯里化(curry)函数:参数逐渐求值的过程
    • compose函数
  • 学习redux,了解它与flux的区别,学会如何使用单项数据流的思想管理状态树。它的使用场景会更多。你也可以看做它是简化了流程的flux。

    • action
    • reducer
    • store
    • middleWare
    • redux-thunk:比较流行的redux异步action中间件,统一了异步和同步action的调用方式,避免在component动刀子。
  • 学习Reselect:构建粒度化的数据,Reselect 库可以创建可记忆的(Memoized)、可组合的 selector 函数。Reselect selectors 可以用来高效地计算 Redux store 里的衍生数据。

  • 学习react-native-drawer:可用于Android ios的抽屉式控件。
  • 学习react-native-model-picker:一个比较好用的model picker,兼容Android iOS

  • 学习redux-watch:一个可以检测全局store数据变动的组件,常用于全局的状态变化,比如登录数据:当发现token不一致时,弹出登录界面。比如全局检测错误数据:根据错误id显示不同的提示。

  • 文件系统
    • react-native-fs:react-native调用本地 文件系统的库,兼容Android iOS
    • react-native-file-transfer:ios专用的从图片库往服务器上传库
    • react-native-fileupload:兼容iOS Android上传文件的库。支持 1 同时上传多个文件 2 支持file and fields
  • 导航
    • react-native-router-flux:可配合redux的路由导航库,目前最全面,功能最强大。常用于构建整个APP的路由规则。
      • react-native-scrollable-tab-view:带scroll滑动切换的tab view
      • react-native-tabs:简版的底部tabbar导航栏,常见于ios应用,兼容Android iOS

解坑阶段

坑1:ipad 模拟器 command+D 程序崩溃

0.3.6才有的问题,ipad丢失了actionsheet布局
修复:
在React/Modules/RctDevMenu.m第519行新增

1
UIAlertControllerStyle style = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone ? UIAlertControllerStyleActionSheet : UIAlertControllerStyleAlert;

然后把519行的

1
2
3
_actionSheet = [UIAlertController alertControllerWithTitle:title
message:@""
preferredStyle:UIAlertControllerStyleActionSheet];

替换为

1
2
3
_actionSheet = [UIAlertController alertControllerWithTitle:title
message:@""
preferredStyle:style];

android学习路线

发表于 2016-11-21   |   分类于 android   |  

初级阶段

技术要求:

  • 四大组件Activity,Service, BroadcastReceive,ContentProvider的使用.参考文章
  • Fragment
  • ui设计
    • 各类layout
    • 简单自定义view,各种用户界面
    • 动画[包括valueAnimator,ObjectAnimator]
    • Bitmap,Canvas
  • 数据存储
    • sharePerference
    • SQLite3,GreenDao,Realm

书籍推荐:

  • 《Thinking in java》 经典

网站推荐:

  • google api guides官方api,不知道怎么用,就看官方的
  • 极客学院Android wiki非常全面
  • Stack Overflow android tag

中级阶段

技术要求

  • aidl:熟悉aidl,理解其工作原理,懂transact和onTransact的区别
  • Binder:从java层大概理解Binder的工作原理,懂Parcel对象的使用
  • 多进程:多进程的运行机制,消息队列,Messenger,Socket
  • 事件分发:弹性滑动 滑动冲突
  • 玩转view: view的绘制原理,各种自定义view
  • 动画系列:熟悉view动画和属性动画的不同点,懂ObjectAnimator的工作原理
  • 懂性能优化,熟悉mat等工具
  • 熟悉常见的设计模式,比如mvp,mvvm
  • 熟悉rxjava响应式编程

学习方法

  • 阅读源码
  • view以及事件分发
    • view的滑动原理
    • 如何实现弹性滑动
    • view的滑动冲突
    • view的measure,layout,draw
    • 自己实现几个经典的view

高级阶段

技术要求

  • 了解SystemSever的启动过程
  • 了解AndroidFramework层的内容
  • 了解主线程的消息循环模型
  • 了解ams和psm的工作原理
  • 了解Windows
  • Activity的启动模式以及异常情况下不同Activity的表现
  • Service的onBind和onReBind的关联
  • onServiceDisconnected(ComponentName className)和binderDied()的区别
  • AsyncTask在不同版本上的表现细节
  • 线程池的细节和参数配置

总结

  • 系统核心机制
  • 基础知识点的细节
  • 设计模式和架构
  • 了解这张图的底层细节
    image

推荐书籍

  • 《android内核剖析》

android基础:控件集锦

发表于 2016-11-20   |   分类于 android   |  

汇总常用的或者经常忘记的Android控件

DrawerLayout

弹出式抽屉视图
DrawerLayout 控件的子视图必须是2个,1个显示原视图,1个显示弹出的抽屉视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.inthecheesefactory.lab.designlibrary.CodeLabActivity">
<!--视图1:原视图-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<!--视图2:弹出的抽屉视图 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ffffff"
android:orientation="vertical">

</LinearLayout>

硬按键控制音量

1 添加权限
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

2 新建控制音量类实例

1
2
 //音量控制,初始化定义
 private AudioManager mAudioManager;

3 实例初始化,在onCreat()中:

1
2
mAudioManager = (AudioManager) 
getSystemService(Context.AUDIO_SERVICE);

4 具体调节音量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

int currentVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
switch(keyCode)
{
case KeyEvent.KEYCODE_VOLUME_UP:
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume+1, 1);
return true;

case KeyEvent.KEYCODE_VOLUME_DOWN:
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume-1, 1);
return true;
}

return super.onKeyDown(keyCode, event);
}

home按键切换后台

1借用surface改变:
切换后台触发:

1
2
3
4
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
  // TODO Auto-generated method stub
  Log.v("admob", "surfaceChanged!");
 }

回到前台触发:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void surfaceCreated(SurfaceHolder arg0) {	//activity resume
  // TODO Auto-generated method stub
  if(isPause && m_State == GAME_PLAY){
   AlertDialog.Builder builder = new AlertDialog.Builder(GameActivity.mContext);
   builder.setTitle("Alert")
   .setMessage("Game is paused,press OK resume")
      .setCancelable(false)
      .setPositiveButton("OK", new DialogInterface.OnClickListener() {
       public void onClick(DialogInterface dialog, int which) {
        // TODO Auto-generated method stub
        mLoopHandler.start();
       }
      });
   AlertDialog alert = builder.create();
   alert.show();
  }else{
   mLoopHandler.start();
  }
  isPause = false;
 }
```

## action bar使用
action bar是3.0之后系统自带的控件,

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aty_securityissue_creat);
actionBar= getActionBar();
actionBar.show();

}

1
2
3


//创建菜单

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
super.onCreateOptionsMenu(menu);
//添加菜单项
MenuItem add=menu.add(0,0,0,”add”);
MenuItem del=menu.add(0,0,0,”del”);
MenuItem save=menu.add(0,0,0,”save”);
//绑定到ActionBar
add.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
del.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
save.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
return true;
}

//选择菜单
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
```

FragmentTabHost

参考案例

python学习笔记:6 tornado

发表于 2016-09-13   |   分类于 python   |  

tornad是Facebook开源的非阻塞式web框架,类似于nodejs,主要是为了解决frendfeed的实时更新。因此相应速度非常高。

安装

win10环境:

1
pip install tornado

mongodb数据库:官网下载地址

数据库请求

Mysql

Tornado-MySQL,是对PyMySQL的异步化的一个库,测试用例,文档,都比较齐全,目前在使用的版本。

异步web请求

使用异步装饰器,实现异步功能

1
2
3
4
5
6
7
8
9
10
11
class TestAsynchr2(tornado.web.RequestHandler):
@tornado.web.asynchronous
@tornado.gen.engine
def get(self, *args, **kwargs):
client = tornado.httpclient.AsyncHTTPClient();
response = yield tornado.gen.Task(client.fetch,test_url)
body = json.loads(response.body)
print '异步请求2 %s' % body
print body['errNum']
self.write('异步请求2 %s' % response.body)
self.finish()

重点是yield,以及self.finish()

使用asyncmongo,来异步的调用mongoDB服务器。它是专门给Tornado开发者开发提供异步数据库访问的

使用tornado进行长轮询

传统的方案是浏览器js进行定时http轮训,但是对服务器压力太大了。
新的技术是让浏览器发起连接来模拟服务器推送更新。这种方式的HTTP连接被称为长轮询或Comet请求。意味着浏览器只需启动一个http请求,其连接的服务器会有意保持开启,浏览器只需要等待更新可用时服务器”推送”响应。当服务器发送响应并关闭连接后,(或者浏览器端客户请求超时),客户端只需打开一个新的连接并等待下一个更新。

好处:

  • 减少web服务器负载
  • 浏览器兼容性,只要支持ajax即可
  • 比如状态更新,消息通知,聊天消息,Twitter显示通知,Facebook的聊天
  • 跟websockets的实现方式不同

常见问题

修改mysql默认字符集

最简单的方法:修改mysql的my.ini配置文件.

1
2
default-character-set = utf8
character_set_server = utf8

python2.7查询mysql的中文乱码

解决方法:

1
2
3
4
5
6
7
8
9
10
reload(sys)
sys.setdefaultencoding('utf-8')

conn = yield tornado_mysql
.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='test',charset='utf8')

然后
print value.decode('utf-8')
如果是插入
则是value = unicode('你好',’utf-8')

12…7
hammercui

hammercui

69 日志
13 分类
19 标签
RSS
github
Links
  • logicool的技术专栏
  • xiekw2010的专栏
  • 江清清的技术专栏
© 2017 hammercui
由 Hexo 强力驱动
主题 - NexT.Pisces