[转载]ASP.NET MVC3 系列教程 - View的变化

mikel阅读(634)

[转载]ASP.NET MVC3 系列教程 – View的变化 – dotNetDR_ 深圳 点燃象征希望的烛光 – 博客园.

I:首先看看在MVC2及MVC3当中,View的继承结构以及变化

MVC2:
image
根据上图的继承关系说明.~~MVC2当中的VIEW还是和WebForm的Page有着紧密相连的关系.

下面我们来看看MVC3当中发生了什么样的变化.

MVC3(WebForm版本):
image
可以看出上图的部分类显示不”友好”不过MVC3刚出不久.文档资料差就差点吧.不妨碍我前进的步伐!下面自己动手整个完整的呗!

image
经过这么一番折腾.继承结构图就完好无损了.哈!

转入正题
MVC3中还是有一个WebForm版本的继承支持.
在这里和上面介绍的MVC2当中的VIEW进行对比的话无任何重大变化.

变化的是(也就是说新增)下面

MVC3(WebPages版):
image
在这里大家可以看到[零WebForm]的身影!也就是MVC3值得注意的一个亮点!
如果大家不知道.NET 4中新增的WebPages是什么的话,在这里我可以简单地介绍一下:

那个WebPages是WebMatrix提出的专门用来提供*.cshtml*.vbhtmlRazor支持的.
安装目录在:C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\
image
结语:从上面介绍的情况来看,我们终于得知了VS2010当中为什么会出现两个模式的VIEW创建类型,及他们之前的差别在于那里
image

在这里可以准确地告诉大家的是:MVC3对比MVC2在程序集大小方面的确涨了~

关于View的WebPages新加的功能.我会另外作一遍文章介绍~
主要就是MasterPage和LayoutPage的对比!

[转载]ASP.NET MVC3 系列教程 - View的变化

mikel阅读(681)

[转载]ASP.NET MVC3 系列教程 – View的变化 – dotNetDR_ 深圳 点燃象征希望的烛光 – 博客园.

I:首先看看在MVC2及MVC3当中,View的继承结构以及变化

MVC2:
image
根据上图的继承关系说明.~~MVC2当中的VIEW还是和WebForm的Page有着紧密相连的关系.

下面我们来看看MVC3当中发生了什么样的变化.

MVC3(WebForm版本):
image
可以看出上图的部分类显示不”友好”不过MVC3刚出不久.文档资料差就差点吧.不妨碍我前进的步伐!下面自己动手整个完整的呗!

image
经过这么一番折腾.继承结构图就完好无损了.哈!

转入正题
MVC3中还是有一个WebForm版本的继承支持.
在这里和上面介绍的MVC2当中的VIEW进行对比的话无任何重大变化.

变化的是(也就是说新增)下面

MVC3(WebPages版):
image
在这里大家可以看到[零WebForm]的身影!也就是MVC3值得注意的一个亮点!
如果大家不知道.NET 4中新增的WebPages是什么的话,在这里我可以简单地介绍一下:

那个WebPages是WebMatrix提出的专门用来提供*.cshtml*.vbhtmlRazor支持的.
安装目录在:C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\
image
结语:从上面介绍的情况来看,我们终于得知了VS2010当中为什么会出现两个模式的VIEW创建类型,及他们之前的差别在于那里
image

在这里可以准确地告诉大家的是:MVC3对比MVC2在程序集大小方面的确涨了~

关于View的WebPages新加的功能.我会另外作一遍文章介绍~
主要就是MasterPage和LayoutPage的对比!

[转载]Asp.Net Mvc: 浅析TempData机制

mikel阅读(838)

[转载]Asp.Net Mvc: 浅析TempData机制 – Tristan’s Tech Farm – 博客园.

环境:

Windows 2008, VS 2008 SP1, ASP.NET Mvc 1.0

——————————————————————————

一. ASP.NET Mvc中的TempData

在Asp.Net Mvc框架的ControllerBase中存在一个叫做TempData的Property,它的类型为TempDataDictionary,顾名思 义是一个字典类。TempData在Asp.Net Mvc中的作用是:可用于在Action执行过程之间传值。简单的说,你可以在执行某个Action的时候,将数据存放在TempData中,那么在下一 次Action执行过程中可以使用TempData中的数据。

如:

上面的代码中,Index()给TempData添加了一个键值对,假设我们先请求Index这个Action,接着请求Index2这个 Action,那么在Index2中,我们便可以得到之前添加到TempData的键值对。有趣的是,这时如果再次请求Index2,那么从 TempData中读到的MyName的值会是null。于是,我们需要了解TempData的生命周期。

二. TempData的生命周期

我们知道Http是无状态的,为什么TempData可以在两次请求之前传递数据呢?很明显,这个数据必定是已某种形式保存了。查看Controller类的源代码,很容易的找到了我们想要的东西:

从上面的代码可以看出,每次在执行Action之前,都要调用一下TempData.Load()方法,执行完Action之后,再调用一下TempData.Save()方法。另外这里还有一个重要成员TempDataProvider。

阅读了相关源代码之后,真相大白了。

TempData.Load()

TempData.Save()

TempDataProvider 用于暂存数据。在TempData.Load()方法中,TempDataProvider中保存的数据会被读到TempData中,供Action调用 过程中使用。Action执行完后,TempData.Save()所作的事情则是,移除TempData中任何没有被更新的键值对,然后再将 TempData中的数据保存,供下一次调用使用(注:也就是说,只有更新过的,以及新添加的键值对才能再下次request中继续使用)。为什么 TempData中的数据需要迅速被清除呢?很简单,节约内存嘛。

三. ITempDataProvider

前面提到的TempDataProvider是Controller的一个Property,它的定义是这样的:

这里我们看到了一个默认实现的SessionStateTempDataProvider类。也就是说,默认情况下,Asp.Net Mvc通过SessionStateTempDataProvider来保存TempData的数据。很明显,数据是存在Session中的,也就是说, 如果你禁用SessionState,那么你的页面就报异常了。

Asp.Net Mvc生来就是被设计为易扩展的,我们可以很容易通过实现自己的ITempDataProvider类来替换这个默认的 SessionStateTempDataProvider。需要注意的是,TempDataProvider存放的数据必需具有用户独立性。

ITempDataProvider接口定义非常简单:

在MvcFutures中,你也可以找到一个CookieTempDataProvider,提供了将TempData存储在Cookie中的实现。

[转载]推荐18个非常棒的Web和移动开发框架

mikel阅读(1114)

[转载]推荐18个非常棒的Web和移动开发框架 – 梦想天空 – 博客园.

如今,Web开发有了很多的辅助框架,它们可以帮助Web开发人员集中精力去实现他 们头脑中的想法而不必浪费过多的时间去思考如何设计网站。当然,第一次使用这些框架或者库的时候可能并不是那么容易,不过通过阅读帮助文档和不断的实践, 相信你很快就能掌握的。今天,本文收集了18个非常棒的Web和移动应用程序开发框架与大家分享。

iWebKit

jQTouch

jQuery Mobile

Sencha Touch

Wijmo – jQuery UI Widgets

The-M-Project – HTML5 Javascript Framework

Treesaver.js – Framework for Creating Magazine-Style Layouts

jQuery Form Framework – jFormer

Not Just A Grid – Flexible and Modular CSS Framework

Zepto.js – Minimalist JavaScript Framework for Mobile

Galleria – JavaScript Image Gallery Framework

Gury – HTML5 Canvas Utility Library

Amplify

Mobl – Open-Source HTML5-Based Language

SproutCore – HTML5 Application Framework

Initializr – HTML5 Templates Generator

iX Framework – JavaScript-Based UI Framework

DHTMLX Touch – HTML5 JavaScript Framework for Mobile

(编译来源:梦想天空 原文来自:18 New Useful Frameworks for Web and Mobile App Developers

[转载]QQ协议分析

mikel阅读(901)

[转载]QQ协议分析 – 道简 – 博客园.

0x0001  注销登录
0x0002  心跳信息
0x0004  更新用户信息
0x0005  搜索用户
0x0006  获取用户信息
0x0009  不需认证方式添加好友
0x000a  删除好友
0x000b  需要认证的方式添加好友
0x000d  设置隐身、示忙等状态

(0x00A6)获取天气预报
0x0012  确认收到系统消息
0x0016  发送消息
0x0017  收到消息(服务器发起)接收群成员消息(0x0017,消息类型0x008C)

接收临时会话消息(0x0017,消息类型0x001F)

接收群消息(0x0017,消息类型0x002B)
0x001a  未知作用。
0x001c  在对方好友列表上删除自己
0x001d  未知作用。
0x0022  登录
0x0026  获取好友清单
0x0027  获取在线好友
0x0030  群操作指令
0x0080  收到系统消息(服务器发起)有人请求加我为好友

0x0081  收到好友状态改变消息(服务器发起)

(0x0126)获取好友列表

(0x0058) 获取好友所属分组

(0x003C)获取分组名称

0x00DD 号码需要激活

http://blog.csdn.net/zym_123456/

http://blog.csdn.net/hujiangnet

http://blog.csdn.net/eleven_1/

[转载]ASP.NET MVC 1.0,静态化缓存 和 OutputCache

mikel阅读(784)

[转载]ASP.NET MVC 1.0,静态化缓存 和 OutputCache – 天空站长教程网 | 天空站长学编程,学习,考试,认证的最佳网站 – www.qzsou.cn.

静态化缓存 和 OutputCache 不同,它适用于那些有大量可访问页面(的)网站(比如新闻站点)。要知道我们(的)网站每天都会被(很)多智商不高(的)傻蜘蛛和灌水机做全身检查,这些 家伙往往会深度遍历 n 多(的)页面,(很)容易导致我们有限(的) “动态缓存” 被频繁刷新,失去了缓存应有(的)价值。还有一点,静态缓存往往独立存储,可以(是)多台 Memchaced 或者 DFS 系统,如此在一个负载均衡环境里,这种跨进程和机器(的)缓存模式会更有效。

我们首先定义一个缓存接口,以便日后可以实现多种缓存策略。

public interface IStaticCache
{
  void Set(string key, object value, DateTime absoluteExpiration);
  void Set(string key, object value, TimeSpan slidingExpiration);
  T Get<T>(string key);
  void Delete(string key);
}

  接下来,我们要拦截 ActionResult Render 输出,将其保存到缓存中,并在下一次访问时使用。原理(很)简单,(就是)调用 Response.SwitchWriter 更换输出器。

public sealed class HttpResponse
{
  internal TextWriter SwitchWriter(TextWriter writer)
  {
    TextWriter writer2 = this._writer;
    this._writer = writer;
    return writer2;
  }  
}

  虽然(是) internal,用反射还(是)(很)容易达成目(的)。

private TextWriter SwitchWriter(TextWriter writer)
{
  var method = typeof(HttpResponse).GetMethod("SwitchWriter", 
    BindingFlags.NonPublic | BindingFlags.Instance);
  return method.Invoke(HttpContext.Current.Response, new object[] { writer }) as TextWriter;
}

[转载]C#编写QQ接口软件--QQ协议篇

mikel阅读(1090)

[转载]C#编写QQ接口软件–QQ协议篇 – yet – 博客园.

1、找寻支持QQ HTTP协议的服务器。
大家也许会被一些假像所迷惑,也许会认为QQ的HTTP服务器是基于80口进行通信的(如:218.17.209.23:80),其实不然,正真基于HTTP的服务器应该是:http://tqq.tencent.com:8000,它是一个通过8000口进行通讯的服务器。
由于QQ的HTTP服务器并不支持HTTP协议中GET方法,它支持POST方法。所以我们要给QQ的HTTP协议传参数,那么就必需要用POST方式才行。
2、C#和DELPHI是实现HTTP的POST方法的通信。

DELPHI:
Delphi里我们利用一个比较流行的第三方VCL,INDY HTTP(这个组件D6,D7里面自带)进行HTTP通信。
使用其的POST方法便可以进行HTTP的POST通信,因为组件比较好用,我就不在其描述具体的过程了。大家
可以参考以下代码:
function PostWebPage(url,para:String;TimeOut:Integer):String;
var
tmpWeb:TIdHTTP;
retrun:String;
Proxy:String;
i:Integer;
paralist:TStrings;
begin
retrun:=”;
try
paralist:=TStringList.Create;
paralist.Text:=_Replacing(para,’&’,#13#10);
tmpWeb:=TIdHTTP.Create(nil);
tmpWeb.ReadTimeout:=TimeOut;
for i:=1 to 3 do
begin
try
retrun:=tmpWeb.Post(url,paralist);
except end;
if retrun<>” then break;
end;
finally
tmpWeb.Disconnect;
FreeAndNil(tmpWeb);
FreeAndNil(paralist);
end;
Result:=retrun;
end;
值在传入、返回时,其是基于UTF-8进行的,C#显示中文是很常,而DELPHI就要进行UTF-8的转换了。大家
可通过Utf8ToAnsi()、AnsiToUtf8()进行转换
C#:
C#里System.Web空间下提供了一个叫做WebClient的对象,使用此对象就可以使C#直接对服务器发送WEB客户端的请求。那么我们要对服 务器提交POST方法那么就必须使用其UploadData()方法才行。首先把要请求的信息先转换为字节(因为POST提交的是字符的流数据),然后再 做为UploadData()的参数。使用UploadData()进行数据提交,最后返回,POST的回馈信息。如下:

WebClient _client = new WebClient();
string postValues = “VER=1.0&CMD=Query_Stat&SEQ=12321&UIN=29501213&TN=50&UN=0″;
Byte[] byteArray = System.Text.Encoding.ASCII.GetBytes(postValues);
Byte[] pageData = _client.UploadData(Host,”POST”,byteArray);

这样,我们就利用C#进行了一次HTTP的POST方法提交了。

值在传入、返回时,其是基于UTF-8进行的,C#显示中文是很常.

3、实现QQ的用户登录。
在QQ通信中用户必需要登录后才可以进行互相发送信息等。QQ的登录是很关键的,大家所看到的用户在线,并不是用户的QQ一直连接着服务器,而是定时发送消信给服务器,证明自己还连着线,如果超出时间QQ就认为用户已经掉线了。
在登录协议中,QQ的密码是用标准的MD5来进行加密,而C#自已带有,但是直接用不了,必需进行处理后,才能使其变成标准的MD5,处理代码如下:

public static string MD5(string toCryString)
{
MD5CryptoServiceProvider hashmd5;
hashmd5 = new MD5CryptoServiceProvider();
return BitConverter.ToString(hashmd5.ComputeHash(Encoding.Default.GetBytes(toCryString))).Replace(“-“,””).ToLower();//asp 是小写,把所有字符变小写
}

了解QQ是如何对用户密码加密后,那么我们就开始真正,解析QQ的HTTP登录协议了,我们把协议当传POST的参数传给服务器,而服务器则回馈相应的信息给客户端:
传入协议:
VER=1.1&CMD=Login&SEQ=&UIN=&PS=&M5=1&LC=9326B87B234E7235

VER是用来说明QQ协议的版本,CMD是说明协议的命令,Login就是指QQ的登录了,SEQ是他的为了防止重复发送而设定的一个标记,一般我们取当 前时间数值的一段放入即可。(C#:DateTime.Now.Ticks.ToString().Substring(7,7) DELPHI:CopyStr(inttostr(GetTickCount()),1,5)),UIN是说明你当前要登录的用户QQ号,PS,是MD5 加密过后的密码的值。

返回协议:

VER=1.1&CMD=Login&SEQ=11281&UIN=&RES=0&RS=0&HI=60&LI=300(成功)

RES为0表示成功返回,RS为0表示登录成功。

VER=1.1&CMD=Login&SEQ=11422&UIN=315103947&RES=0&RS=1&RA=登录失败

RS为1表示登录失败,那么就会出现提示信息RA说明原因。
4、获得QQ名单。
如果您加了您的好友,那么您的好友就会放入你的QQ的好友名单里面,那么我们要得到QQ名单就必需给QQ服务器发送得到好友名单的协议(我就不从复已知的参数了):

VER=1.1&CMD=List&SEQ=&UIN=&TN=160&UN=0

服务器得到协议后如果成功则返回:

VER=1.1&CMD=LIST&SEQ=43661&UIN=29501213&RES=0&FN=1&SN=24&UN=561256,1943497,….

UN后面则是您好友的QQ号码,每个号码都由,进行分开。那么我们只需要得到UN后面的代码,把它列表化就OK了。C#可以用string.Split(‘,’)把值放入列表进行处理,而DELPHI可以使用Split()把数值放入TStrings里进行处理。

5、获得QQ好友在线名单
获得QQ好友在线名单,跟获得好友名单差不多,唯一不同的是用的命令不同用的是Query_Stat,协议如下:

VER=1.1&CMD=Query_Stat&SEQ=&UIN=&TN=50&UN=0

服务器得到协议后如果成功则返回:

VER=1.1&CMD=QUERY_STAT&SEQ=-1&UIN=29501213&RES=0&FC=141,270,270,&FN=1&SN=3&ST=10,10,10,&UN=

FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1。ST为QQ用户的状态,10为上线,20为离线,30为忙碌。UN为在线用户的QQ号,NK为在线用户的QQ昵称。ST,UN,NK,每个逗号隔开的数据相互对应。
6、得到QQ用户的信息。
如果要看到QQ用户的真实名称,MAIL,年龄,个人说明等信息,那么我们必需要向服务器发送得到好友信息的信息:

VER=1.1&CMD=GetInfo&SEQ=&UIN=&LV=2&UN=

UN为要查看用户信息的QQ号。

服务器得到协议后如果成功则返回:

VER=1.1&CMD=GETINFO&SEQ=12707&UIN=415103947&RES=0&AD=云南昆明&AG=0&EM=Microprogramer@hotmail.com&FC=270&HP=msger.org(建 设中…)&JB=程序员&LV=2&PC=650000&PH=0871-6466529&PR=网络为 媒%252c关系为本%252c信息为财%252c客户为主.%0d%0a&PV=云南省&RN=刘X&SC=社会大学& amp;SX=0&UN=24259132&NK=微程

AD用户的联系地址,AG为用户年龄,EM为用户MAIL,FC为用户头像,HP为用户网站,JB为用户职业,PC为用户邮编,PH为用户联系电 话,PR为用户简介,PV为用户所以的省,RN为用户真实名称,SC为用户毕业院校,SX为用户性别,UN为用户QQ号,NK为用户QQ昵称。

7、增加QQ好友。
想要新增好友,就要发送AddToList命令给服务器,具体命令如下:

VER=1.1&CMD=AddToList&SEQ=&UIN=&UN=

UN为我们要增加用户的QQ号。

服务器得到协议后如果成功则返回:

VER=1.1&CMD=AddToList&SEQ=13666&UIN=415103947&RES=0&CD=0&UN=24259132

CD为被加QQ的身份验证状态,CD为0表示“允许任何人把我列为好友”,CD为1表示“需要身份证认才能把我列为好友”,CD为3表示“不允许任 何人把我列为好友”。如果CD为0那么信息回馈后,用户就直接加为好友了,如果CD为1,那么还要发送一次回应加为好友的响应。

8、回应加为好友的响应。

回应加为好友响应是双方的:1、如果你发送了请求加对方为好友,如果对方需要验证,那么必需发送回应加为好友的响应。2、如果对方发送加为好友请求给你,那么你可以加应加为好友的响应,一是加为好友,一是通过验证,一是拒决加为好友。我们要向服务器发送命令:

VER=1.1&CMD=Ack_AddToList&SEQ=&UIN=&UN=&CD=&RS=

CD为响应状态,CD为0表示“通过验证”。CD为1表示“拒决加为对方为好友”。CD为2表示“为请求对方加为好友”。RS为你要请求的理由.

服务器得到协议后如果成功则返回:

VER=1.1&CMD=Ack_AddToList&SEQ=1130&UIN=415103947&RES=0&

9、删除好友。

删除好友其实很容易,向服务器发送DelFromList命令则可以删除用户:

VER=1.1&CMD=DelFromList&SEQ=&UIN=&UN=

UN为要删除用户的QQ号。

服务器得到协议后如果成功则返回:

VER=1.1&CMD=DelFromList&SEQ=24514&UIN=415103947&RES=0&

10、改变用户当前状态。
可以把QQ设置为在线,隐身等状态,我们可以发送Change_Stat给服务器以改变当前状态,具体命令如下:

VER=1.1&CMD=Change_Stat&SEQ=&UIN=&ST=

ST为要改变的状态,10为上线,20为离线,30为忙碌。

服务器得到协议后如果成功则返回:

VER=1.1&CMD=Change_Stat&SEQ=17512&UIN=415103947&RES=0&

11、退出登录
要退出登录,要向服务器发送命令Logout,具体命令如下:

VER=1.1&CMD=Logout&SEQ=&UIN=

服务器得到协议后如果成功则返回:

VER=1.1&CMD=LOGOUT&SEQ=15803&UIN=415103947&RES=0

12、获得好友QQ的消息

如果要接收好友的消息,要向服务器发送命令GetMsgEx,具体命令如下:

VER=1.1&CMD=GetMsgEx&SEQ=&UIN=

服务器得到协议后如果成功则返回:

VER=1.1&CMD=GETMSGEX&SEQ=56661&UIN=29501213&RES=0&MN=3&MT=99,9,9,&UN=24259132,24259132,24259132,&MG=30 ,asdfasdfasdfasdf ,asdfasdfasdf ,&

MT表示消息类型,99表示系统消息,9表示用户消息。UN表示消息发送来源用户,MG表示发送的消息,MG消息可以表示某些特定的系统含意,譬 如:当MT为99,MG为30,UN为24259132则表示用户4259132现在处于忙碌状态,可根据此消息进行好友列表的刷新,提高效率。

13、向好友QQ发送消息

要发送消息给好友,要向服务器发送命令CLTMSG命令,具体命令如下:

VER=1.1&CMD=CLTMSG&SEQ=&UIN=&UN=&MG=

UN为消息发送给的用户QQ号码,MG为发送给该用户的消息。

服务器得到协议后如果成功则返回:

VER=1.1&CMD=CLTMSG&SEQ=15803&UIN=415103947&RES=0

好了,以上就是QQ基于HTTP的一个不完全的协议分析,利用以上协议您就可以实现很多东西,如:QQ机器人,QQ广告系统,即时通讯的整合工具等等

QQ协议网络协议–请求部份

//登录
VER=1.0&CMD=Login&SEQ=&UIN=&PS=&M5=1&LC=9326B87B234E7235

//获取消息
VER=1.0&CMD=GetMsgEx&SEQ=&UIN=

//发送消息
VER=1.0&CMD=CLTMSG&SEQ=&UIN=&UN=&MG=

//朋友列表
VER=1.0&CMD=List&SEQ=&UIN=&TN=160&UN=0

//获取好友状态
VER=1.0&CMD=Query_Stat&SEQ=&UIN=&TN=50&UN=0

//获取好友信息
VER=1.0&CMD=GetInfo&SEQ=&UIN=&LV=2&UN=

//增加好友
VER=1.0&CMD=AddToList&SEQ=&UIN=&UN=

//回应对方请求加你为好友的响应
VER=1.0&CMD=Ack_AddToList&SEQ=&UIN=&UN=&CD=&RS=

//删除好友
VER=1.0&CMD=DelFromList&SEQ=&UIN=&UN=

//搜索好友
VER=1.0&CMD=Finger&SEQ=&UIN=&AG=&SX=&PV=

//改变自己状态,ST的代码应该和获取好友状态代码一致
VER=1.0&CMD=Change_Stat&SEQ=&UIN=&ST=

//退出登录
VER=1.0&CMD=Logout&SEQ=&UIN=

[转载]Android学习系列(2)--App自动更新之通知栏下载

mikel阅读(820)

[转载]Android学习系列(2)–App自动更新之通知栏下载 – 谦虚的天下 – 博客园.

见证过博客园的多次升级,你也希望你的软件通过更新发布新特性通知用户吧,是的。
这篇文章是Android开发人员的必备知识,是我特别为大家整理和总结的,不求完美,但是有用。

1.设计思路,使用VersionCode定义为版本升级参数。
Android为我们定义版本提供了2个属性:

android:versionCode="1" <!--Integer类型,系统不显示给用户-->
android:versionName="1.0"<!--String类型,系统显示用户-->
&gt;

谷歌建议我们使用versionCode自增来表明版本升级,无论是大的改动还是小的改动,而versionName是显示用户看的软件版本,作为显示使用。所以我们选择了VersionCode作为我们定义版本升级的参数。

2.工程目录
为了对真实项目或者企业运用有实战指导作用,我模拟一个独立的项目,工程目录设置的合理严谨一些,而不是仅仅一个demo。
假设我们以上海地铁为项目,命名为”Subway”,工程结构如下,

3.版本初始化和版本号的对比。
首先定义在全局文件Global.java中定义变量localVersion和serverVersion分别存放本地版本号和服务器版本号。

public class Global {
//版本信息
public static int localVersion = 0;
public static int serverVersion = 0;
}

3.版本初始化和版本号的对比。
首先定义在全局文件Global.java中定义变量localVersion和serverVersion分别存放本地版本号和服务器版本号。

public class Global {
//版本信息
public static int localVersion = 0;
public static int serverVersion = 0;
}

因为本文只是重点说明升级更新,为了防止其他太多无关代码冗余其中,我直接在SubwayApplication中定义方法initGlobal()方法。

/**
* 初始化全局变量
* 实际工作中这个方法中serverVersion从服务器端获取,最好在启动画面的activity中执行
*/
public void initGlobal(){
try{
Global.localVersion = getPackageManager().getPackageInfo(getPackageName(),0).versionCode; //设置本地版本号
Global.serverVersion = 1;//假定服务器版本为2,本地版本默认是1
}catch (Exception ex){
ex.printStackTrace();
}
}

如果检测到新版本发布,提示用户是否更新,我在SubwayActivity中定义了checkVersion()方法:

/**
* 检查更新版本
*/
public void checkVersion(){

if(Global.localVersion &lt; Global.serverVersion){
//发现新版本,提示用户更新
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("软件升级")
.setMessage("发现新版本,建议立即更新使用.")
.setPositiveButton("更新", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//开启更新服务UpdateService
//这里为了把update更好模块化,可以传一些updateService依赖的值
//如布局ID,资源ID,动态获取的标题,这里以app_name为例
Intent updateIntent =new Intent(SubwayActivity.this, UpdateService.class);
updateIntent.putExtra("titleId",R.string.app_name);
startService(updateIntent);
}
})
.setNegativeButton("取消",new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert.create().show();
}else{
//清理工作,略去
//cheanUpdateFile(),文章后面我会附上代码
}
}

如下图:

好,我们现在把这些东西串一下:
第一步在SubwayApplication的onCreate()方法中执行initGlobal()初始化版本变量。

public void onCreate() {
super.onCreate();
initGlobal();
}

第二步在SubwayActivity的onCreate()方法中检测版本更新checkVersion()。

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
checkVersion();
}

现在入口已经打开,在checkVersion方法的第18行代码中看出,当用户点击更新,我们开启更新服务,从服务器上下载最新版本。

4.使用Service在后台从服务器端下载,完成后提示用户下载完成,并关闭服务。
定义一个服务UpdateService.java,首先定义与下载和通知相关的变量:

//标题
private int titleId = 0;

//文件存储
private File updateDir = null;
private File updateFile = null;

//通知栏
private NotificationManager updateNotificationManager = null;
private Notification updateNotification = null;
//通知栏跳转Intent
private Intent updateIntent = null;
private PendingIntent updatePendingIntent = null;

在onStartCommand()方法中准备相关的下载工作:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//获取传值
titleId = intent.getIntExtra("titleId",0);
//创建文件
if(android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState())){
updateDir = new File(Environment.getExternalStorageDirectory(),Global.downloadDir);
updateFile = new File(updateDir.getPath(),getResources().getString(titleId)+".apk");
}

this.updateNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
this.updateNotification = new Notification();

//设置下载过程中,点击通知栏,回到主界面
updateIntent = new Intent(this, SubwayActivity.class);
updatePendingIntent = PendingIntent.getActivity(this,0,updateIntent,0);
//设置通知栏显示内容
updateNotification.icon = R.drawable.arrow_down_float;
updateNotification.tickerText = "开始下载";
updateNotification.setLatestEventInfo(this,"上海地铁","0%",updatePendingIntent);
//发出通知
updateNotificationManager.notify(0,updateNotification);

//开启一个新的线程下载,如果使用Service同步下载,会导致ANR问题,Service本身也会阻塞
new Thread(new updateRunnable()).start();//这个是下载的重点,是下载的过程

return super.onStartCommand(intent, flags, startId);
}

上面都是准备工作,如图:

从代码中可以看出来,updateRunnable类才是真正下载的类,出于用户体验的考虑,这个类是我们单独一个线程后台去执行的。
下载的过程有两个工作:1.从服务器上下载数据;2.通知用户下载的进度。
线程通知,我们先定义一个空的updateHandler。

private Handler updateHandler = new  Handler(){
@Override
public void handleMessage(Message msg) {

}
};

再来创建updateRunnable类的真正实现:

class updateRunnable implements Runnable {
Message message = updateHandler.obtainMessage();
public void run() {
message.what = DOWNLOAD_COMPLETE;
try{
//增加权限;
if(!updateDir.exists()){
updateDir.mkdirs();
}
if(!updateFile.exists()){
updateFile.createNewFile();
}
//下载函数,以QQ为例子
//增加权限;
long downloadSize = downloadUpdateFile("http://softfile.3g.qq.com:8080/msoft/179/1105/10753/MobileQQ1.0(Android)_Build0198.apk",updateFile);
if(downloadSize&gt;0){
//下载成功
updateHandler.sendMessage(message);
}
}catch(Exception ex){
ex.printStackTrace();
message.what = DOWNLOAD_FAIL;
//下载失败
updateHandler.sendMessage(message);
}
}
}

下载函数的实现有很多,我这里把代码贴出来,而且我们要在下载的时候通知用户下载进度:

public long downloadUpdateFile(String downloadUrl, File saveFile) throws Exception {
//这样的下载代码很多,我就不做过多的说明
int downloadCount = 0;
int currentSize = 0;
long totalSize = 0;
int updateTotalSize = 0;

HttpURLConnection httpConnection = null;
InputStream is = null;
FileOutputStream fos = null;

try {
URL url = new URL(downloadUrl);
httpConnection = (HttpURLConnection)url.openConnection();
httpConnection.setRequestProperty("User-Agent", "PacificHttpClient");
if(currentSize &gt; 0) {
httpConnection.setRequestProperty("RANGE", "bytes=" + currentSize + "-");
}
httpConnection.setConnectTimeout(10000);
httpConnection.setReadTimeout(20000);
updateTotalSize = httpConnection.getContentLength();
if (httpConnection.getResponseCode() == 404) {
throw new Exception("fail!");
}
is = httpConnection.getInputStream();
fos = new FileOutputStream(saveFile, false);
byte buffer[] = new byte[4096];
int readsize = 0;
while((readsize = is.read(buffer)) &gt; 0){
fos.write(buffer, 0, readsize);
totalSize += readsize;
//为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次
if((downloadCount == 0)||(int) (totalSize*100/updateTotalSize)-10&gt;downloadCount){
downloadCount += 10;
updateNotification.setLatestEventInfo(UpdateService.this, "正在下载", (int)totalSize*100/updateTotalSize+"%", updatePendingIntent);
updateNotificationManager.notify(0, updateNotification);
}
}
} finally {
if(httpConnection != null) {
httpConnection.disconnect();
}
if(is != null) {
is.close();
}
if(fos != null) {
fos.close();
}
}
return totalSize;
}

显示下载进度,如图:

下载完成后,我们提示用户下载完成,并且可以点击安装,那么我们来补全前面的Handler吧。
先在UpdateService.java定义2个常量来表示下载状态:

//下载状态
private final static int DOWNLOAD_COMPLETE = 0;
private final static int DOWNLOAD_FAIL = 1;

根据下载状态处理主线程:

private Handler updateHandler = new  Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case DOWNLOAD_COMPLETE:
//点击安装PendingIntent
Uri uri = Uri.fromFile(updateFile);
Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
updatePendingIntent = PendingIntent.getActivity(UpdateService.this, 0, installIntent, 0);

updateNotification.defaults = Notification.DEFAULT_SOUND;//铃声提醒
updateNotification.setLatestEventInfo(UpdateService.this, "上海地铁", "下载完成,点击安装。", updatePendingIntent);
updateNotificationManager.notify(0, updateNotification);

//停止服务
stopService(updateIntent);
case DOWNLOAD_FAIL:
//下载失败
updateNotification.setLatestEventInfo(UpdateService.this, "上海地铁", "下载完成,点击安装。", updatePendingIntent);
updateNotificationManager.notify(0, updateNotification);
default:
stopService(updateIntent);
}
}
};

下载完成,如图:

至此,文件下载并且在通知栏通知进度。
发现本人废话很多,其实几句话的事情,来来回回写了这么多,啰嗦了,后面博文我会朝着精简方面努力。
PS:前面说要附上cheanUpdateFile()的代码

File updateFile = new File(Global.downloadDir,getResources().getString(R.string.app_name)+".apk");
if(updateFile.exists()){
//当不需要的时候,清除之前的下载文件,避免浪费用户空间
updateFile.delete();
}

[转载]高效CSS写法

mikel阅读(823)

[转载]高效CSS写法 – yupeng – 博客园.

上周末翻译了molliza 和google关于高效CSS 的写法的文章,觉得他们的说法有一些共同之处,就是CSS解析引擎是从右到左开始解析的,我们要做的就是减少CSS

引擎的解析时间,所以避免一些低效的CSS 选择器去匹配大量元素能够减少页面加载的时间。结合我自己编写CSS的经验,我总结如下:

1) CSS 的层级选择器不要超过3个,保持3个以内

bad case: .class1 ul li a{}

good case .class a{}

2) 尽量少使用标签选择器,但是也是可以使用的,比如写列表(ul li语法)的时候,如果给每个li一个class,那样相反不仅代码难看,而且也无疑的增加了代码

复杂度,很难维护,总之,在于自己权衡这个点就是了。

3) 使用一些有代表意义的单词,比如我在模块化开发的过程中,我一般用mod-xxx,在这里模块中我写的CSS都在这个里面包含,很利于维护,代码也很漂亮,

不会超过3层的包含关系。也不用过多的考虑同名的问题。

4)不要早id前面添加任何限定符,包括class tag 或者其他的选择符。

bad case: .class #id{}   div#id{}这2个都是不推荐的

good case: #id{}推荐的做的

5)不要再class 前面使用标签限定符,除非你是想给不同的标签定义多个class ,那么只有这样用了。

bad case: div.class{}

good case :.class{}

另外: div.class{} span.class{} 这样那就这样吧。。

6) 使用class 来代替层级关系,如果发现要写很多的层级关系才能表达意义的时候,那么放弃吧。干脆写一个class 来替代这个解决方案。例如

bad case: #id .class1 ul li a{}

good case .class2{}

将这个class2直接加在a标签上。

请各位大侠拍砖。谢谢。

[转载]jQuery实战之仿淘宝商城左侧导航效果

mikel阅读(702)

[转载]jQuery实战之仿淘宝商城左侧导航效果 – Mr.mac – 博客园.

网络上很很多这种效果的JS写法,但是还没有看见用JQuery写的,效果实现很简单,确切的说是用JQuery实现这个效果很简单,这就是JQuery的强大和魅力所在。

希望对大家有用。

下面是效果图:

效果实现基于jq的 .html()方法。大大简化了对DOM的操作。

下面是代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content= "text/html; charset=utf-8">
        <title>仿淘宝商城左侧导航效果t</title>
        <script src="jquery-1.4.2.min.js" type="text/javascript">
        </script>
        <style type="text/css">
            * {
                margin: 0px;
                padding: 0px;
            }
            
            ul{
                list-style: none;
            }
            
            ul.nav li {
                cursor: pointer;
                width: 130px;
                height: 30px;
                text-align: center;
                border: 1px solid #A91319;
                line-height: 30px;
                margin: 4px auto;
                background: #FFF8F6
            }
            
            ul.nav li a {
                width: 130px;
                height: 30px;
                display: block;
                color: #A71F37;
                text-decoration: none;
            }
            
            ul.nav li a:hover {
                background: #A91319;
                width: 130px;
                height: 30px;
                display: block;
                color: #ffffff
            }
            
            div#showValue {
                border: 3px solid #A91319; background:#ffffff; width:400px; height:auto; padding-bottom:10px;
            }
			ul.brand_list{ overflow:hidden; width:350px;}
			ul.brand_list li{line-height:30px; height:auto;}
			ul.brand_list li.brand_name{ font-weight:bolder; width:100px; float:left; margin-left:10px; color:#A71F37; margin-right:5px;}
			ul.brand_list li.brand_content{ width:220px; float:right;} 		
			ul.brand_list li.brand_content a{color:#A71F37; text-decoration:none; }
			ul.brand_list li.brand_content span{ padding:0 3px; border-left:1px solid #cccccc; font-size:14px;}
			
			
			
			
        </style>
    </head>
    <body>
        <div id='guid' style=" width:200px;">
            <ul class="nav" style=" border:none;">
                <li>
                    <a href="#">潮流服饰</a>
                </li>
                <li>
                    <a href="#">精品鞋包</a>
                </li>
                <li>
                    <a href="#">运动户外</a>
                </li>
                <li>
                    <a href="#">手机数码</a>
                </li>
                <li>
                    <a href="#">母婴用品</a>
                </li>
            </ul>
        </div>
        <div id="hdValue" style=" display:none; position:absolute; left:0px;">
            <div>
               <div class="con_st">
               	  <h3>品牌关键字1</h3>
				  <div>
				  	  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					
				  </div>
               </div> 
            </div>
			
            <div>
             <div class="con_st">
               	  <h3>品牌关键字2</h3>
				  <div>
				  	  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
				  </div>
               </div>    
				
            </div>
            <div>
            	 <h3>品牌关键字3</h3>
               <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
            </div>
            <div>
            	 <h3>品牌关键字4</h3>
               <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul> 
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>     
					 </div>
            <div>
            	 <h3>品牌关键字5</h3>
              <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
					  <ul class="brand_list">
				  	  	<li class="brand_name">大家电<b>></b></li>
						<li class="brand_content">
							<span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span><span><a href="#">品牌</a></span>
						</li>
						
				  	  </ul>
			        </div>
        </div>
        <div id="showValue" style=" z-index:22; display:none; position:fixed; top:-77px; left:130px; margin-left:20px; margin-top:100px;">
        </div>
        <script type="text/javascript">
            $(document).ready(function(){//加载DOM
                if (!$("#guid").is(":animated")) {//首先判断是否处于动画状态
                    var lis = $("#guid ul.nav li");
					//遍历文档树
                    lis.each(function(i){
                        $(this).bind("mouseover", i, function(){
                            $("#showValue").show();
                            var hv = $("#hdValue").children().eq(i);
                            $("#showValue").html(hv.html());
                            $("#showValue").bind("mouseover", function(){
                                $("#showValue").show();
                            })
                        });
                        
                    });
					//控制鼠标移除事件
                    $("#guid,#showValue").mouseleave(function(){
                       
                        $("#showValue").hide();
                    });                   
                }
            });
        </script>
    </body>
</html>