李晓鹏
Adam
2017-01-07T04:15:39.186Z
http://xpleeandroid.github.io/
Adam
Hexo
再见2016,Hello 2017
http://xpleeandroid.github.io/2017/01/03/goodbye2016-hello2017/
2017-01-03T01:32:38.000Z
2017-01-07T04:15:39.186Z
<p> 写之前看了14年的总结,感慨颇多。专业大学毕业已经过了两个年头。 </p>
<a id="more"></a>
<h2 id="2016"><a href="#2016" class="headerlink" title="2016"></a>2016</h2><ul>
<li>工作上</li>
</ul>
<p>上半年比较空闲,下半年比较忙碌。在现在的公司将近两年,刚进来的时候做一直做安卓开发,上半年公司比较尴尬,老同事因为薪资等问题纷纷离职,还碰到了工作以来很多狗血的老板与员工之间的问题。上半年自己也一直想走,想离开,去找个靠谱的公司,起码工资高,没那么多烦心事,但是一直没有开口,期间也有朋友同事介绍过几家公司,待遇啥的都比较靠谱,由于我个人的原因没有去。最终公司技术只剩下两人,后来来了一个IOS美女同事,2016进入下半年。由于后台技术一直空缺,下半年开始接手PHP的工作,之前自己学过PHP基础,所以接手还是比较顺畅的,开始恶补后端知识,没多久就开始开发公司项目了。</p>
<ul>
<li>生活上</li>
</ul>
<p>从崂山搬到了李沧区,到公司十分钟,学会了做菜,做很多菜,自己感觉也蛮好吃。又胖了,毕业以后一直在胖着,从来没间断。</p>
<ul>
<li>学习上</li>
</ul>
<p>程序方面 PHP MYSQL 前端统统学习了一遍。接触了点日语跟西班牙语。</p>
<ul>
<li>总结</li>
</ul>
<p>选择有时候可能会大于努力;<br>该减肥了;做事情一定要提高效率,不一定事半功倍,但是不要事倍功半;早起,多喝水(周老师说不合适膀胱会出问题),多运动。</p>
<h2 id="2017"><a href="#2017" class="headerlink" title="2017"></a>2017</h2><ul>
<li>工作上</li>
</ul>
<p>做正确的选择,多为家人,为自己考虑一下。</p>
<ul>
<li>生活上</li>
</ul>
<p>做正确的选择,多为家人,为自己考虑一下。<br>早起,运动,尽量是早饭和午饭。买个像样的衣服鞋子。多与别人交流,尤其不是程序员不同行业的同学朋友。多交朋友,对人实实在在。</p>
<ul>
<li>学习上 </li>
</ul>
<p>深入学习PHP,多读读程序源码,学习小程序开发,熟悉一下微信开发,深入学习JS. Android上多看源码.<br>把自己规划要做的东西抓紧做出来,PC和APP.<br>日语争取进一个台阶。</p>
<p> 写之前看了14年的总结,感慨颇多。专业大学毕业已经过了两个年头。 </p>
Visual-Represenation-of-Sql-Joins
http://xpleeandroid.github.io/2016/12/27/Visual-Represenation-of-Sql-Joins/
2016-12-27T05:28:30.000Z
2016-12-27T05:38:53.720Z
<p><img src="https://xpleeandroid.github.io/img/sql/Visual_SQL_JOINS_orig.jpg" alt=""></p>
<p>IMAGE Quote from <a href="https://www.codeproject.com/articles/33052/visual-representation-of-sql-joins" title="Code Project" target="_blank" rel="external">Code Project</a></p>
<p><img src="https://xpleeandroid.github.io/img/sql/Visual_SQL_JOINS_orig.jpg" alt=""></p>
<p>IMAGE Quote from <a href="https://www.codeproj
lnmp pathinfo设置
http://xpleeandroid.github.io/2016/11/08/tp5-lnmp-pathinfo/
2016-11-07T16:21:23.000Z
2016-11-07T16:28:56.247Z
<p>今晚在centos服务器上上传了一个tp5的demo:<br><a href="http://yuedu.lixiaopeng.top/public/index.php访问没有问题" target="_blank" rel="external">http://yuedu.lixiaopeng.top/public/index.php访问没有问题</a><br><a href="http://yuedu.lixiaopeng.top/public/index.php/index却访问显示404错误,权限给了。google了一堆,都不能解决问题,最后在lnmp网站找到了解决办法:" target="_blank" rel="external">http://yuedu.lixiaopeng.top/public/index.php/index却访问显示404错误,权限给了。google了一堆,都不能解决问题,最后在lnmp网站找到了解决办法:</a></p>
<pre><code>`lnmp v1.1上,修改对应虚拟主机的配置文件
去掉#include pathinfo.conf前面的#,把try_files $uri =404; 前面加上# 注释掉。
1.2,1.3上,修改对应虚拟主机的配置文件
将include enable-php.conf;替换为include enable-php-pathinfo.conf;
修改pathinfo需要重启nginx生效。`
</code></pre>
<p>今晚在centos服务器上上传了一个tp5的demo:<br><a href="http://yuedu.lixiaopeng.top/public/index.php访问没有问题" target="_blank" rel="external">http://yuedu.l
CentOS 允许mysql远程连接
http://xpleeandroid.github.io/2016/10/19/centos-allow-remote-mysql/
2016-10-19T15:01:29.000Z
2016-10-19T15:09:57.360Z
<hr>
<p>搭建ss过程中在另一台服务器上开启ss manyuser始终连接不上,错误日志是无法连接远程数据库,所以google了如下解决办法,以后就不用再找了: </p>
<pre><code>mysql -u root -p 输入数据库密码
mysql控制台运行:
grant all privileges on *.* to 'root'@'%' identified by '数据库密码' with grant option;
flush privileges; # 重载系统权限
exit;
允许3306端口
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT
iptables -L -n # 或者: service iptables status
此时生产环境是不安全的,远程管理之后应该关闭端口,删除之前添加的规则
iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT
</code></pre>
<hr>
<p>搭建ss过程中在另一台服务器上开启ss manyuser始终连接不上,错误日志是无法连接远程数据库,所以google了如下解决办法,以后就不用再找了: </p>
<pre><code>mysql -u root -p 输入数据库密码
mysql控制台运行:
g
CentOS搭建LNMP,搭建ss-panel以及后端经验总结
http://xpleeandroid.github.io/2016/10/19/centos-build-ss-panel-and-server/
2016-10-19T03:32:39.000Z
2016-10-19T07:53:29.788Z
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>几个月前开始搭建<a href="http://ss.lixiaopeng.top/" title="http://ss.lixiaopeng.top/" target="_blank" rel="external">http://ss.lixiaopeng.top/</a>shadowsocks并免费提供给别人使用,搭建过程中遇到不少问题,在这记录下来。</p>
<h1 id="安装LNMP"><a href="#安装LNMP" class="headerlink" title="安装LNMP"></a>安装LNMP</h1><pre><code>yum update //更新yum
wget -c http://soft.vpser.net/lnmp/lnmp1.3.tar.gz && tar zxf lnmp1.3.tar.gz && cd lnmp1.3 && ./install.sh lnmp 下载并安装lnmp
如果wget过程中出现
-bash: wget: command not found
那么执行 yum -y install wget 安装wget然后继续执行上一步。然后等待lnmp安装完成。
</code></pre><h1 id="安装ss-panel"><a href="#安装ss-panel" class="headerlink" title="安装ss-panel"></a>安装ss-panel</h1><pre><code>cd/home/wwwroot/default
git clone https://github.com/orvice/ss-panel.git
cp -R ss-panel/. ./
cp .env.example .env
vi .env 一次填写网站的配置信息,数据库信息
安装composer:
curl -sS https://getcomposer.org/installer | php
php composer.phar install
把phpmyadmin目录下的内容拷贝到public/phpmyadmin目录下:
cp -R phpmyadmin/. public/phpmyadmin/
添加管理员账号:
php xcat createAdmin
添加权限:
chmod -R 777 storage
添加www用户访问目录权限:
chown -R www /home/wwwroot/default/
cd /usr/local/nginx
vi nginx.conf
在 root /home/wwwroot/default后面加 /public
紧跟下面添加:
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
退出vi保存。
service nginx reload
</code></pre><h1 id="安装shadowsocks-manyuser"><a href="#安装shadowsocks-manyuser" class="headerlink" title="安装shadowsocks manyuser"></a>安装shadowsocks manyuser</h1><pre><code>mysql -root -p 输入数据库密码;执行use mysql;
grant all privileges on *.* to '数据库名'@'manyuser所在ip'identified by '密码' with grant option;
下载rm:
git clone -b manyuser https://github.com/mengskysama/shadowsocks-rm.git
安装pip: yum install python-pip -y (Centos7会报错需要这样执行: sudo yum -y install epel-release sudo yum -y install python-pip sudo yum clean all)
安装cymysql:
pip install cymysql
cd shadowsocks-rm
cd shadowsocks
vi config.py 填写相应信息保存退出。
python servers.py开启服务。
nohup python servers.py & 后台运行。
</code></pre>
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>几个月前开始搭建<a href="http://ss.lixiaopeng.top/" title="http://ss.lixiaopen
中文网站绑定Apache无法解析的问题解决办法
http://xpleeandroid.github.io/2016/10/14/apache-bind-chinese-domain/
2016-10-14T05:40:29.000Z
2016-10-14T05:52:36.872Z
<p>公司申请了俩网站,www.subanggo.com和www.速帮购.com,服务器上都配好了,今天域名备案成功,于是开始解析,解析中文域名始终不成功,google了一下吗,找到答案了:</p>
<p> 中文域名需要先转成punycode,再把punycode绑定到apache的vhost中,关于punycode,<a href="https://zh.wikipedia.org/wiki/Punycode" target="_blank" rel="external">维基中解释的很简洁</a> 不在缀余。<br>用<a href="http://www.cnnic.cn/jczyfw/zwym/zgymzcjsy/201206/t20120612_26523.htm?spm=5176.bbsr268165.0.0.i2QEbv" target="_blank" rel="external">在线工具</a>把shop.速帮购.com转成punycode格式:shop.xn–huT195Hu3B.com,然后再绑定到apache: </p>
<pre><code>#shop.速帮购
<VirtualHost *:80>
DocumentRoot "E:/server/ecmoban/upload"
ServerName shop.xn--huT195Hu3B.com:80
ServerAlias
ServerAdmin webmaster@shop.xn--huT195Hu3B.com
DirectoryIndex index.html index.htm index.php default.php app.php u.php
ErrorLog logs/shop.xn--huT195Hu3B.com-error.log
CustomLog logs/shop.xn--huT195Hu3B.com-access_%Y%m%d.log comonvhost
php_admin_value open_basedir "E:\server\ecmoban\upload\;E:\software\UPUPW_AP5.6-1510\UPUPW_AP5.6\htdocs\;E:\software\UPUPW_AP5.6-1510\UPUPW_AP5.6\memcached\;E:\software\UPUPW_AP5.6-1510\UPUPW_AP5.6\phpmyadmin\;E:\software\UPUPW_AP5.6-1510\UPUPW_AP5.6\temp\;C:\Windows\Temp\"
<Directory "E:/server/ecmoban/upload">
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<LocationMatch "/(inc)/(.*)$">
Require all denied
</LocationMatch>
<LocationMatch "/(attachment|attachments|uploadfiles|avatar)/(.*).(php|php5|phps|asp|asp.net|jsp)$">
Require all denied
</LocationMatch>
</VirtualHost>
</code></pre>
<p>公司申请了俩网站,www.subanggo.com和www.速帮购.com,服务器上都配好了,今天域名备案成功,于是开始解析,解析中文域名始终不成功,google了一下吗,找到答案了:</p>
<p> 中文域名需要先转成punycode,再把punycode绑定到apac
解决CentOS VI中文乱码问题
http://xpleeandroid.github.io/2016/10/08/centos-vi-chinese-garbled/
2016-10-08T05:06:13.000Z
2016-10-08T05:09:29.932Z
<p>centos 7.1 </p>
<p>cd /etc/<br>vi virc<br>在最后面增加如下字段:</p>
<pre><code>set fileencodings=utf-8,gb2312,gbk,gb18030
set termencoding=utf-8
set fileformats=unix
set encoding=prc
</code></pre><p>Over.</p>
<p>centos 7.1 </p>
<p>cd /etc/<br>vi virc<br>在最后面增加如下字段:</p>
<pre><code>set fileencodings=utf-8,gb2312,gbk,gb18030
set termencoding=utf-8
Life Record of My 撒欢
http://xpleeandroid.github.io/2016/08/31/MyGoldRetriever/
2016-08-31T05:42:32.000Z
2016-11-07T16:39:24.484Z
<p><strong>2016.08.31</strong><br>大清早的,随地大小便了。<br><img src="https://xpleeandroid.github.io/img/IMG20160831084548.jpg" alt=""><br><a id="more"></a><br>你身后是啥,不要瞪着你无辜的小眼睛看着我!<br>早上下楼听到他在家里叫唤了<br>上班路遇大撒欢三个月的金毛狗狗,三个月后撒欢长啥样?<br><img src="https://xpleeandroid.github.io/img/IMG_20160831_092113557.jpg" alt=""></p>
<h2 id="2016-08"><a href="#2016-08" class="headerlink" title="2016 08"></a>2016 08</h2><p>16年8月14日把这货带回家。<br>8.18 </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16081801.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16081802.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16081803.jpg" alt=""> </p>
<p>8.19 </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16081901.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16081902.jpg" alt=""> </p>
<p>8.20<br><img src="https://xpleeandroid.github.io/img/sahuan/16082001.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16082002.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16082003.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16082004.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16082005.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16082006.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16082007.jpg" alt=""> </p>
<p>8.22<br><img src="https://xpleeandroid.github.io/img/sahuan/16082201.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16082202.jpg" alt=""> </p>
<h2 id="2016-09"><a href="#2016-09" class="headerlink" title="2016 09"></a>2016 09</h2><p>9.4<br><img src="https://xpleeandroid.github.io/img/sahuan/16090401.jpg" alt=""><br>9.6<br><img src="https://xpleeandroid.github.io/img/sahuan/16090601.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16090602.jpg" alt=""><br>9.15<br><img src="https://xpleeandroid.github.io/img/sahuan/16091501.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16091502.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16091503.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16091504.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16091505.jpg" alt=""><br>9.22<br><img src="https://xpleeandroid.github.io/img/sahuan/16092200.jpg" alt=""><br>9.23<br><img src="https://xpleeandroid.github.io/img/sahuan/16092301.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16092302.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16092303.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16092304.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16092305.jpg" alt=""><br>9.24<br><img src="https://xpleeandroid.github.io/img/sahuan/16092401.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16092402.jpg" alt=""><br>9.26<br><img src="https://xpleeandroid.github.io/img/sahuan/16092601.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16092602.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16092603.jpg" alt=""> </p>
<h2 id="2016-10"><a href="#2016-10" class="headerlink" title="2016 10"></a>2016 10</h2><p>10.5<br><img src="https://xpleeandroid.github.io/img/sahuan/16100501.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100502.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100503.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100504.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100505.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100506.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100507.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100508.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100509.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16100510.jpg" alt=""> </p>
<p>10.11 </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101101.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101102.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101103.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101104.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101105.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101106.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101107.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101108.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101109.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101110.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101111.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101112.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101113.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101114.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101115.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101116.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101117.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101118.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101119.jpg" alt=""> </p>
<p>10.13 </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101301.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101302.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101303.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101304.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101305.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101306.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101307.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101308.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101309.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101310.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16101311.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16101312.jpg" alt=""> </p>
<h2 id="2016-11"><a href="#2016-11" class="headerlink" title="2016 11"></a>2016 11</h2><p>11.5<br><img src="https://xpleeandroid.github.io/img/sahuan/16110501.jpg" alt=""><br><img src="https://xpleeandroid.github.io/img/sahuan/16110502.jpg" alt=""> </p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/16110503.jpg" alt=""> </p>
<p>11.8 0:33</p>
<p><img src="https://xpleeandroid.github.io/img/sahuan/20161108_003359.jpg" alt=""> 敲完代码,准备睡觉,这家伙一直躺在我身边,时不时的舔舔我的脚丫子。</p>
<p><strong>2016.08.31</strong><br>大清早的,随地大小便了。<br><img src="https://xpleeandroid.github.io/img/IMG20160831084548.jpg" alt=""><br>
SS用户说明
http://xpleeandroid.github.io/2016/08/12/ss-user-guide/
2016-08-12T06:54:55.000Z
2016-10-08T06:48:32.134Z
<h1 id="ShadowSocks使用说明"><a href="#ShadowSocks使用说明" class="headerlink" title="ShadowSocks使用说明"></a>ShadowSocks使用说明</h1><p>shadowsocks是一款开源的基于UDP转发的开源的科学上网工具</p>
<h2 id="客户端下载与配置"><a href="#客户端下载与配置" class="headerlink" title="客户端下载与配置"></a>客户端下载与配置</h2><p>下载地址: <a href="http://download.lixiaopeng.top" target="_blank" rel="external">http://download.lixiaopeng.top</a><br>提供了Windows,Mac OS X ,Android,IOS的客户端<br>以下显示Windows客户端的配置方法 </p>
<h3 id="1-下载Windows客户端"><a href="#1-下载Windows客户端" class="headerlink" title="1.下载Windows客户端"></a>1.下载Windows客户端</h3><p>下载地址 <a href="http://download.lixiaopeng.top/" target="_blank" rel="external">http://download.lixiaopeng.top/</a> </p>
<h3 id="2-登录”用户中心”并获取配置信息"><a href="#2-登录”用户中心”并获取配置信息" class="headerlink" title="2.登录”用户中心”并获取配置信息"></a>2.登录”用户中心”并获取配置信息</h3><p>地址 :<a href="http://ss.lixiaopeng.top" target="_blank" rel="external">http://ss.lixiaopeng.top</a><br><img src="https://xpleeandroid.github.io/img/ss-1.png" alt=""><br><img src="https://xpleeandroid.github.io/img/ss-2.png" alt=""> </p>
<p>“server”:”xx.xxx.xxx.xx”, 服务器IP<br>“server_port”:xxx, 服务器端口<br>“local_port”:1080, 本地端口<br>“password”:”xxxx”, 密码<br>“timeout”:600, 这个不用管<br>“method”:”rc4-md5” 加密方式选择一样 </p>
<h3 id="3-双击开客户端软件并配置服务器【一般配置图片里的前4项保存即可】"><a href="#3-双击开客户端软件并配置服务器【一般配置图片里的前4项保存即可】" class="headerlink" title="3. 双击开客户端软件并配置服务器【一般配置图片里的前4项保存即可】"></a>3. 双击开客户端软件并配置服务器【一般配置图片里的前4项保存即可】</h3><p><img src="https://xpleeandroid.github.io/img/ss-3.png" alt=""> </p>
<h3 id="4-右击客户端如下图设置代理模式并启用代理"><a href="#4-右击客户端如下图设置代理模式并启用代理" class="headerlink" title="4. 右击客户端如下图设置代理模式并启用代理"></a>4. 右击客户端如下图设置代理模式并启用代理</h3><p><img src="https://xpleeandroid.github.io/img/ss-4.png" alt=""> </p>
<h3 id="此时即可用浏览器上youtube推特等国外网站"><a href="#此时即可用浏览器上youtube推特等国外网站" class="headerlink" title="此时即可用浏览器上youtube推特等国外网站"></a>此时即可用浏览器上youtube推特等国外网站</h3>
<h1 id="ShadowSocks使用说明"><a href="#ShadowSocks使用说明" class="headerlink" title="ShadowSocks使用说明"></a>ShadowSocks使用说明</h1><p>shadowsocks是一款开源的基
linux日常命令
http://xpleeandroid.github.io/2016/08/10/daily-linux-command/
2016-08-10T03:30:06.000Z
2016-10-22T06:34:24.637Z
<ul>
<li>ps -aux | grep servers.py 查看servers.py后台进程 -aux 显示所有状态</li>
<li>ps -ef | grep servers.py -e:显示所有进程,环境变量;-f:全格式 -h 不显示标题 </li>
<li>kill -9 pid 强制杀死进程pid</li>
<li>service iptabes stop 停止防火墙 centos7之前版本</li>
<li>chkconfig iptables off 禁用防火墙 centos7之前版本</li>
<li>systemctl stop firewalld.service 停止防火墙 centos7</li>
<li>systemctl disable firewalld.service 禁用防火墙 centos7</li>
<li>chmod -R 777 shadowsocks-rm</li>
<li>mv ss-panel/{.,}* .; rmdir ss-panel 移动ss-panel文件夹下的内容到上级目录,并且删除ss-panel目录</li>
<li>复制目录下所有到另一目录 cp -r phpmyadmin/. public/phpmyadmin/</li>
<li>df -h 查看磁盘各个分区的大小 使用情况</li>
<li>du -sh yuedu 查看yuedu目录大小</li>
</ul>
<ul>
<li>ps -aux | grep servers.py 查看servers.py后台进程 -aux 显示所有状态</li>
<li>ps -ef | grep servers.py -e:显示所有进程,环境变量;-f:全格式 -h 不显示标题 </li>
<li>k
安卓中使用ThreadPoolExcutor
http://xpleeandroid.github.io/2016/07/29/using-threadpoolexcuter-in-android/
2016-07-29T02:14:02.000Z
2016-07-29T08:42:00.042Z
<blockquote>
<ul>
<li>原文链接 <a href="https://medium.freecodecamp.com/threadpoolexecutor-in-android-8e9d22330ee3#.hiw1y4s2e" target="_blank" rel="external">https://medium.freecodecamp.com/threadpoolexecutor-in-android-8e9d22330ee3#.hiw1y4s2e</a></li>
<li>翻译: <a href="https://github.com/adamin1990" target="_blank" rel="external">Adamin90</a></li>
<li>转载请注明出处,谢谢!</li>
</ul>
</blockquote>
<p><img src="/img/using_threadpoolexcutor.png" alt=""></p>
<p>这篇文章将涉及到线程池,线程池执行程序,和他们在Android中的使用。<br>我们将使用很多的利用,详细的(thoroughly)介绍这些主题。<br><a id="more"></a></p>
<h1 id="Thread-Pools-线程池"><a href="#Thread-Pools-线程池" class="headerlink" title="Thread Pools (线程池)"></a>Thread Pools (线程池)</h1><p>一个线程池管理一池的工作线程(准确的数量依赖于它的实现方式)。<br>一个task队列等待池中的空闲线程执行队列中的task.Task被生产者加入队列中,工作线程作为消费者,只要池中有空闲线程在等待新的后台任务,就会从task队列中消费任务。</p>
<h1 id="ThreadPoolExcutor"><a href="#ThreadPoolExcutor" class="headerlink" title="ThreadPoolExcutor"></a>ThreadPoolExcutor</h1><p>ThreadPoolExcutor 从线程池中的一个线程执行一个给定的task。</p>
<pre><code>ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue
);
</code></pre><p>参数解释:</p>
<ol>
<li><strong>corePoolSize:</strong> 线程池中保留线程的最小数目,最开始线程池中没有线程,但是随着task被加入队列,新线程被创建。如果有空闲的线程,但是线程的数目小于corePoolSize,就会创建新的线程。</li>
<li><strong>maximumPoolSize:</strong> 线程池中线程的最大值,如果线程数量超过corePoolSize,线程数量>=corePoolSize,那么只有队列满的时候才会创建新的工作线程。</li>
<li><strong>keepAliveTime:</strong> 当线程数量超过corepoolsize,非corepoolsize的空闲线程将等待一个新的task,如果在这个定义的时间参数内没有等到新的task,该线程将被终止。</li>
<li><strong>unit:</strong> <strong>keppAliveTime</strong>的时间单位</li>
<li><strong>workQueue:</strong> task队列,持有runnable task,必须是一个<a href="https://developer.android.com/reference/java/util/concurrent/BlockingQueue.html" target="_blank" rel="external">BlockingQueue</a>.</li>
</ol>
<h1 id="为什么在Android和JAVA应用程序中使用Thread-Pool-Executor"><a href="#为什么在Android和JAVA应用程序中使用Thread-Pool-Executor" class="headerlink" title="为什么在Android和JAVA应用程序中使用Thread Pool Executor?"></a>为什么在Android和JAVA应用程序中使用Thread Pool Executor?</h1><ol>
<li>它是一个强大的任务执行框架,支持任务添加到队列,任务取消,任务优先级。</li>
<li>降低了线程创建的开销,它在线程池内管理一定数量的线程。</li>
</ol>
<h1 id="在Android中使用ThreadPoolExcutor"><a href="#在Android中使用ThreadPoolExcutor" class="headerlink" title="在Android中使用ThreadPoolExcutor"></a>在Android中使用ThreadPoolExcutor</h1><p>首先,创建一个PriorityThreadFactory:</p>
<pre><code>import android.os.Process;
import java.util.concurrent.ThreadFactory;
/**
* Created by Adam on 2016/7/29.
*/
public class PriorityThreadFactory implements ThreadFactory {
private final int mThreadPrority;
public PriorityThreadFactory(int mThreadPrority) {
this.mThreadPrority = mThreadPrority;
}
@Override
public Thread newThread(final Runnable r) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
Process.setThreadPriority(mThreadPrority);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
r.run();
;
}
};
return new Thread(runnable);
}
}
</code></pre><p>创建一个MainThreadExecutor:</p>
<pre><code>import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;
/**
* Created by Adam on 2016/7/29.
*/
public class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable command) {
handler.post(command);
}
}
</code></pre><p>创建一个DefaultExecutorSupplier:</p>
<pre><code>import android.os.Process;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Created by Adam on 2016/7/29.
*/
public class DefaultExecutorSupplier {
/*
*指定线程数量
*/
public static final int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
/**
* 后台任务的线程池
*/
private final ThreadPoolExecutor mForBackgroundTasks;
/**
* 轻量后台任务的线程池
*/
private final ThreadPoolExecutor mForLightWeightBackgroundTasks;
/**
* 主线程任务的线程池executor
*/
private final Executor mMainThreadExcutor;
private static DefaultExecutorSupplier mInstance;
/**
* 返回DefaultExecutorSupplier的实例
*/
public static DefaultExecutorSupplier getInstance() {
if (mInstance == null) {
synchronized (DefaultExecutorSupplier.class) {
mInstance = new DefaultExecutorSupplier();
}
}
return mInstance;
}
private DefaultExecutorSupplier() {
ThreadFactory backgroundPriorityThreadFactory = new PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND);
mForBackgroundTasks = new ThreadPoolExecutor(
NUMBER_OF_CORES * 2,
NUMBER_OF_CORES * 2,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
backgroundPriorityThreadFactory
);
mForLightWeightBackgroundTasks = new ThreadPoolExecutor(
NUMBER_OF_CORES * 2,
NUMBER_OF_CORES * 2,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
backgroundPriorityThreadFactory
);
mMainThreadExcutor = new MainThreadExecutor();
}
/*
* returns the thread pool executor for background task
*/
public ThreadPoolExecutor forBackgroundTasks() {
return mForBackgroundTasks;
}
/*
* returns the thread pool executor for light weight background task
*/
public ThreadPoolExecutor forLightWeightBackgroundTasks() {
return mForLightWeightBackgroundTasks;
}
/*
* returns the thread pool executor for main thread task
*/
public Executor forMainThreadTasks() {
return mMainThreadExcutor;
}
}
</code></pre><p><strong>注意:不同线程池的数量依赖于你的需求</strong></p>
<h1 id="现在在你的代码中这样使用"><a href="#现在在你的代码中这样使用" class="headerlink" title="现在在你的代码中这样使用"></a>现在在你的代码中这样使用</h1><pre><code> /*
* 后台任务
*/
public void doSomeBackgroundWork() {
DefaultExecutorSupplier.getInstance().forBackgroundTasks()
.execute(new Runnable() {
@Override
public void run() {
// 在这里后台工作.
}
});
}
/*
* 轻量后台任务
*/
public void doSomeLightWeightBackgroundWork() {
DefaultExecutorSupplier.getInstance().forLightWeightBackgroundTasks()
.execute(new Runnable() {
@Override
public void run() {
// 在这里做一些轻量后台工作.
}
});
}
/*
* 主线程任务
*/
public void doSomeMainThreadWork() {
DefaultExecutorSupplier.getInstance().forMainThreadTasks()
.execute(new Runnable() {
@Override
public void run() {
// 做一些中线程工作.
}
});
}
</code></pre><p>这样,我们可以为网络任务,I/O任务,重型的后台任务和其他任务创建不同的线程池。</p>
<h1 id="怎样取消一个task?"><a href="#怎样取消一个task?" class="headerlink" title="怎样取消一个task?"></a>怎样取消一个task?</h1><p>为了取消一个task,你必须得到task的<strong>future</strong>。所以,不要使用<strong>execute</strong>,使用<strong>submit</strong>,将返回一个future。现在future就可以用来取消task了。</p>
<pre><code>Future future= DefaultExecutorSupplier.getInstance().forBackgroundTasks()
.submit(new Runnable() {
@Override
public void run() {
}
});
future.cancel(true);
</code></pre><h1 id="如何设置task的优先级?"><a href="#如何设置task的优先级?" class="headerlink" title="如何设置task的优先级?"></a>如何设置task的优先级?</h1><p>假设队列里有20个任务,线程池持有4个线程,我们根据task的优先级处理他们,因为线程池此时同时可处理4个线程。</p>
<p>但是假设我们需要我们最后推进队列的任务最先执行,我们需要为该任务设置<strong>立即</strong>的优先当线程从队列里拿取新任务时。</p>
<p>为了设置任务的优先级,我们需要创建一个线程池executor。</p>
<p>为优先级创建一个枚举类:</p>
<pre><code>/**
* Created by Adam on 2016/7/29.
*/
public enum Priority {
/**
* 注意:不要在任何情况下改变顺序,否则会使排序不准确
*/
/**
* 最低优先级,预加载数据用
*/
LOW,
/**
* 中优先级
*/
MEDIUM,
/**
* 高优先级
*/
HIGH,
/**
* 立即
*/
IMMEDIATE,
}
</code></pre><h2 id="创建一个PriorityRunnable"><a href="#创建一个PriorityRunnable" class="headerlink" title="创建一个PriorityRunnable"></a>创建一个PriorityRunnable</h2><pre><code>public class PriorityRunnable implements Runnable {
private final Priority priority;
public PriorityRunnable(Priority priority) {
this.priority = priority;
}
@Override
public void run() {
}
public Priority getPriority(){
return priority;
}
}
</code></pre><p>创建一个PriorityThreadPoolExecutor,继承自ThreadPoolExecutor.我们必须创建PriorityFutureTask,将实现Comparable<priorityfuturetask>接口。</priorityfuturetask></p>
<pre><code>import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Created by Adam on 2016/7/29.
*/
public class PriorityThreadPoolExecutor extends ThreadPoolExecutor {
public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new PriorityBlockingQueue<Runnable>(), threadFactory);
}
@Override
public Future<?> submit(Runnable task) {
PriorityFutureTask futureTask = new PriorityFutureTask((PriorityRunnable) task);
execute(futureTask);
return futureTask;
}
private static final class PriorityFutureTask extends FutureTask<PriorityRunnable>
implements Comparable<PriorityFutureTask> {
private final PriorityRunnable priorityRunnable;
public PriorityFutureTask(PriorityRunnable priorityRunnable) {
super(priorityRunnable, null);
this.priorityRunnable = priorityRunnable;
}
@Override
public int compareTo(PriorityFutureTask another) {
Priority p1 = priorityRunnable.getPriority();
Priority p2 = another.priorityRunnable.getPriority();
return p2.ordinal() - p1.ordinal();
}
}
}
</code></pre><p>首先在DefaultExcutorSupplier,用PriorityThreadPoolExecutor代替ThreadPoolExecutor.</p>
<pre><code> ThreadFactory backgroundPriorityThreadFactory = new PriorityThreadFactory(Process.THREAD_PRIORITY_BACKGROUND);
// mForBackgroundTasks = new ThreadPoolExecutor(
// NUMBER_OF_CORES * 2,
// NUMBER_OF_CORES * 2,
// 60L,
// TimeUnit.SECONDS,
// new LinkedBlockingQueue<Runnable>(),
// backgroundPriorityThreadFactory
//
// );
mForBackgroundTasks=new PriorityThreadPoolExecutor(
NUMBER_OF_CORES * 2,
NUMBER_OF_CORES * 2,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
backgroundPriorityThreadFactory
);
</code></pre><p>下面的例子演示了如何设置高优先级:</p>
<pre><code> public void doSomeTaskAtHighPriority(){
DefaultExecutorSupplier.getInstance().forBackgroundTasks()
.submit(new PriorityRunnable(Priority.HIGH){
@Override
public void run() {
super.run();
}
});
}
</code></pre>
<blockquote>
<ul>
<li>原文链接 <a href="https://medium.freecodecamp.com/threadpoolexecutor-in-android-8e9d22330ee3#.hiw1y4s2e">https://medium.freecodecamp.com/threadpoolexecutor-in-android-8e9d22330ee3#.hiw1y4s2e</a></li>
<li>翻译: <a href="https://github.com/adamin1990">Adamin90</a></li>
<li>转载请注明出处,谢谢!</li>
</ul>
</blockquote>
<p><img src="/img/using_threadpoolexcutor.png" alt=""></p>
<p>这篇文章将涉及到线程池,线程池执行程序,和他们在Android中的使用。<br>我们将使用很多的利用,详细的(thoroughly)介绍这些主题。<br>
安卓计算下载速度
http://xpleeandroid.github.io/2016/07/28/android-calculate-download-speed/
2016-07-28T03:23:13.000Z
2016-07-28T03:41:16.658Z
<p>昨天开始封装一个安卓多线程下载器,在写的过程中,猜测想加入检测下载过程中的速度,于是google一番,得出一个比较靠谱的答案,在此总结一下。<br><a id="more"></a></p>
<h1 id="NANOSECONDS"><a href="#NANOSECONDS" class="headerlink" title="NANOSECONDS"></a>NANOSECONDS</h1><p><strong>NANOSECONDS</strong>,毫微秒,十亿分之一秒,1s=1000000000毫微秒。</p>
<h1 id="CODE-EXAMPLE"><a href="#CODE-EXAMPLE" class="headerlink" title="CODE EXAMPLE"></a>CODE EXAMPLE</h1><pre><code> long start = System.nanoTime(); //开始时间
long totalRead = 0; //总共下载了多少
final double NANOS_PER_SECOND = 1000000000.0; //1秒=10亿nanoseconds
final double BYTES_PER_MIB = 1024 * 1024; //1M=1024*1024byte
while (((len = is.read(buffler, 0, 1024)) >0)) {
totalRead += len;
double speed = NANOS_PER_SECOND / BYTES_PER_MIB * totalRead / (System.nanoTime() - start + 1);
}
</code></pre><h1 id="WARNING"><a href="#WARNING" class="headerlink" title="WARNING"></a>WARNING</h1><p>这种方法计算的是从start开始时间的平均速度,不是实时速度。</p>
<p>昨天开始封装一个安卓多线程下载器,在写的过程中,猜测想加入检测下载过程中的速度,于是google一番,得出一个比较靠谱的答案,在此总结一下。<br>
Android拍照上传至PHP服务器并写入MySql数据库(下)
http://xpleeandroid.github.io/2016/07/22/android-upload-img-to-php-server-2/
2016-07-22T07:45:32.000Z
2016-07-22T08:02:25.418Z
<h1 id="Android实现"><a href="#Android实现" class="headerlink" title="Android实现"></a>Android实现</h1><p>调用系统相机,拍照:</p>
<pre><code> Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
getFileUri();
intent.putExtra(MediaStore.EXTRA_OUTPUT, file_uri);
startActivityForResult(intent, CODE_CAMERA);
private void getFileUri() {
image_name = Calendar.getInstance().getTimeInMillis() + ".jpg";
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + image_name);
file_uri = Uri.fromFile(file);
}
</code></pre><a id="more"></a>
<p>在onActivityResult里面接收图片并Base64处理:</p>
<pre><code> @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CODE_CAMERA && resultCode == RESULT_OK) {
new EncodeImage().execute(); //把bitmap转换成base64字符串
}
}
</code></pre><p>EncodeImage是一个AsyncTask,doInBackground里面从uri里面获取bitmap,然后转入输出流,最终转换为base64编码字符串:</p>
<pre><code>@Override
protected Void doInBackground(Void... voids) {
bitmap = BitmapFactory.decodeFile(file_uri.getPath());
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
byte[] array = stream.toByteArray();
encoded_string = Base64.encodeToString(array, 0);
bitmap.recycle(); //防止oom
return null;
}
</code></pre><p>然后就可以上传到服务器了:</p>
<pre><code> private void uploadImage() {
HashMap<String, String> map = new HashMap<>();
map.put("encoding_string", encoded_string);
map.put("image_name", image_name);
OkHttpUtils.post()
.url("http:192.168.0.112/phpdemo/uploadimage.php")
.params(map)
.tag(this)
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e, int id) {
Log.e("出错了", "错误信息:" + e.getMessage());
}
@Override
public void onResponse(String response, int id) {
Log.e("成功or失败", "信息:" + response);
}
});
}
</code></pre><p>在上传服务器过程中,遇到两个问题,第一,提示<code>POST Content-Length of ... bytes exceeds the limit of 8388608 bytes</code>,这个错误是因为php默认最大post上传8M,更改php.ini里面的<code>post_max_size=1000M</code>就ok了;第二,当第二次拍照的时候会出现OOM的情况,检查代码发现bitmap没有recycle。</p>
<p>OVER</p>
<h1 id="Android实现"><a href="#Android实现" class="headerlink" title="Android实现"></a>Android实现</h1><p>调用系统相机,拍照:</p>
<pre><code> Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
getFileUri();
intent.putExtra(MediaStore.EXTRA_OUTPUT, file_uri);
startActivityForResult(intent, CODE_CAMERA);
private void getFileUri() {
image_name = Calendar.getInstance().getTimeInMillis() + ".jpg";
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + image_name);
file_uri = Uri.fromFile(file);
}
</code></pre>
Android拍照上传至PHP服务器并写入MySql数据库(上)
http://xpleeandroid.github.io/2016/07/21/android-upload-img-to-php-server-1/
2016-07-21T08:45:00.000Z
2016-07-22T07:47:25.904Z
<h1 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h1><p>需求很简单,Android客户端点击拍照后,进行Base64加密,自动上传至服务器,服务器接收上传的数据并解密后保存到指定文件夹下,并将图片信心写入数据库,并返回相应的Json数据。</p>
<a id="more"></a>
<h1 id="数据库"><a href="#数据库" class="headerlink" title="数据库"></a>数据库</h1><h2 id="创建数据库"><a href="#创建数据库" class="headerlink" title="创建数据库"></a>创建数据库</h2><p>数据库名称为 turtorial_upload_image:</p>
<pre><code>CREATE DATABASE tutorial_upload_image;
</code></pre><h2 id="创建表"><a href="#创建表" class="headerlink" title="创建表"></a>创建表</h2><p>我们要保存的信息是图片的名称和图片的路径,表名称是photos:</p>
<pre><code>CREATE TABLE photos(
id INT(32) NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
path VARCHAR(30) NOT NULL,
PRIMARY KEY(id)
);
</code></pre><h1 id="PHP"><a href="#PHP" class="headerlink" title="PHP"></a>PHP</h1><p>先上代码:</p>
<pre><code><?php
/**
* Created by PhpStorm.
* User: Adam
* Date: 2016/7/21
* Time: 15:01
*/
header('Content-type : bitmap; charset=utf-8;');
$dbms = 'mysql'; //数据库类型
$host = 'localhost'; //数据库主机名
$dbName = 'tutorial_upload_image'; //使用的数据库
$user = 'root'; //数据库连接用户名
$pass = ''; //对应的密码
$dsn = "$dbms:host=$host;dbname=$dbName";
if (isset($_POST["encoding_string"])) {
$encoding_string = $_POST["encoding_string"];
$image_name = $_POST["image_name"];
//decode 客户端上传的base64数据
$decoded_string = base64_decode($encoding_string);
$path = "images/" . $image_name; //定义存放路径
$file = fopen($path, "wb");
$is_written = fwrite($file, $decoded_string);
fclose($file);
//写入数据库
if ($is_written > 0) {
//sql语句
$strSql = "insert into photos(name,path) values('$image_name','$path')";
//方法一 pdo方式 支持多种数据库
try {
$dbh = new PDO($dsn, $user, $pass); //初始化一个PDO对象
$temp = $dbh->prepare($strSql);
$temp->execute();
$array = array(
"status" => true,
"msg" => "插入数据成功"
);
echo json_encode($array);
$dbh = null; //运行完成后关闭链接
} catch (PDOException $e) {
$array = array(
"status" => false,
"msg" => "插入数据失败" . ($e->getMessage())
);
echo json_encode($array);
}
//方法2 mysqli方式
// $connection=mysqli_connect('localhost','root','','tutorial_upload_image');
// $result=mysqli_query($connection,$strSql);
// if($result){
// $array = array (
// "status" => true,
// "msg" => "插入数据成功"
// );
// echo json_encode($array);
// }else{
// $array = array (
// "status" => false,
// "msg" => "插入数据失败"
// );
// echo json_encode($array);
// }
// mysqli_close($connection); //关闭连接
}
}
?>
</code></pre><p>这里我列举了两种连接数据库的方式 PDO和mysqli ,mysql方式官方已经不推荐使用了,所以就不再列举(我也没用过)。数据库连接过程首先是读取POST过来的内容,然后写到images目录下面,再把地址和名称写入数据库里,返回相应的JSON数据,在这里每次上传完毕后都关闭了连接。</p>
<h1 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h1><p>测试阶段我们找用postman进行模拟发送数据,首先在<a href="http://www.motobit.com/util/base64-decoder-encoder.asp" target="_blank" rel="external">这个网站</a>Base64 encode一张图片,复制之后,拷贝到postman里面,postman数据如下:</p>
<p><img src="/img/android_upload_img_to_php_1.png" alt=""></p>
<p>测试结果成功~</p>
<p>下节我们将开发安卓客户端。</p>
<h1 id="需求分析"><a href="#需求分析" class="headerlink" title="需求分析"></a>需求分析</h1><p>需求很简单,Android客户端点击拍照后,进行Base64加密,自动上传至服务器,服务器接收上传的数据并解密后保存到指定文件夹下,并将图片信心写入数据库,并返回相应的Json数据。</p>
anonymous
http://xpleeandroid.github.io/2016/07/20/newsapi/
2016-07-20T08:12:35.000Z
2016-07-20T08:16:24.973Z
<h1 id="register-host-club-qingdaonews-com"><a href="#register-host-club-qingdaonews-com" class="headerlink" title="register(host club.qingdaonews.com)"></a>register(host club.qingdaonews.com)</h1><a id="more"></a>
<hr>
<ul>
<li>step1 /user/touch_reg.php param: act=regstep1&reg_un=adamin90&reg_pw=wsxqaz123&con_pw=wsxqaz123&tel=15725266012 error response :{“result”:”error”,”type”:”tel”,”info”:”\u6b64\u624b\u673a\u53f7\u5df2\u7ecf\u6ce8\u518c(\u9ad8)”} success response :{“result”:”success”,”type”:”code”,”info”:”\u53d1\u9001\u6210\u529f”}</li>
</ul>
<h1 id="login-host-app-qingdaonews-com"><a href="#login-host-app-qingdaonews-com" class="headerlink" title="login (host app.qingdaonews.com)"></a>login (host app.qingdaonews.com)</h1><ul>
<li>/shoujikehuduan/interface_login.php?username=15725266012&password=wsxqaz success response :{“result”:”success”,”point”:”200”,”uid”:”8087267”,”phone”:”15725266012”,”first”:0,”token”:”52165771559e88f430573c6cd0925e68”,”money”:”0”,”face”:”http:\/\/pic.qingdaonews.com\/f\/avatar_big.jpg”,”type”:”passport”,”username”:”15725266012”,”loginname”:”15725266012”,”password”:”wsxqaz”} error response :{“result”:”error”,”point”:null,”uid”:””,”phone”:null,”first”:0,”face”:”http:\/\/pic.qingdaonews.com\/f\/avatar_big.jpg”,”type”:”passport”,”username”:”15725266019”,”loginname”:”15725266019”,”password”:”123456”}</li>
</ul>
<h1 id="签到-post-app-qingdaonews-com"><a href="#签到-post-app-qingdaonews-com" class="headerlink" title="签到 post app.qingdaonews.com"></a>签到 post app.qingdaonews.com</h1><p>/shoujikehuduan/interface_missionstate.php?token=52165771559e88f430573c6cd0925e68&mission=mis_10</p>
<h1 id="头条"><a href="#头条" class="headerlink" title="头条"></a>头条</h1><p>/shoujikehuduan/mdi_newslist300.php?v=2.0&num=20&type=bd</p>
<p>/shoujikehuduan/mdi_newslist300.php?v=2.0&num=20&type=bd&minid=463459</p>
<h1 id="青青岛"><a href="#青青岛" class="headerlink" title="青青岛"></a>青青岛</h1><p>/imobile/index.php?page=1&title=%E5%A4%B4%E6%9D%A1&type=newsapp</p>
<h1 id="焦点"><a href="#焦点" class="headerlink" title="焦点"></a>焦点</h1><p>/shoujikehuduan/mdi_newslist300.php?v=2.0&num=20&type=jdxw</p>
<p>/shoujikehuduan/mdi_newslist300.php?v=2.0&num=20&type=jdxw&minid=462981</p>
<h1 id="体育"><a href="#体育" class="headerlink" title="体育"></a>体育</h1><p>/shoujikehuduan/mdi_newslist300.php?v=2.0&num=20&type=ty</p>
<h1 id="文娱"><a href="#文娱" class="headerlink" title="文娱"></a>文娱</h1><p>yl</p>
<h1 id="房产"><a href="#房产" class="headerlink" title="房产"></a>房产</h1><p>qdfc</p>
<h1 id="汽车"><a href="#汽车" class="headerlink" title="汽车"></a>汽车</h1><p>qdqc</p>
<h1 id="旅游"><a href="#旅游" class="headerlink" title="旅游"></a>旅游</h1><p>qdly</p>
<h1 id="家居"><a href="#家居" class="headerlink" title="家居"></a>家居</h1><p>qdjj</p>
<h1 id="财经"><a href="#财经" class="headerlink" title="财经"></a>财经</h1><p>cj</p>
<h1 id="教育"><a href="#教育" class="headerlink" title="教育"></a>教育</h1><p>jy</p>
<h1 id="健康"><a href="#健康" class="headerlink" title="健康"></a>健康</h1><p>jk</p>
<h1 id="消费"><a href="#消费" class="headerlink" title="消费"></a>消费</h1><p>xf</p>
<h1 id="舆情"><a href="#舆情" class="headerlink" title="舆情"></a>舆情</h1><p>yuqing</p>
<h1 id="婚假"><a href="#婚假" class="headerlink" title="婚假"></a>婚假</h1><p>hj</p>
<h1 id="民生"><a href="#民生" class="headerlink" title="民生"></a>民生</h1><p>msbl</p>
<h1 id="黄岛-huangdao"><a href="#黄岛-huangdao" class="headerlink" title="黄岛 huangdao"></a>黄岛 huangdao</h1>
<h1 id="register-host-club-qingdaonews-com"><a href="#register-host-club-qingdaonews-com" class="headerlink" title="register(host club.qingdaonews.com)"></a>register(host club.qingdaonews.com)</h1>
English Jokes(英文笑话)
http://xpleeandroid.github.io/2016/07/07/English-Jokes/
2016-07-07T06:43:44.000Z
2016-07-07T07:04:33.191Z
<h1 id="1-十个大兵与两个小偷的故事"><a href="#1-十个大兵与两个小偷的故事" class="headerlink" title="1. 十个大兵与两个小偷的故事"></a>1. 十个大兵与两个小偷的故事</h1><pre><code>Ten soldiers were setting up tents in the forest preparing for the night.
Later, two thieves arrived and attempted to rob them of their rations, but were caught.
The soldiers told them, "We would kill you, but we're in a good mood today.
We'll release you if you can make us all laugh." The thieves reluctantly agreed.
One begins to tell a humorous story.
After the story, nine of the soldiers are laughing hysterically.
However, one is merely looking at the thief with a blank stare.
Consequently, one soldier told the thief "Sorry, not all of us laughed," and killed him.
The other thief was nervous after seeing his friend killed, so he told a much less entertaining story.
No soldiers were laughing except for the one who didn't laugh previously, so they killed the second thief as well.
After killing the thieves, the soldiers asked their friend, "Why did you laugh during the second thief's story but not during the first's?
It was much funnier after all."
He responded, "When the second thief was speaking, I finally understood the first thief's story, and it was damn funny."
</code></pre><p>引用Zootopia(疯狂动物城)的一个场景,so hilarious!:</p>
<p><img src="http://img4.duitang.com/uploads/item/201607/07/20160707145046_hr5LB.thumb.500_500_g.gif" alt=""><br><a id="more"></a></p>
<h1 id="2-狮子和森林动物的故事(给乌龟跪了)"><a href="#2-狮子和森林动物的故事(给乌龟跪了)" class="headerlink" title="2. 狮子和森林动物的故事(给乌龟跪了)"></a>2. 狮子和森林动物的故事(给乌龟跪了)</h1><pre><code>One day a lion wakes up in a bad mood and summons the other animals in the jungle.
"I want each of you to tell a joke, but I warn you that if anyone of you fails to laugh, I'll kill the one who told it.
Let's see, monkey, you will be first."
Shaking with fear the monkey begins, "Two men are in the street and..."
When he finishes, everyone bursts out laughing save the tortoise.
"The tortoise didn't laugh!" roars the lion, pouncing on the monkey and ripping him to pieces.
Then he orders, "Elephant, you're next."
Cursing through clenched teeth, the elephant begins, "A drunk walks into a bar and..."
When he finishes, all the animals split their sides laughing except the tortoise, who remains impassive.
"The tortoise didn't think it was funny!" exclaimed the lion who, seeing that the furious elephant is about to step on the tortoise, kills the elephant with his claws.
By now, everyone wants to murder the tortoise, but nobody dares move.
"Now it's your turn, tiger," orders the lion.
The scared tiger begins, "They say that Little Red Riding Hood..."
At that moment, the tortoise falls over laughing. "What's with you?" bellows the lion.
"Tiger hasn't finished yet..."
To which the tortoise replies, "The monkey's joke is hilarious!"
</code></pre><h1 id="3-王后跟三个犯人的故事(the-queen-will-get-watermelon-shoved-up-the-third-prisoner’s-ass-hahaha-)"><a href="#3-王后跟三个犯人的故事(the-queen-will-get-watermelon-shoved-up-the-third-prisoner’s-ass-hahaha-)" class="headerlink" title="3. 王后跟三个犯人的故事(the queen will get watermelon shoved up the third prisoner’s ass? hahaha!)"></a>3. 王后跟三个犯人的故事(the queen will get watermelon shoved up the third prisoner’s ass? hahaha!)</h1><pre><code>Three prisoners on death row are summoned by the queen for a chance to be free.
The queen tells the prisoners they have one day to go into the jungle and bring her a fruit.
If she likes it, they are free to go.
However, if she doesn't like it, the fruit of their will be shoved up their ass, and then killed they will be back on death row.
The first one comes back with grapes.
The queen does not like the grapes and while the grapes were being shoved up his ass, the prisoner was crying.
The second prisoner returns with an apple.
Again, the queen does not like the apple and the apple gets shoved up the second prisoner's ass.
However, the first prisoner noticed that he was laughing while the apple was being inserted.
When asked why he was crying, the second prisoner said "I saw the third prisoner coming back with a watermelon."
</code></pre>
<h1 id="1-十个大兵与两个小偷的故事"><a href="#1-十个大兵与两个小偷的故事" class="headerlink" title="1. 十个大兵与两个小偷的故事"></a>1. 十个大兵与两个小偷的故事</h1><pre><code>Ten soldiers were setting up tents in the forest preparing for the night.
Later, two thieves arrived and attempted to rob them of their rations, but were caught.
The soldiers told them, "We would kill you, but we're in a good mood today.
We'll release you if you can make us all laugh." The thieves reluctantly agreed.
One begins to tell a humorous story.
After the story, nine of the soldiers are laughing hysterically.
However, one is merely looking at the thief with a blank stare.
Consequently, one soldier told the thief "Sorry, not all of us laughed," and killed him.
The other thief was nervous after seeing his friend killed, so he told a much less entertaining story.
No soldiers were laughing except for the one who didn't laugh previously, so they killed the second thief as well.
After killing the thieves, the soldiers asked their friend, "Why did you laugh during the second thief's story but not during the first's?
It was much funnier after all."
He responded, "When the second thief was speaking, I finally understood the first thief's story, and it was damn funny."
</code></pre><p>引用Zootopia(疯狂动物城)的一个场景,so hilarious!:</p>
<p><img src="http://img4.duitang.com/uploads/item/201607/07/20160707145046_hr5LB.thumb.500_500_g.gif" alt=""><br>
PHP学习笔记
http://xpleeandroid.github.io/2016/07/07/Learn-PHP/
2016-07-07T03:33:29.000Z
2016-07-08T09:51:53.028Z
<h2 id="php文件操作的模式"><a href="#php文件操作的模式" class="headerlink" title="php文件操作的模式"></a>php文件操作的模式</h2><ul>
<li><strong>r</strong> 只读权限打开文件</li>
<li><strong>w</strong> 只写权限打开文件,擦除内容,如果没有则新建文件</li>
<li><strong>a</strong> 只写权限打开文件</li>
<li><strong>x</strong> 新建一个只写权限的文件</li>
<li><strong>r+</strong> 打开读/写权限文件</li>
<li><strong>w+</strong> 打开读/写权限的文件, 擦除内容,如果没有则新建文件</li>
<li><strong>a+</strong> 打开读/写权限文件,如果没有则新建文件;</li>
<li><strong>x+</strong> 新建一个读/写权限的文件</li>
</ul>
<h2 id="将表单提交到本身页面"><a href="#将表单提交到本身页面" class="headerlink" title="将表单提交到本身页面"></a>将表单提交到本身页面</h2><p>只需将form的action 设置为<code><?php echo $_SERVER['PHP_SELF'];?></code><br>为了防止跨站点攻击(XSS),我们通常需要使用<strong>htmlspecialchars()</strong><br>避免<strong>$_SERVER[“PHP_SELF”]</strong> 被利用。如下:</p>
<pre><code><form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
</code></pre><h2 id="正则匹配规则"><a href="#正则匹配规则" class="headerlink" title="正则匹配规则"></a>正则匹配规则</h2><ul>
<li><strong>[abc]</strong> 单独的字符串 :a,b或c</li>
<li><strong>[^abc]</strong> 任意的单独字符串单不是a,b,或c</li>
<li><strong>[a-z]</strong> a-z任意的单独字符串</li>
<li><strong>[a-zA-Z]</strong> a-z 或A-Z中任意的单独字符串</li>
<li><strong>^</strong> 匹配整行开头 (比如 <strong>^\d+</strong>匹配的是任意的数字开头的字符串)</li>
<li><strong>$</strong> 匹配整行结尾 (比如<strong>\d+$</strong>匹配任意以数字结尾的字符串)</li>
<li><strong>\A</strong> 匹配字符串输入的开头</li>
<li><strong>\z</strong> 匹配字符串输入的结尾</li>
<li><strong>.</strong> 任意单个字符串</li>
<li><strong>\s</strong> 任意空字符串</li>
<li><strong>\S</strong> 任意非空字符串</li>
<li><strong>\d</strong> 任意数字</li>
<li><strong>\D</strong> 任意非数字</li>
<li><strong>\w</strong> 任意任何单字符(数字,字母,下滑线)、</li>
<li><strong>\W</strong> 任意非字符</li>
<li><strong>\B</strong> 匹配任意链接字符串</li>
<li><strong>(…)</strong> 捕获封闭的内容 </li>
<li><strong>(a|b)</strong> 匹配a或b</li>
<li><strong>a?</strong> 0或1个a</li>
<li><strong>a*</strong> 0或多个a</li>
<li><strong>a+</strong> 1或多个a</li>
<li><strong>a{3}</strong> 三个a</li>
<li><strong>a{3,}</strong> 3个或更多a</li>
<li><strong>a{3,6}</strong> 3到6个a</li>
<li><strong>i</strong> 忽略大小写 <strong>m</strong> 匹配多行 <strong>x</strong> 忽略空白</li>
</ul>
<h2 id="php文件操作的模式"><a href="#php文件操作的模式" class="headerlink" title="php文件操作的模式"></a>php文件操作的模式</h2><ul>
<li><strong>r</strong> 只读权限打开文件</li>
java8教程-泛型(Generics)
http://xpleeandroid.github.io/2016/06/28/java8-Generics/
2016-06-28T06:04:35.000Z
2016-07-20T09:34:13.862Z
<blockquote>
<ul>
<li>原文链接 [<a href="https://docs.oracle.com/javase/tutorial/java/generics/index.html" target="_blank" rel="external">https://docs.oracle.com/javase/tutorial/java/generics/index.html</a>)</li>
<li>翻译: <a href="https://github.com/adamin1990" target="_blank" rel="external">Adamin90</a></li>
<li>转载请注明出处,谢谢!</li>
</ul>
</blockquote>
<h1 id="泛型(已更新)"><a href="#泛型(已更新)" class="headerlink" title="泛型(已更新)"></a>泛型(已更新)</h1><p> 在任何繁琐的(nontrivial)软件项目中,bug是家常便饭。细心的规划,编程和测试可以帮助减少bug的普遍性(pervasiveness),但是无论如何,无论在哪里,bug总会伺机悄悄溜进(creep)你的代码,因为很明显,新的特性会不断的被引入,并且你的代码基数会不断变大和复杂。</p>
<p> 幸运的是,一些bug相比其它比较容易检测。编译时bug可以在早期被检测到;你可以利用编译器的错误信息查明是什么问题并且解决,就在那时。然而,运行时bug会更加未预知,他们不会立即展示出来,不知道什么时候发生,可能根本不在程序真正出现问题的点上。</p>
<p>泛型通过更多的在编译时检测bug为你的代码增加了稳定性。<br><a id="more"></a></p>
<h1 id="为什么要用泛型"><a href="#为什么要用泛型" class="headerlink" title="为什么要用泛型"></a>为什么要用泛型</h1><p>简言之,泛型能够使<strong>类型</strong>(类和接口)在定义类,接口和方法的时候参数化。非常像方法定义时用到的<strong>形式参数</strong>(formal parameters),类型参数提供了一种你可以通过不同的输入来复用同一段代码的方法。不同点是,<strong>形式参数</strong>输入的是<strong>值</strong>,而类型参数输入的是<strong>类型</strong>。</p>
<p>使用泛型比非泛型有很多好处:</p>
<ul>
<li>编译时更强大的类型检测</li>
</ul>
<p> Java编译器对泛型应用了强大的类型检测,如果代码违反了类型安全就会报错。修复编译时错误比修复运行时错误更加容易,因为运行时错误很难查找到。</p>
<ul>
<li><p>消除类型转换(Elimination of casts)</p>
<p>以下代码片段没有泛型需要转型:</p>
<p> List list = new ArrayList();<br> list.add(“hello”);<br> String s = (String) list.get(0);<br>当我们重新用泛型编写,代码就不需要类型转换了:</p>
<p> List<string> list = new ArrayList<string>();<br> list.add(“hello”);<br> String s = list.get(0); // no cast</string></string></p>
</li>
<li><p>使开发者实现泛型算法</p>
</li>
</ul>
<p>通过泛型,开发者可以自己实现泛型算法,应用到一系列的不同类型,可以自定义,并且类型安全,易读。</p>
<h1 id="泛型类型"><a href="#泛型类型" class="headerlink" title="泛型类型"></a>泛型类型</h1><p><strong>泛型类型</strong>是泛型类或者接口被类型参数化。下面的<strong>Box</strong>类将被更改演示这个概念。</p>
<h3 id="简单的-Box-类"><a href="#简单的-Box-类" class="headerlink" title="简单的 Box 类"></a>简单的 Box 类</h3><p>列举一个简单的非泛型 <strong>Box</strong>操作任意类型的object。它只需要提供两个方法:set,添加一个obejct到box,get,获取这个对象:</p>
<pre><code>public class Box {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
</code></pre><p>因为它的方法接收或返回一个对象,你可以任意传入,只要传入的不是原始数据类型。我们没有在编译时辨别clas如何使用的。一边可能替换一个 Integer到box,另一边获取的不是Integer类型,而可能传入一个String类型,结果会导致运行时错误。</p>
<h3 id="泛型版本的Box"><a href="#泛型版本的Box" class="headerlink" title="泛型版本的Box"></a>泛型版本的Box</h3><p>泛型类的定义形式如下:</p>
<pre><code>class name<T1, T2, ..., Tn> { /* ... */ }
</code></pre><p>类型参数部分被一对尖括号(<>)划分,紧跟类名,它指定了<strong>类型参数</strong>(也叫作类型变量)T1, T2, ….,和Tn.</p>
<p>把原Box类更新为泛型类,你要通过把“public class Box”改变为“public class Box<t>”创建一个类型声明。这会引入一个<strong>类型变量</strong>, <strong>T</strong>,你可以在类中任意地方使用。通过这个改变,Box类就变为:</t></p>
<pre><code>/**
* Generic version of the Box class.
* @param <T> the type of the value being boxed
*/
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
</code></pre><p>你可以看到,所有<strong>Object</strong>出现的地方都被替换为T了。一个类型变量可以指定为任意非原始类型的类型:任意的类,任意的接口,任意的数组,甚至其他的类型变量。同样的技术可以应用到创建泛型接口上。</p>
<h3 id="类型参数命名规则(Naming-Conventions)"><a href="#类型参数命名规则(Naming-Conventions)" class="headerlink" title="类型参数命名规则(Naming Conventions)"></a>类型参数命名规则(Naming Conventions)</h3><p>通过规则,类型参数是单独的,大写字母。这个表示鲜明区别了你已知的变量命名规则,一个好的理由是:没有这个规则,你将很难区分类型变量和原生类或接口名的区别。</p>
<p>最普遍使用的类型参数是:</p>
<ul>
<li>E -Element(Java Collections框架大量使用)</li>
<li>K -Key</li>
<li>N -Number</li>
<li>T -Type</li>
<li>V -Value </li>
<li>S,U,V 等 -第二,第三,第四个类型</li>
</ul>
<p>你可以在JAVA SE API 看到这些名字的使用。</p>
<h3 id="调用和实例化一个泛型类型"><a href="#调用和实例化一个泛型类型" class="headerlink" title="调用和实例化一个泛型类型"></a>调用和实例化一个泛型类型</h3><p>要在你的代码引用泛型类 Box,你必须执行 泛型类型调用,把T替换成具体的值,比如Integer: </p>
<pre><code>Box<Integer> integerBox;
</code></pre><p>你可以认为泛型类型调用跟原生方法调用大致一样,但是不是传入一个参数到方法,而是传入一个类型蚕食–这个情况下的Integer–给Box类本身。</p>
<blockquote>
<p><strong>Type Parameter</strong>和<strong>Type Argument</strong>术语(Terminology):<br>很多开发者交换使用这个两个术语,但是这两个术语并不同。敲代码时,<br>type argument 创建一个参数化类型,因此,Foo< T>中的T是type parameter,Foo< String> f中的String是一个type argument。</p>
</blockquote>
<p>就想其他的变量定义,上面的代码不会真正创建一个新的 Box对象。它只是声明,integerBox将持有一个“Box of Integer”的引用,用以读取Box<integer>.泛型类型的调用通常称为参数化类型。</integer></p>
<p>为了实例化这个类,用new 关键字,把<integer>放在类名和括号之间。</integer></p>
<pre><code>Box<Integer> integerBox = new Box<Integer>();
</code></pre><h3 id="The-Diamond"><a href="#The-Diamond" class="headerlink" title="The Diamond"></a>The Diamond</h3><p>在Java SE 7及以后版本,可以省去类型参数调用泛型类的构造函数,用一个空的类型参数(<>),编译器可以通过上下文决定,或推测type arguments,这个尖括号非正式得叫作diamond(钻石?这么奇葩),你可以这样创建Box< Integer>的一个实例:</p>
<pre><code>Box<Integer> integerBox = new Box<>();
</code></pre><p>要查看更多关于diamond 符号和类型推断(inference),请看<a href="https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html" target="_blank" rel="external">类型推断</a>。</p>
<h3 id="多类型参数"><a href="#多类型参数" class="headerlink" title="多类型参数"></a>多类型参数</h3><p>正如前面提到的,泛型类可以有多个类型参数。比如泛型 OrderedPair 类,实现了泛型接口 Pair:</p>
<pre><code>public interface Pair<K, V> {
public K getKey();
public V getValue();
}
public class OrderedPair<K, V> implements Pair<K, V> {
private K key;
private V value;
public OrderedPair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
</code></pre><p>下面的语句创建了两个OrderedPair的实例:</p>
<pre><code>Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);
Pair<String, String> p2 = new OrderedPair<String, String>("hello", "world");
</code></pre><p>new OrderedPair<string,integer>把K实例化为String,V实例化为Integer。因此OrderedPair的参数类型分别(respectively)是String和Integer。因为<a href="https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html" target="_blank" rel="external">自动装箱</a>,传入String和int到类是有效的。</string,integer></p>
<h3 id="参数化类型"><a href="#参数化类型" class="headerlink" title="参数化类型"></a>参数化类型</h3><p>你也可以用一个参数化的类型(ie List< String>)替换(substitute)类型参数(K ,V),例如用OrderedPair< K,V>:</p>
<pre><code>OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));
</code></pre><h1 id="原类型(Raw-Types)"><a href="#原类型(Raw-Types)" class="headerlink" title="原类型(Raw Types)"></a>原类型(Raw Types)</h1><p>原类型是指泛型类或泛型接口的名字没有任何参数,比如,给出泛型类Box:</p>
<pre><code>public class Box(T){
public void set(T t){
/* ...... */
}
}
</code></pre><p>你可以为形参<strong>T</strong>赋值一个真实的类型参数来创建一个参数化类型的 Box(T):</p>
<pre><code>Box(Ingeter) intBox=new Box<>();
</code></pre><p>如果真实的类型参数被省略掉了,你就创建了一个<strong>原类型</strong>的Box<t>:</t></p>
<pre><code>Box rawBox =new Box();
</code></pre><p>因此,Box是Box<t>的原类型。然而,非泛型类或非泛型接口没有原类型。<br>原类型出现在遗赠的代码里是因为大量的API类(比如<strong>Collections</strong>类)在JDK5之前不是泛型类。当使用原类型的时候,你本质上使用的是泛型之前的表现—Box ->Object.为了向后兼容,赋值参数化类型给他的原类型是允许的:</t></p>
<pre><code>Box<String> stringBox=new Box<>();
Box rawBox=stringBox; //OK
</code></pre><p>但是如果你赋值一个原类型给一个参数化的类型,你将得到警告:</p>
<pre><code>Box rawBox=new Box(); //rawBox是Box<T>()的原类型
Box<Integer> intBox=rawBox; //warning:unchecked conversion
</code></pre><p>当你用原类型调用关联的反省类型的泛型方法时,你也会得到警告:</p>
<pre><code>Box<String> stringBox=new Box<>();
Box rawBox=stringBox;
rawBox.set(8); //waring: unchecked invocation to set(T)
</code></pre><p>警告显示原类型绕过泛型类型检查,延迟捕获不安全代码到运行时。因此,你需要避免使用原类型。<a href="https://docs.oracle.com/javase/tutorial/java/generics/erasure.html" target="_blank" rel="external">类型擦除</a>部分会有更多关于Java编译器如何使用原类型的内容。</p>
<h2 id="Unchecked-Error-Messages"><a href="#Unchecked-Error-Messages" class="headerlink" title="Unchecked Error Messages"></a>Unchecked Error Messages</h2><p>正如上面提到的,当混合遗赠代码和泛型代码时,你可能会碰到跟下面相似的警告:</p>
<pre><code>Note: Example.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
</code></pre><p>这发生在当使用老的API操作原类型时,例如如下代码:</p>
<pre><code>public class WarningDemo {
Box<Integer> bi;
bi=createBox();
}
static Box createBox(){
return new Box();
}
</code></pre><p>‘unchecked’指的是编译器没有足够的类型信息来执行所有必要的类型检查以保证类型安全。</p>
<blockquote>
<ul>
<li>原文链接 [<a href="https://docs.oracle.com/javase/tutorial/java/generics/index.html">https://docs.oracle.com/javase/tutorial/java/generics/index.html</a>)</li>
<li>翻译: <a href="https://github.com/adamin1990">Adamin90</a></li>
<li>转载请注明出处,谢谢!</li>
</ul>
</blockquote>
<h1 id="泛型(已更新)"><a href="#泛型(已更新)" class="headerlink" title="泛型(已更新)"></a>泛型(已更新)</h1><p> 在任何繁琐的(nontrivial)软件项目中,bug是家常便饭。细心的规划,编程和测试可以帮助减少bug的普遍性(pervasiveness),但是无论如何,无论在哪里,bug总会伺机悄悄溜进(creep)你的代码,因为很明显,新的特性会不断的被引入,并且你的代码基数会不断变大和复杂。</p>
<p> 幸运的是,一些bug相比其它比较容易检测。编译时bug可以在早期被检测到;你可以利用编译器的错误信息查明是什么问题并且解决,就在那时。然而,运行时bug会更加未预知,他们不会立即展示出来,不知道什么时候发生,可能根本不在程序真正出现问题的点上。</p>
<p>泛型通过更多的在编译时检测bug为你的代码增加了稳定性。<br>
翻译:no more findViewById
http://xpleeandroid.github.io/2016/06/26/translate-no-more-findviewbyid/
2016-06-26T06:40:57.000Z
2016-06-28T09:49:39.814Z
<blockquote>
<ul>
<li>原文链接 <a href="https://medium.com/google-developers/no-more-findviewbyid-457457644885#.cs0jg2og6" target="_blank" rel="external">https://medium.com/google-developers/no-more-findviewbyid-457457644885#.cs0jg2og6</a></li>
<li>翻译: <a href="https://github.com/adamin1990" target="_blank" rel="external">Adamin90</a></li>
<li>转载请注明出处,谢谢!</li>
</ul>
</blockquote>
<h1 id="No-More-findViewById"><a href="#No-More-findViewById" class="headerlink" title="No More findViewById"></a>No More findViewById</h1><hr>
<p>Android Studio开发android程序的一个小特点是数据绑定。我会在将来的文章中讲解它的其他一些优雅的特点,但是你要了解的最基础的是怎样消除findViewById.<br><a id="more"></a><br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">TextView hello = (TextView) findViewById(R.id.hello);</span><br></pre></td></tr></table></figure></p>
<p>虽然现在有很多试用的方法可以省略这些多余代码,但是Android Studio 1.5以及更高版本已经有官方的方法了。</p>
<p>首先,你必须在Application的build.gradle里的android块内填写如下代码:</p>
<pre><code>android {
…
dataBinding.enabled = true
</code></pre><p>}</p>
<p>下一步就是在你的layout文件的最外层添加 <layout>标签,不管你用的是任何 ViewGroup:</layout></p>
<pre><code><layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView
android:id="@+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</code></pre><p></p>
<p><strong>Layout</strong>标签告诉Android Studio这个layout在编译时将进行额外的操作,查找到所有感兴趣的view,并且标签为下一步。所有外部没有包<code>layout</code>标签的布局将不会执行额外操作。所以你可以在新项目中少量使用而无需改变项目中其他的部分。</p>
<p>下面要做的就是告诉它在运行时分别加载你的layout。因为它向后兼容,所以不需要依赖新框架的改变来加载这些预执行的layout文件。因此你只需对程序做一个轻微的改变。</p>
<p>从一个Activity,不是:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> setContentView(R.layout.hello_world);</span><br><span class="line">TextView hello = (TextView) findViewById(R.id.hello);</span><br><span class="line">hello.setText(<span class="string">"Hello World"</span>); </span><br></pre></td></tr></table></figure>
<p>而是这样加载:</p>
<pre><code>HelloWorldBinding binding =
DataBindingUtil.setContentView(this, R.layout.hello_world);
binding.hello.setText("Hello World");
</code></pre><p>你可以看到 <strong>HelloWordBinding</strong>这个类自动为<strong>hello_world.xml</strong>生成并且id为“@+id/hello”的view分配到了一个<strong>hello</strong>的field你可以使用。没有强制类型转换,没有findViewById.</p>
<p>这标兵这是访问view的机制不仅仅比findViewById更加简单,而且也更加快!绑定程序一次执行覆盖所有layout的view,把view分配到field。当你运行findViewById,的时候view结构每次都会被遍历查找。</p>
<p>你会注意到一件事:它对你的变量名使用了驼峰命名法(比如hello_world.html 变成类 HelloWorldBinding),所以如果你给它的id是“@+id/hello_text”,那么field的名称将会是 helloText.</p>
<p>当你正在inflate你布局里RecyclerView,ViewPager,或其他不设置Activity内容的控件,你将希望在生成的类上用生成的类型安全的方法,这里有几个版本匹配LayoutInflater,所以使用你最适合食用的.举个例子:</p>
<pre><code>HelloWorldBinding binding = HelloWorldBinding.inflate(
getLayoutInflater(), container, attachToContainer);
</code></pre><p>如果你们有把被inflate的view 附加到包含他们的ViewGroup上,你必须访问被infalte的view的view结构。你可以用binding的getRoot()方法:</p>
<pre><code>linearLayout.addView(binding.getRoot());
</code></pre><p>现在,你可能会考虑,如果我有一个layout包含同步view的不同配置呢?layout预执行和运行时inflate阶段通过添加所有View 的id到生成的类,如果没有被inflate的话设置为null。</p>
<p>相当神奇,不是吗?最好的部分是运行时没有反射和其他任何高消耗的技术。把他少量添加到你现有程序里面非常容易,他能让你的生活更加简单,让你的layout加载的更快!</p>
<blockquote>
<ul>
<li>原文链接 <a href="https://medium.com/google-developers/no-more-findviewbyid-457457644885#.cs0jg2og6">https://medium.com/google-developers/no-more-findviewbyid-457457644885#.cs0jg2og6</a></li>
<li>翻译: <a href="https://github.com/adamin1990">Adamin90</a></li>
<li>转载请注明出处,谢谢!</li>
</ul>
</blockquote>
<h1 id="No-More-findViewById"><a href="#No-More-findViewById" class="headerlink" title="No More findViewById"></a>No More findViewById</h1><hr>
<p>Android Studio开发android程序的一个小特点是数据绑定。我会在将来的文章中讲解它的其他一些优雅的特点,但是你要了解的最基础的是怎样消除findViewById.<br>
GoodNight
http://xpleeandroid.github.io/2016/06/25/GoodNight/
2016-06-25T15:50:44.000Z
2016-06-28T05:42:00.662Z
<p> use one day for establish this blog,thanks for opensource!</p>
<p> Now we can say good night!</p>
<p> ``<br><img src="http://f5.topitme.com/5/98/93/1153052438ba893985l.jpg" alt=""></p>
<p> use one day for establish this blog,thanks for opensource!</p>
<p> Now we can say good night!</p>
<p> ``<br><img src="http://f5.topitme.