[转载]C#环境下使用 Get 和Post 的方式访问WFS服务 - Li Minghua的专栏 - 博客频道 - CSDN.NET

mikel阅读(868)

[转载]C#环境下使用 Get 和Post 的方式访问WFS服务 – Li Minghua的专栏 – 博客频道 – CSDN.NET.

软件开发环境:VS2010

地图服务器:GeoServer 2.3.1

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.Text;

 

private void GetUrlData()

        {
            WebClient client = new WebClient();
            string rUrl = "http://10.14.1.34:8080/geoserver/wfs?service=WFS&version=1.0.0&request=getFeature&typeName=Shanxi:Toll&PROPERTYNAME=NAME,the_geom&FILTER=<Filter><PropertyIsEqualTo><PropertyName>KIND</PropertyName><Literal>8400</Literal></PropertyIsEqualTo></Filter>";
            //client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
            byte[] ss = client.DownloadData(new Uri(rUrl));
            string result = Encoding.UTF8.GetString(ss);
        }
        private void PostUrlData()
        {
            string rUrl = "http://10.14.1.34:8080/geoserver/wfs";
            //将字符串转换成字节数组, 注意Encoding.UTF8这样才能支持中文查询
            byte[] postBy = Encoding.UTF8.GetBytes(this.WfsData());
            //初始化WebClient
            WebClient webClient = new WebClient();
            //webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            webClient.Headers.Add("Content-Type", "application/xml;charset=UTF-8");           
            webClient.Headers.Add("ContentLength", postBy.Length.ToString());
            //上传数据,返回页面的字节数组
            byte[] responseData = webClient.UploadData(rUrl, "POST", postBy);
            // 将返回的将字节数组转换成字符串(HTML);
            string srcString = Encoding.UTF8.GetString(responseData);
        }
        private string WfsData()
        {
            var xmlPara = "<?xml version='1.0' encoding='UTF-8'?>"
            + "<wfs:GetFeature service='WFS' version='1.0.0' "
            + "xmlns:wfs='http://www.opengis.net/wfs' "
            + "xmlns:gml='http://www.opengis.net/gml' "
            + "xmlns:ogc='http://www.opengis.net/ogc' "
            + "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
            + "xsi:schemaLocation='http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd'>"
            + "<wfs:Query typeName='Shanxi:Toll' srsName='EPSG:4326'>"
            
            //属性查询
            + "<ogc:Filter xmlns:ogc='http://www.opengis.net/ogc'>"
            + "<ogc:And><ogc:PropertyIsLike wildCard='*' singleChar='.' escape='!'>"
            + "<ogc:PropertyName>NAME</ogc:PropertyName>"
            + "<ogc:Literal>*收费站*</ogc:Literal>"
            + "</ogc:PropertyIsLike></ogc:And></ogc:Filter>"
            //空间查询
            //+ "<ogc:Filter>"
            //+ "<ogc:Intersects>"
            //+ "<ogc:PropertyName>the_geom</ogc:PropertyName>"
            //+ " <gml:Point srsName='http://www.opengis.net/gml/srs/epsg.xml#4326'>"
            //+ "<gml:coordinates>111.08158415999999,38.98932696</gml:coordinates>"
            //+ "</gml:Point>"
            //+ "</ogc:Intersects>"
            //+ "</ogc:Filter>"
            //后部分节点
            + "</wfs:Query>"
            +"</wfs:GetFeature>";
            return xmlPara;
        }

[转载]C#信息采集工具实现 - HOT SUMMER - 博客园

mikel阅读(1032)

[转载]C#信息采集工具实现 – HOT SUMMER – 博客园.

简单C#信息采集工具实现

最近想整只爬虫玩玩,顺便熟悉下正则表达式。

 

开发环境 vs2008  SQL2000

实现方法如下

1.先抓取网页代码

2.通过正则匹配出你需要的内容

比如http://www.soso.com/q?w=%C4%E3%BA%C3&pg=1  页面中 搜索结果的标题跟连接地址。具体可以根据你的需要填写合适的地址跟正则。

3.把匹配出的内容保存到数据库中。对其中的数据可以根据需要自己进行处理

 

 

具体实现代码

1.读取网页的代码

public static string GetDataFromUrl(string url)

{

string str = string.Empty;

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

//设置Http头;

request.AllowAutoRedirect = true;

request.AllowWriteStreamBuffering = true;

request.Referer = “”;

request.Timeout = 10 * 1000;

//request.UserAgent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)”;

HttpWebResponse response = null;

try

{

response = (HttpWebResponse)request.GetResponse();

if (response.StatusCode == HttpStatusCode.OK)

{

//根据http应答头来判别编码

string Characterset = response.CharacterSet;

Encoding encode;

if (Characterset != “”)

{

if (Characterset == “ISO-8859-1”)

{

Characterset = “gb2312”;

}

encode = Encoding.GetEncoding(Characterset);

}

else

{

encode = Encoding.Default;

}

//声明一个内存流来贮存http应答流

Stream Receivestream = response.GetResponseStream();

MemoryStream mstream = new MemoryStream();

byte[] bf = new byte[255];

int count = Receivestream.Read(bf, 0, 255);

while (count > 0)

{

mstream.Write(bf, 0, count);

count = Receivestream.Read(bf, 0, 255);

}

Receivestream.Close();

mstream.Seek(0, SeekOrigin.Begin);

//从内存流里读取字符串这里涉及到了编码方案

StreamReader reader = new StreamReader(mstream, encode);

char[] buf = new char[1024];

count = reader.Read(buf, 0, 1024);

while (count > 0)

{

str += new string(buf, 0, 1024);

count = reader.Read(buf, 0, 1024);

 

}

reader.Close();

mstream.Close();

 

 

 

}

 

}

catch (Exception ex)

{

 

GetDataFromUrl(url);

 

}

finally

{

if (response != null)

response.Close();

}

 

return str;

}

2.正则匹配的代码

 

public static ArrayList GetString(string reg, string content)

{

Regex r = new Regex(reg, RegexOptions.Compiled);

MatchCollection matches = r.Matches(content);

 

ArrayList a = new ArrayList();

foreach (Match m in matches)

{

string[] arr = new string[10];

arr[0] = m.Groups[1].Value;

arr[1] = m.Groups[2].Value;

arr[2] = m.Groups[3].Value;

arr[3] = m.Groups[4].Value;

arr[4] = m.Groups[5].Value;

arr[5] = m.Groups[6].Value;

arr[6] = m.Groups[7].Value;

arr[7] = m.Groups[8].Value;

arr[8] = m.Groups[9].Value;

arr[9] = m.Groups[10].Value;

a.Add(arr);

}

return a;

}

 

3.如果抓取的页面很多 ,可以把多线程跟队列应用过来,提高抓取效率

 

Queue<int> numbers = new Queue<int>();

const int MaxCount = 5;//同时运行的最多线程数

private static object _lock = new object();

private void Test()

{

while (true)

{

int i = 0;

lock (_lock)

{

if (numbers.Count == 0)

{

flag = false;

return;

}

i = numbers.Dequeue();

}

f(i);

}

}

void Ssss()

{

for (int i = 1; i <= 100; i++)//处理的页面参数  从http://www.soso.com/q?w=你好&pg=1  到http://www.soso.com/q?w=你好&pg=100

{

numbers.Enqueue(i);

}

for (int i = 0; i < MaxCount; i++)

{

Thread thread = new Thread(new ThreadStart(Test));

thread.Name = “T” + i.ToString();

thread.Start();

}

}

private void f(int num)

{

string str = ClassLibrary1.Class1.GetDataFromUrl(“http://www.soso.com/q?w=%C4%E3%BA%C3&pg=”+num);

string reg = “<a href=/”([^/”]+?)/” [^>]+? target=/”_blank/”>([//s//S]+?)</a>”;

ArrayList a = ClassLibrary1.Class1.GetString(reg, str);

for (int i = 0; i < a.Count; i++)

{

string[] arr = (string[])a[i];

Result r = new Result();

r.Value1 = arr[0];

r.Value2 = ClassLibrary1.Class1.Html2Txt(arr[1]);

ResultManager.AddResult(r);

}

}

5.常用的一些正则表达式

*  0-多个

?  0-1个

+  1-多个

+? 尽可能少的匹配

*? 0次或多次,尽可能少

/w   等效于 [a-zA-Z_0-9]

/W   匹配非单词

/S   非空

/s   等效于 [ /f/n/r/t/v] 空格,制表  换页

.   匹配除了换行以为的任何字符

/d    数字

[^>]  除了>以为的字符

[/u4e00-/u9fa5] 汉字

 

6.代码只是实现了信息采集的主要功能,根据你自己的需要更换采集页面,跟合适的正则表达式后,可以根据你的需要自动进行采集,对采集到的数据,再根据你的需要自己进行处理。

7.数据库操作部分用的3层代码生成器连接地址  在 app.config中

 

 

 

 

如果你发现有什么不合理的,需要改进的地方,邮件联系328452421@qq.com(qq常年不在线,邮件联系)朱晓 。相互交流 谢谢

 

顺便问下 有家是新泰的没。

 

 

下载地址   http://download.csdn.net/source/3329838

[转载]html5+js+.Net的即时多人聊天 - flowbywind - 博客园

mikel阅读(1254)

[转载]html5+js+.Net的即时多人聊天 – flowbywind – 博客园.

今天看了下websocket的知识,了解到这是html5新增的特性,主要用于实时web的通信。之前客户端获取服务端的数据,是通过客户端发出请求, 服务端进行响应的模式,或者通过ajax每隔一段时间从后台发出请求,然后更新页面的信息,这种轮询的方式使得用户感觉页面是“实时响应”的,这样做虽然 简单但未免有些暴力,另外每次请求都会有TCP三次握手并且附带了http头信息,服务器表示压力很大,这就造成了性能上和延迟的问题。

后来的技术方案中又出现了长轮询、Comet、浏览器插件(flash)和Java等来实现服务器往客户端推送消息,但都有一些弊端。

WebSocket的出现,意味着另一种解决方案,其提供了基于TCP的双向的、全双工(发送数据的同时也能够接受数据,两者同步进行)的socket连 接。使用websocket,一旦服务端和客户端之间完成握手,信息就可以随意往来两端,而不用附件那些无用的http头信息,降低了带宽的占用,提高了 性能,降低了延时。但其缺陷是浏览器的支持不够,比如IE,到了IE10才支持。

现在就通过一个简单的例子来讲讲其运用过程,先上下效果图:

即时通讯2

项目的环境:.NET 4.5 +MVC 4 +JQuery+HTML5+VS2013+IE11

核心的实现过程,分以下几步:

1、websocket的创建、发送消息、接受消息、关闭

2、服务端的响应

下面针对上面的步骤,具体讲解下:

1、websocket的创建、发送消息、接受消息、关闭

websocket里包含的几个重要事件如下图: onopen onmessage onerror onclose;

image003

websocket的创建: 这时连接会发送到服务端后台代码,进行客户端和服务端的握手,如果握手成功,则会触发onopen事件,表示连接建立;如果连接失败,就会执行 onerror事件,随后执行onclose事件。当客户端获取到服务端推送的消息后,就会执行onmessage事件。

复制代码
    try{
        if ("WebSocket" in window) {   //判断浏览器是否支持WebSocket
            socket = new WebSocket("ws://localhost:13458/Socket/SocketHandler.ashx"); //socket连接服务端地址
        }
    }
    catch(ex)
    {
        log("您的浏览器不支持WebSocket,请切换到更高版本 或用chrome firefox");
        return;
    }

    //相应的socket事件 
    //socket建立连接
    socket.onopen = function () {
        //连接成功,将消息广播出去
        isSocketConnect = true;
        $("#btnWs").val("断开");
        sendSocketMessage(Event,"进入聊天室");
    }
    //socket得到服务端广播的消息
    socket.onmessage = function (event) {
        Log(event.data);
    }
    //socket连接关闭
    socket.onclose = function () {
        Log("socket closed!");
    }
    //socket连接出现错误
    socket.onerror = function (event) {
        Log("socket connect error");
    }
复制代码

当然客户端也可以往服务端发送消息,发送事件便是socket.send(data);data代表发送给服务端的数据:具体代码如下

复制代码
if (socket.readyState == WebSocket.OPEN) {
        if ($("#txtMsg").val() == "") {
            if (!msg) {
                return; //空文本不发送消息
            }
        }
        //如果未输入用户名,根据当前时间生成游客昵称
        if ($("#userName").val() == "") {
            var d = new Date();
            $("#userName").val("游客" + d.getMinutes() + "_" + d.getSeconds() + "_" + d.getMilliseconds());
        }
        if (!msg) {
            msg = "" + $("#userName").val() + ":" + "<div class='divChat'>" + $("#txtMsg").val() + "</div>";
        }
        else {
            msg = "" + $("#userName").val() + " " + msg;
        }
        socket.send(msg);
        $("#txtMsg").val(""); //清空已输入的数据
        $("#txtMsg").focus();
    }
复制代码

2、服务端的响应

这里我们添加一般处理程序来进行响应和推送客户端消息,其中有一点要处理的是 我们要实现即时多人聊天,就要把客户端发过来的消息广播到其他客户端,这里实现原理也很简单,就是把所有的连接用list存起来,然后遍历list集合, 将消息发送给各个客户端。具体实现代码如下:

复制代码
    public class SocketHandler : IHttpHandler
    {
        //用来存储当前所有连接的客户单 
        public static List<WebSocket> WebSocketList;
        public void ProcessRequest(HttpContext context)
        {
            if (WebSocketList == null)
            {
                WebSocketList = new List<WebSocket>();
            }
            HttpContext.Current.AcceptWebSocketRequest(async (contexts) =>
            {
                WebSocket socket = contexts.WebSocket;
                while (true)
                {
                    ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);
                    CancellationToken token;
                    WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, token);
                    //获取客户端发过来的消息
                    string clientMessage = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);

                    if (socket.State == WebSocketState.Open)
                    {
                        //重新组织消息,发送给客户端
                        clientMessage = DateTime.Now.ToString() + "           " + clientMessage;
                        buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(clientMessage));
                        //如果该客户端为初次加入,添加到用户列表;
                        if (!WebSocketList.Contains(socket))
                        {
                            WebSocketList.Add(socket);
                        }
                        //将消息进行广播
                        foreach (WebSocket item in WebSocketList)
                        {
                            await item.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                        }
                    }
                    if (socket.State == WebSocketState.CloseReceived)
                    {
                        //客户断开的时候,要从列表中移除
                        WebSocketList.Remove(socket);
                    }
                }
            });
        }
复制代码

参考资料:使用 HTML5 WebSocket 构建实时 Web 应用

源码下载

[转载]android多线程学习之handler - Jack Jia - 博客园

mikel阅读(937)

[转载]android多线程学习之handler – Jack Jia – 博客园.

在编写Android多线程程序时,进程间通信交换信息的一种方式就是使用handler,非常方便。

首先,在主线程里new一个Handler对象,并重写它的handleMessage(Message msg)方法,Message里有几个属性可以用来传递简单的int型参数,如what属性我们可以用来标记信息的种类(这在有N个线程N个 Message时非常有用,可以用老区分是哪个线程发送的什么消息),这时你可以定义几个static final int变量,用来给what分类;还有arg1和arg2两个属性可以用来存储int型消息内容,obj属性可以用来传递其他对象。

下面这个程序,我在新线程里做了一个循环,每隔一秒给主线程发送一个消息,每次传一个不同的int数据,在主线程里显示出来。

//thread_activity.java

package com.jiadebin.android;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class thread_activity extends Activity {
private final static String TAG = "THREAD_ACTIVITY"; //调试标记
public final static int MUTI_THREAD = 0; //用于what属性的标记变量
public final static int COMPLETE_THREAD = 1; //用于what属性的标记变量

private Button btn;
private TextView tv;
private Handler handler = new Handler(){

@Override
public void handleMessage(Message msg) { //重写处理消息的方法
// TODO Auto-generated method stub
// Log.v(TAG, ""+msg.what);
if(msg.what==MUTI_THREAD){
tv.setText(""+msg.arg1);
}
else if(msg.what==COMPLETE_THREAD){
tv.setText("complete");
btn.setText("complete");
}
super.handleMessage(msg);
}

};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.tv);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
start_thread();
btn.setText("running...");
}
});

}
private void start_thread() {
// TODO Auto-generated method stub
new Thread(){ //新线程

@Override
public void run() {
// TODO Auto-generated method stub
int i = 100;
int j = 0;
Message msg = new Message();
for(j=1;j&lt;i;j++){
Log.v(TAG, "J = "+j);
msg.what = MUTI_THREAD;
msg.arg1 = j;
handler.sendMessage(msg); //每次发送一个消息
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
msg.what = COMPLETE_THREAD;
handler.sendMessage(msg); //完成时,改变what属性

}

}.start();
}
}

//main.xml

<!--?xml version="1.0" encoding="utf-8"?-->

<button></button>

[转载]Android--多线程之Handler - 承香墨影 - 博客园

mikel阅读(785)

[转载]Android–多线程之Handler – 承香墨影 – 博客园.

前言

Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决Android应用中多线程的问题,在Android中不 允许Activity新启动的线程访问该Activity里的UI组件,这样会导致新启动的线程无法改变UI组件的属性值。但实际开发中,很多地方需要在 工作线程中改变UI组件的属性值,比如下载网络图片、动画等等。本篇博客主要介绍Handler是如何发送与处理线程上传递来的消息,并讲解 Message的几种传递数据的方式,最后均会以小Demo来演示。

 

Handler

Handler, 它直接继承自Object,一个Handler允许发送和处理Message或者Runnable对象,并且会关联到主线程的MessageQueue 中。每个Handler具有一个单独的线程,并且关联到一个消息队列的线程,就是说一个Handler有一个固有的消息队列。当实例化一个Handler 的时候,它就承载在一个线程和消息队列的线程,这个Handler可以把Message或Runnable压入到消息队列,并且从消息队列中取出 Message或Runnable,进而操作它们。

Handler主要有两个作用:

  • 在工作线程中发送消息。
  • 在UI线程中获取、处理消息。

上面介绍到Handler可以把一个Message对象或者Runnable对象压入到消息队列中,进而在UI线程中获取Message或者执行Runnable对象,所以Handler把压入消息队列有两大体系,Post和sendMessage:

  • Post:Post允许把一个Runnable对象入队到消息队列中。它的方法有:post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)。
  • sendMessage:sendMessage允许把一个包含消息数据的Message对象压入到消息队列中。它的方法 有:sendEmptyMessage(int)、sendMessage(Message)、 sendMessageAtTime(Message,long)、sendMessageDelayed(Message,long)。

从上面的各种方法可以看出,不管是post还是sendMessage都具有多种方法,它们可以设定Runnable对象和Message对象被入队到消息队列中,是立即执行还是延迟执行。

Post

对于Handler的Post方式来说,它会传递一个Runnable对象到消息队列中,在这个Runnable对象中,重写run()方法。一般在这个run()方法中写入需要在UI线程上的操作。

在Handler中,关于Post方式的方法有:

  • boolean post(Runnable r):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,立即执行。
  • boolean postAtTime(Runnable r,long uptimeMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,在特定的时间执行。
  • boolean postDelayed(Runnable r,long delayMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,延迟delayMills秒执行
  • void removeCallbacks(Runnable r):从消息队列中移除一个Runnable对象。

下面通过一个Demo,讲解如何通过Handler的post方式在新启动的线程中修改UI组件的属性:

复制代码
 1 package com.bgxt.datatimepickerdemo;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.os.Handler;
 6 import android.view.View;
 7 import android.widget.Button;
 8 import android.widget.TextView;
 9 
10 public class HandlerPostActivity1 extends Activity {
11     private Button btnMes1,btnMes2;
12     private TextView tvMessage;
13     // 声明一个Handler对象
14     private static Handler handler=new Handler();
15     
16     @Override
17     protected void onCreate(Bundle savedInstanceState) {
18         super.onCreate(savedInstanceState);
19         setContentView(R.layout.message_activity);        
20         
21         btnMes1=(Button)findViewById(R.id.btnMes1);
22         btnMes2=(Button)findViewById(R.id.btnMes2);
23         tvMessage=(TextView)findViewById(R.id.tvMessage);
24         btnMes1.setOnClickListener(new View.OnClickListener() {
25             
26             @Override
27             public void onClick(View v) {
28                 // 新启动一个子线程
29                 new Thread(new Runnable() {                    
30                     @Override
31                     public void run() {
32                         // tvMessage.setText("...");
33                         // 以上操作会报错,无法再子线程中访问UI组件,UI组件的属性必须在UI线程中访问
34                         // 使用post方式修改UI组件tvMessage的Text属性
35                         handler.post(new Runnable() {                    
36                             @Override
37                             public void run() {
38                                 tvMessage.setText("使用Handler.post在工作线程中发送一段执行到消息队列中,在主线程中执行。");                        
39                             }
40                         });                                
41                     }
42                 }).start();
43             }
44         });
45         
46         btnMes2.setOnClickListener(new View.OnClickListener() {
47             
48             @Override
49             public void onClick(View v) {
50                 new Thread(new Runnable() {                    
51                     @Override
52                     public void run() {
53                         // 使用postDelayed方式修改UI组件tvMessage的Text属性值
54                         // 并且延迟3S执行
55                         handler.postDelayed(new Runnable() {
56                             
57                             @Override
58                             public void run() {
59                                 tvMessage.setText("使用Handler.postDelayed在工作线程中发送一段执行到消息队列中,在主线程中延迟3S执行。");    
60                                 
61                             }
62                         }, 3000);                        
63                     }
64                 }).start();
65                 
66             }
67         });
68     }
69 }
复制代码

效果展示:

有一点值得注意的是,对于Post方式而言,它其中Runnable对象的run()方法的代码,均执行在UI线程上,所以对于这段代码而言, 不能执行在UI线程上的操作,一样无法使用post方式执行,比如说访问网络,下面提供一个例子,使用post方式从互联网上获取一张图片,并且显示在 ImageView中。

复制代码
 1 package com.bgxt.datatimepickerdemo;
 2 
 3 import org.apache.http.HttpResponse;
 4 import org.apache.http.client.HttpClient;
 5 import org.apache.http.client.methods.HttpGet;
 6 import org.apache.http.impl.client.DefaultHttpClient;
 7 import org.apache.http.util.EntityUtils;
 8 
 9 import android.app.Activity;
10 import android.app.ProgressDialog;
11 import android.graphics.Bitmap;
12 import android.graphics.BitmapFactory;
13 import android.os.Bundle;
14 import android.os.Handler;
15 import android.view.View;
16 import android.widget.Button;
17 import android.widget.ImageView;
18 
19 public class HandlerPostActivity2 extends Activity {
20     private Button btnDown;
21     private ImageView ivImage;
22     private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
23     private ProgressDialog dialog;
24     // 一个静态的Handler,Handler建议声明为静态的
25     private static  Handler handler=new Handler();
26     @Override
27     protected void onCreate(Bundle savedInstanceState) {
28         super.onCreate(savedInstanceState);
29         setContentView(R.layout.asynctask_activity);
30         
31         btnDown = (Button) findViewById(R.id.btnDown);
32         ivImage = (ImageView) findViewById(R.id.ivSinaImage);
33 
34         dialog = new ProgressDialog(this);
35         dialog.setTitle("提示");
36         dialog.setMessage("正在下载,请稍后...");
37         dialog.setCancelable(false);
38         
39         btnDown.setOnClickListener(new View.OnClickListener() {            
40             @Override
41             public void onClick(View v) {
42                 // 开启一个子线程,用于下载图片
43                 new Thread(new MyThread()).start();
44                 // 显示对话框
45                 dialog.show();
46             }
47         });
48     }
49     
50     public class MyThread implements Runnable {
51 
52         @Override
53         public void run() {
54             // 下载一个图片
55             HttpClient httpClient = new DefaultHttpClient();
56             HttpGet httpGet = new HttpGet(image_path);
57             HttpResponse httpResponse = null;
58             try {
59                 httpResponse = httpClient.execute(httpGet);
60                 if (httpResponse.getStatusLine().getStatusCode() == 200) {
61                     byte[] data = EntityUtils.toByteArray(httpResponse
62                             .getEntity());
63                     // 得到一个Bitmap对象,并且为了使其在post内部可以访问,必须声明为final
64                     final Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
65                     handler.post(new Runnable() {                        
66                         @Override
67                         public void run() {
68                             // 在Post中操作UI组件ImageView
69                             ivImage.setImageBitmap(bmp);
70                         }
71                     });
72                     // 隐藏对话框
73                     dialog.dismiss();
74                 }
75             } catch (Exception e) {
76                 e.printStackTrace();
77             }
78         }
79 
80     }
81 }
复制代码

效果展示:

 

Message

Handler如果使用sendMessage的方式把消息入队到消息队列中,需要传递一个Message对象,而在Handler中,需要重 写handleMessage()方法,用于获取工作线程传递过来的消息,此方法运行在UI线程上。下面先介绍一下Message。

Message是一个final类,所以不可被继承。Message封装了线程中传递的消息,如果对于一般的数据,Message提供了getData()和setData()方法来获取与设置数据,其中操作的数据是一个Bundle对 象,这个Bundle对象提供一系列的getXxx()和setXxx()方法用于传递基本数据类型的键值对,对于基本数据类型,使用起来很简单,这里不 再详细讲解。而对于复杂的数据类型,如一个对象的传递就要相对复杂一些。在Bundle中提供了两个方法,专门用来传递对象的,但是这两个方法也有相应的 限制,需要实现特定的接口,当然,一些Android自带的类,其实已经实现了这两个接口中的某一个,可以直接使用。方法如下:

  • putParcelable(String key,Parcelable value):需要传递的对象类实现Parcelable接口。
  • pubSerializable(String key,Serializable value):需要传递的对象类实现Serializable接口。

还有另外一种方式在Message中传递对象,那就是使用Message自带的obj属性传值,它是一个Object类型,所以可以传递任意类型的对象,Message自带的有如下几个属性:

  • int arg1:参数一,用于传递不复杂的数据,复杂数据使用setData()传递。
  • int arg2:参数二,用于传递不复杂的数据,复杂数据使用setData()传递。
  • Object obj:传递一个任意的对象。
  • int what:定义的消息码,一般用于设定消息的标志。

对于Message对象,一般并不推荐直接使用它的构造方法得到,而是建议通过使用Message.obtain()这个静态的方法或者 Handler.obtainMessage()获取。Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的, 才会使用构造方法实例化一个新Message,这样有利于消息资源的利用。并不需要担心消息池中的消息过多,它是有上限的,上限为10个。 Handler.obtainMessage()具有多个重载方法,如果查看源码,会发现其实Handler.obtainMessage()在内部也是 调用的Message.obtain()。

既然Message是在线程间传递消息,那么先以一个Demo讲解一下Message的使用,还是常规的从互联网上下载一张图片的Demo,下载后使用ImageView控件展示:

复制代码
 1 package com.bgxt.datatimepickerdemo;
 2 
 3 import org.apache.http.HttpResponse;
 4 import org.apache.http.client.HttpClient;
 5 import org.apache.http.client.methods.HttpGet;
 6 import org.apache.http.impl.client.DefaultHttpClient;
 7 import org.apache.http.util.EntityUtils;
 8 
 9 import android.app.Activity;
10 import android.app.ProgressDialog;
11 import android.graphics.Bitmap;
12 import android.graphics.BitmapFactory;
13 import android.os.Bundle;
14 import android.os.Handler;
15 import android.os.Message;
16 import android.view.View;
17 import android.widget.Button;
18 import android.widget.ImageView;
19 
20 public class HandlerMessageActivity1 extends Activity {
21     private Button btnDown;
22     private ImageView ivImage;
23     private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
24     private ProgressDialog dialog;
25     private static int IS_FINISH = 1;
26 
27     @Override
28     protected void onCreate(Bundle savedInstanceState) {
29         super.onCreate(savedInstanceState);
30         setContentView(R.layout.asynctask_activity);
31 
32         btnDown = (Button) findViewById(R.id.btnDown);
33         ivImage = (ImageView) findViewById(R.id.ivSinaImage);
34 
35         dialog = new ProgressDialog(this);
36         dialog.setTitle("提示信息");
37         dialog.setMessage("正在下载,请稍后...");
38         dialog.setCancelable(false);
39 
40         btnDown.setOnClickListener(new View.OnClickListener() {
41             @Override
42             public void onClick(View v) {
43                     new Thread(new MyThread()).start();
44                     dialog.show();
45             }
46         });
47     }
48 
49     private  Handler handler = new Handler() {
50         // 在Handler中获取消息,重写handleMessage()方法
51         @Override
52         public void handleMessage(Message msg) {            
53             // 判断消息码是否为1
54             if(msg.what==IS_FINISH){
55                 byte[] data=(byte[])msg.obj;
56                 Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
57                 ivImage.setImageBitmap(bmp);
58                 dialog.dismiss();
59             }
60         }
61     };
62 
63     public class MyThread implements Runnable {
64 
65         @Override
66         public void run() {
67             HttpClient httpClient = new DefaultHttpClient();
68             HttpGet httpGet = new HttpGet(image_path);
69             HttpResponse httpResponse = null;
70             try {
71                 httpResponse = httpClient.execute(httpGet);
72                 if (httpResponse.getStatusLine().getStatusCode() == 200) {
73                     byte[] data = EntityUtils.toByteArray(httpResponse
74                             .getEntity());
75                     // 获取一个Message对象,设置what为1
76                     Message msg = Message.obtain();
77                     msg.obj = data;
78                     msg.what = IS_FINISH;
79                     // 发送这个消息到消息队列中
80                     handler.sendMessage(msg);
81                 }
82             } catch (Exception e) {
83                 e.printStackTrace();
84             }
85         }
86     }
87 }
复制代码

展示效果:

Message.obtain()方法具有多个重载方法,大致可以分为为两类,一类是无需传递Handler对象,对于这类的方法,当填充好消 息后,需要调用Handler.sendMessage()方法来发送消息到消息队列中。第二类需要传递一个Handler对象,这类方法可以直接使用 Message.sendToTarget()方法发送消息到消息队列中,这是因为在Message对象中有一个私有的Handler类型的属性 Target,当时obtain方法传递进一个Handler对象的时候,会给Target属性赋值,当调用sendToTarget()方法的时候,实 际在它内部还是调用的Target.sendMessage()方法。

在Handler中,也定义了一些发送空消息的方法,如:sendEmptyMessage(int what)、sendEmptyMessageDelayed(int what,long delayMillis),看似这些方法没有使用Message就可以发送一个消息,但是如果查看源码就会发现,其实内部也是从 Message.obtain()方法中获取一个Message对象,然后给属性赋值,最后使用sendMessage()发送消息到消息队列中。

Handler中,与Message发送消息相关的方法有:

  • Message obtainMessage():获取一个Message对象。
  • boolean sendMessage():发送一个Message对象到消息队列中,并在UI线程取到消息后,立即执行。
  • boolean sendMessageDelayed():发送一个Message对象到消息队列中,在UI线程取到消息后,延迟执行。
  • boolean sendEmptyMessage(int what):发送一个空的Message对象到队列中,并在UI线程取到消息后,立即执行。
  • boolean sendEmptyMessageDelayed(int what,long delayMillis):发送一个空Message对象到消息队列中,在UI线程取到消息后,延迟执行。
  • void removeMessage():从消息队列中移除一个未响应的消息。

下面通过一个小Demo演示一下各种发送Message的方式:

复制代码
  1 package com.bgxt.datatimepickerdemo;
  2 
  3 import android.app.Activity;
  4 import android.os.Bundle;
  5 import android.os.Handler;
  6 import android.os.Message;
  7 import android.view.View;
  8 import android.widget.Button;
  9 import android.widget.TextView;
 10 
 11 public class HandlerMessageActivity2 extends Activity {
 12     private Button btn1, btn2, btn3, btn4,btn5;
 13     private static TextView tvMes;
 14     private static Handler handler = new Handler() {
 15         @Override
 16         public void handleMessage(android.os.Message msg) {
 17             if (msg.what == 3||msg.what==5) {
 18                 tvMes.setText("what=" + msg.what + ",这是一个空消息");
 19             } else {
 20                 tvMes.setText("what=" + msg.what + "," + msg.obj.toString());
 21             }
 22 
 23         };
 24     };
 25 
 26     @Override
 27     protected void onCreate(Bundle savedInstanceState) {
 28         // TODO Auto-generated method stub
 29         super.onCreate(savedInstanceState);
 30         setContentView(R.layout.message_activity2);
 31         tvMes = (TextView) findViewById(R.id.tvMes);
 32         btn1 = (Button) findViewById(R.id.btnMessage1);
 33         btn2 = (Button) findViewById(R.id.btnMessage2);
 34         btn3 = (Button) findViewById(R.id.btnMessage3);
 35         btn4 = (Button) findViewById(R.id.btnMessage4);
 36         btn5 = (Button) findViewById(R.id.btnMessage5);
 37 
 38         btn1.setOnClickListener(new View.OnClickListener() {
 39             @Override
 40             public void onClick(View v) {
 41                 // 使用Message.Obtain+Hander.sendMessage()发送消息
 42                 new Thread(new Runnable() {
 43                     @Override
 44                     public void run() {
 45                         Message msg = Message.obtain();
 46                         msg.what = 1;
 47                         msg.obj = "使用Message.Obtain+Hander.sendMessage()发送消息";
 48                         handler.sendMessage(msg);
 49                     }
 50                 }).start();
 51             }
 52         });
 53 
 54         btn2.setOnClickListener(new View.OnClickListener() {
 55 
 56             @Override
 57             public void onClick(View v) {
 58                 // 使用Message.sendToTarget发送消息
 59                 new Thread(new Runnable() {
 60                     @Override
 61                     public void run() {
 62                         Message msg = Message.obtain(handler);
 63                         msg.what = 2;
 64                         msg.obj = "使用Message.sendToTarget发送消息";
 65                         msg.sendToTarget();
 66                     }
 67                 }).start();
 68             }
 69         });
 70 
 71         btn3.setOnClickListener(new View.OnClickListener() {
 72             // 发送一个延迟消息
 73             @Override
 74             public void onClick(View v) {
 75                 new Thread(new Runnable() {
 76                     @Override
 77                     public void run() {
 78                         handler.sendEmptyMessage(3);
 79                     }
 80                 }).start();
 81             }
 82         });
 83 
 84         btn4.setOnClickListener(new View.OnClickListener() {
 85 
 86             @Override
 87             public void onClick(View v) {
 88                 new Thread(new Runnable() {
 89                     @Override
 90                     public void run() {
 91                         Message msg = Message.obtain();
 92                         msg.what =4;
 93                         msg.obj = "使用Message.Obtain+Hander.sendMessage()发送延迟消息";
 94                         handler.sendMessageDelayed(msg, 3000);
 95                     }
 96                 }).start();
 97             }
 98         });
 99         
100         btn5.setOnClickListener(new View.OnClickListener() {
101             // 发送一个延迟的空消息
102             @Override
103             public void onClick(View v) {
104                 new Thread(new Runnable() {
105                     @Override
106                     public void run() {
107                         handler.sendEmptyMessageDelayed(5, 3000);
108                     }
109                 }).start();
110             }
111         });
112     }
113 }
复制代码

效果展示:

源码下载

 

请支持原创,尊重原创,转载请注明出处。谢谢。

[转载]android ListView显示网络图片 - 忆冉 - 博客园

mikel阅读(870)

[转载]android ListView显示网络图片 – 忆冉 – 博客园.

研究了Android两个礼拜,稍微有了点眉目,开始正式帮公司开发应用的时候,发现ListView没有现成的显示网络图片的类或方法,网上查了查也没找到好的解决方法。心一横,自己研究吧,现在把我的解决办法和大家分享一下。

 

使用ListView的方法就不在此介绍了,google一下都是的。

 

第一步:分析api

使用ListView都需要使用Adapter,而api中的adapter都继承自BaseAdapter,所以第一反应就是自己实现一个继承自 BaseAdapter的adapter,但是BaseAdapter还是属于高度抽象的基类,所以实现起来还是还是有点难度的。此时作为初学者的你(当 然我也是啦)应该最熟悉的是SimpleAdapter了吧,而且SimpleAdapter也可以实现在ListView显示图片,但是就是不能显示网 络图片,只能显示在drawalbe中定义过的图片。所以就想,我是否可以改写SimpleAdapter的类,在它实例化drawalbe中图片时,我 替换成我自己 的显示网络图片的方法呢?答案是肯定的!(想获取Android的源码,可以查看我的另一篇文章http://hulefei29.iteye.com/blog/615016

 

第二步:源码分析

经过查看源码SimpleAdapter发现,显示每个item视图都是通过调用(int position, View convertView, ViewGroup parent)方法来实现的

Java代码 复制代码 收藏代码
  1. /**  
  2.      * @see Android.widget.Adapter#getView(int, View, ViewGroup)  
  3.      */  
  4.     public View getView(int position, View convertView, ViewGroup parent) {   
  5.         return createViewFromResource(position, convertView, parent, mResource);   
  6.     }  
/**
     * @see android.widget.Adapter#getView(int, View, ViewGroup)
     */
    public View getView(int position, View convertView, ViewGroup parent) {
        return createViewFromResource(position, convertView, parent, mResource);
    }

 

在getView(int position, View convertView, ViewGroup parent)中又调用了SimpleAdapter的私有方法createViewFromResource来组装View,在 createViewFromResource中对SimpleAdapter的参数String[] from

和int[] to进行了组装,代码如下:

Java代码 复制代码 收藏代码
  1. private View createViewFromResource(int position, View convertView,   
  2.             ViewGroup parent, int resource) {   
  3.         View v;   
  4.         if (convertView == null) {   
  5.             v = mInflater.inflate(resource, parent, false);   
  6.   
  7.             final int[] to = mTo;   
  8.             final int count = to.length;   
  9.             final View[] holder = new View[count];   
  10.   
  11.             for (int i = 0; i < count; i++) {   
  12.                 holder[i] = v.findViewById(to[i]);   
  13.             }   
  14.   
  15.             v.setTag(holder);   
  16.         } else {   
  17.             v = convertView;   
  18.         }   
  19.   
  20.         bindView(position, v);   
  21.   
  22.         return v;   
  23.     }  
private View createViewFromResource(int position, View convertView,
            ViewGroup parent, int resource) {
        View v;
        if (convertView == null) {
            v = mInflater.inflate(resource, parent, false);

            final int[] to = mTo;
            final int count = to.length;
            final View[] holder = new View[count];

            for (int i = 0; i < count; i++) {
                holder[i] = v.findViewById(to[i]);
            }

            v.setTag(holder);
        } else {
            v = convertView;
        }

        bindView(position, v);

        return v;
    }

 

在createViewFromResource方法中又有一个bindView(position, v)方法对item中的各个View进行了组装,bindView(position, v)代码如下:

Java代码 复制代码 收藏代码
  1. private void bindView(int position, View view) {   
  2.         final Map dataSet = mData.get(position);   
  3.         if (dataSet == null) {   
  4.             return;   
  5.         }   
  6.   
  7.         final ViewBinder binder = mViewBinder;   
  8.         final View[] holder = (View[]) view.getTag();   
  9.         final String[] from = mFrom;   
  10.         final int[] to = mTo;   
  11.         final int count = to.length;   
  12.   
  13.         for (int i = 0; i < count; i++) {   
  14.             final View v = holder[i];   
  15.             if (v != null) {   
  16.                 final Object data = dataSet.get(from[i]);   
  17.                 String text = data == null ? “” : data.toString();   
  18.                 if (text == null) {   
  19.                     text = “”;   
  20.                 }   
  21.   
  22.                 boolean bound = false;   
  23.                 if (binder != null) {   
  24.                     bound = binder.setViewValue(v, data, text);   
  25.                 }   
  26.   
  27.                 if (!bound) {   
  28.                     if (v instanceof Checkable) {   
  29.                         if (data instanceof Boolean) {   
  30.                             ((Checkable) v).setChecked((Boolean) data);   
  31.                         } else {   
  32.                             throw new IllegalStateException(v.getClass().getName() +   
  33.                                     ” should be bound to a Boolean, not a “ + data.getClass());   
  34.                         }   
  35.                     } else if (v instanceof TextView) {   
  36.                         // Note: keep the instanceof TextView check at the bottom of these   
  37.                         // ifs since a lot of views are TextViews (e.g. CheckBoxes).   
  38.                         setViewText((TextView) v, text);   
  39.                     } else if (v instanceof ImageView) {   
  40.                                if (data instanceof Integer) {   
  41.                             setViewImage((ImageView) v, (Integer) data);                               
  42.                         } else {   
  43.                             setViewImage((ImageView) v, text);   
  44.                         }   
  45.                     } else {   
  46.                         throw new IllegalStateException(v.getClass().getName() + ” is not a “ +   
  47.                                 ” view that can be bounds by this SimpleAdapter”);   
  48.                     }   
  49.                 }   
  50.             }   
  51.         }   
  52.     }  
private void bindView(int position, View view) {
        final Map dataSet = mData.get(position);
        if (dataSet == null) {
            return;
        }

        final ViewBinder binder = mViewBinder;
        final View[] holder = (View[]) view.getTag();
        final String[] from = mFrom;
        final int[] to = mTo;
        final int count = to.length;

        for (int i = 0; i < count; i++) {
            final View v = holder[i];
            if (v != null) {
                final Object data = dataSet.get(from[i]);
                String text = data == null ? "" : data.toString();
                if (text == null) {
                    text = "";
                }

                boolean bound = false;
                if (binder != null) {
                    bound = binder.setViewValue(v, data, text);
                }

                if (!bound) {
                    if (v instanceof Checkable) {
                        if (data instanceof Boolean) {
                            ((Checkable) v).setChecked((Boolean) data);
                        } else {
                            throw new IllegalStateException(v.getClass().getName() +
                                    " should be bound to a Boolean, not a " + data.getClass());
                        }
                    } else if (v instanceof TextView) {
                        // Note: keep the instanceof TextView check at the bottom of these
                        // ifs since a lot of views are TextViews (e.g. CheckBoxes).
                        setViewText((TextView) v, text);
                    } else if (v instanceof ImageView) {
                               if (data instanceof Integer) {
                            setViewImage((ImageView) v, (Integer) data);                            
                        } else {
                            setViewImage((ImageView) v, text);
                        }
                    } else {
                        throw new IllegalStateException(v.getClass().getName() + " is not a " +
                                " view that can be bounds by this SimpleAdapter");
                    }
                }
            }
        }
    }

终于找到了对ViewImage进行组装的代码了“else if (v instanceof ImageView)”,我们留成功之差一步之遥了!

看到上面茫茫的代码是不是已经头晕了呢,其实以上的都是源代码,我没有做过任何的修改,也不需要修改,只是需要把它从SimpleAdapter中 取出来进行覆盖,以为他们私有方法,不能用super调用!到最后终于到你出手的时候了,你需要重写SimpleAdapter类中的 setViewText方法,SimpleAdapter对setViewText进行了重载,有两个方法,代码如下:

Java代码 复制代码 收藏代码
  1. public void setViewImage(ImageView v, int value) {   
  2.     v.setImageResource(value);   
  3. }   
  4.   
  5.   
  6. public void setViewImage(ImageView v, String value) {   
  7.     try {   
  8.         v.setImageResource(Integer.parseInt(value));   
  9.     } catch (NumberFormatException nfe) {   
  10.         v.setImageURI(Uri.parse(value));   
  11.     }   
  12. }  
    public void setViewImage(ImageView v, int value) {
        v.setImageResource(value);
    }

    public void setViewImage(ImageView v, String value) {
        try {
            v.setImageResource(Integer.parseInt(value));
        } catch (NumberFormatException nfe) {
            v.setImageURI(Uri.parse(value));
        }
    }

setViewImage(ImageView v, int value) 你应该一看就熟悉了吧,int就是R中的索引值,但是你还看到SimpleAdapter居然还有一个setViewImage(ImageView v, String value)可以接受String的方法,在往下看就是知道了,如果不是索引,ImageView 也可以接受Uri的值来设置图片,切忌Uri不是Url,所以我们只需要改写一下这个方法就ok了,代码如下:

Java代码 复制代码 收藏代码
  1. public void setViewImage(ImageView v, String value) {   
  2.         Bitmap bitmap = WebImageBuilder.returnBitMap(value);   
  3.         ((ImageView) v).setImageBitmap(bitmap);   
  4.     }  
public void setViewImage(ImageView v, String value) {
    	Bitmap bitmap = WebImageBuilder.returnBitMap(value);
    	((ImageView) v).setImageBitmap(bitmap);
    }

我们用Bitmap 来对ImageView进行设置,WebImageBuilder.returnBitMap是我自己实现的获取网络图片的方法,当然google下都是 的,在我下面的源码中也有,在这里就不多说了!说到这,我的解释也就说完了,希望可以给你帮助!如果你是不愿意跟着别人思路走的人,希望自己研究出来的 话,那最后我也拿我的源码贴上,对有些朋友来说获取直接看源码,理解的更快吧!

 

最后强调一下,本文为胡乐费的原创,如果要转载的话,希望注明出处!

本文转自: http://hulefei29.iteye.com/blog/616262

[转载]android ListView 重写 SimpleAdapter 显示图片 异步加载及文字处理 - freexiaoyu - 博客园

mikel阅读(928)

[转载]android ListView 重写 SimpleAdapter 显示图片 异步加载及文字处理 – freexiaoyu – 博客园.

simpleAdapter=new SimpleAdapter(context, mData, R.layout.goods_info, 
                    new String[]{"name","small_pic","price"}, 
                    new int[]{R.id.goods_name,R.id.goodsimg,R.id.goods_price}){
                        @Override
                        public void setViewImage(final ImageView v,final  String value) {
                            // TODO Auto-generated method stub
                            if(v.getId()==R.id.goodsimg)
                            {
                                 new Thread(new Runnable() {
                                     @Override
                                     public void run() {
                                         try{
                                             //通过图片Url返回Bitmap
                                             final Bitmap img= StreamTool.returnBitMap(value); 
                                             handler.post(new Runnable() {
                                                 @Override
                                                 public void run() {
                                                     if(img!=null){
                                                     v.setImageBitmap(img);}
                                                 }
                                             });  
                                             }
                                             catch(Exception e){
                                                 e.printStackTrace();
                                             }
                                         
                                     }
                                 }).start();
                            }
                            else{super.setViewImage(v, value);}
                 }
                
            };

这样就能获得图片并显示,但是这样有个小问题就是当用户滚动过快的时候图片显示的就不对,因为图片异步加载,要过一会才能显示对应产品名称的图片

[转载]电子商务项目深度解析前言篇及个人技术经验(需求,架构,模块设计,详细技术难点) - koolbing - 博客园

mikel阅读(2067)

[转载]电子商务项目深度解析前言篇及个人技术经验(需求,架构,模块设计,详细技术难点) – koolbing – 博客园.

本人计算机专业出身,目前在一家公司做技术负责人。从事技术工作已经十几年了,然而笔者一向都没有写日志的习惯,一方面是因为处于不断的忙碌之中没有太多时间也没有这个意识,另一方总感觉自己接触的技术比较简单,没有分享的冲动。

 

不过十几年来一直有个心愿,想把自己在这十多年的技术经历及所见所感付诸笔端,也算是对自己的一份总结,即使哪一天再也不从事具体的开发工作了,也可以看到自己曾经的足迹。

 

仔细想来,从我的经历来看,我使用的技术十分庞杂,总结起来自己也被吓了一跳,这些技术部分精通,大部分基本上都熟练状态,也就是说拿来略微回忆一下,就可以用。

其中包括,

一,c/c++, asp com+, php(LAMP XOOPS), java(SSH),以及现在的.net技术,我称为技术流派。

asp com+/C++Com组件技术 在2002年全国比较流行的某B2B行业网站中使用

php 使用ecshop为几个公司进行过个性化的二次开发

ssh (struts2+hiberrnate+spring+ognl) 开发过电子商务网站

.net  windows/webForm/mvc3.0 开发过 招聘网站,数据采集系统,救援系统,电子商务网站,团购网站,视频网站,音乐网站,搜索引擎网站, 医药网 某天猫淘宝接口集成与开发

java Adroid 开发电子商务系统手机客户端

 

二,开发工具及环境

 

三,数据库系统接触的有: access , mySQL / SQLServer /oracle / db2

 

四。设计工具: Visio, PD (powerDesigner), RSA(IBM rational software architect), PhotoShop, Dreamweaver (网页三剑客)vs2012,

 

管理工具: project, vss/svn, maven, msf

 

 

在开发过程中,以b/s架构为核心,其余为辅助软件及应用。

当然也可以这样理解,在现有国内环境下,在企业及个人生存压迫下,十几年来我从未放弃过学习的步伐,这使得一个悲悴的技术人员几乎 被迫成了全能工具。当然也使我面对当前任何技术都不会感觉困难,不管多么复杂的软件,在略微了解之后,都会从心里发出不过如此的窃喜。这也可能算是会当凌绝顶,一览众山小吧。

 

言归正传,本人曾深入研究电子商务框架及源代码有:hishop(.net), ecshop(php + smarty), 商派shopex(php),  JEShop( struts2+hiberrnate+spring+ognl )并在上述框架基础上进行过多家客户电子商务的二次开发。

 

不过本系统文章以笔者目前从事的电子商务技术开发为核心,将融入我工作以来接触到及所学到的所有的技术,当然这里不是给出的通用的标准,只是参考了大量的现有电子商务框架与技术,结合我们自己的实际情况的开发过程,我暂时给它起名为《电子商务项目深度解析》吧。

 

注意本系统是已经上线多年的成熟系统,目前主系统和各子系统运行良好,不是不存在的系统,是切切实实为企业创造价值的系统。注:本文介绍的电子商务系统主系统及各子系统,已经获得了软件著作权及各项专利。

 

其中将包括如下几大部分:

一,电子商务网站需求白皮书

此部分,主要介绍电子商务网站的总需求,及要主要专业术语的解释,具体会有大量篇幅介绍(大概30页,将以大量图表的形式来展开,这样会比较轻松理解)

包括:

1电子商务系统需求概览

电子商务网站前台需求:

系统管理需求:

 

二,电子商务网站总架构

此部分,包括以一个b/s为核心的电子商务系统为例,分析要涉及的所有子系统并与之整合  电子商务前台展示系统, 后台管理系统,数据采集与比价系统,电子商务手机客户端系统         CRM CTI与管理平台整合系统  淘宝数据同步与供应商查询系统  电商平台整合系统  会员系统与Discuz, UCHome整合系统作到单点登录

 

 

三,电子商务网站中所使用到的技术

 

四,电子商务主网站经典模块解析

此处没有过多的理论解释,只有根据实践进行的总结及设计描述,详细类结构,并包括一些设计模式在其中的应用。

3.1 会员系统

3.2 产品展示系统

3.3 购物车系统设计

3.4 集成登录接口设计

3.5 支付接口设计(几乎支持国内所有支付接口)

3.6 订单系统

3.7 定时任务系统

五,其它,以后再补充

 

[转载]Weibo用户地图 - JK_Rush - 博客园

mikel阅读(910)

[转载]Weibo用户地图 – JK_Rush – 博客园.

1.1.1 摘要

现在,许多应用都提供地理位置定位的功能,只要 用户开放他们的位置信息就可以实现定位了,今天我们将创建一个基于Google 地图的微博用户地图,这里我们将通过Weibo API获取微博用户的地理信息,然后使用Google地理位置服务将用户的地理信息转换为相应的地理坐标,最后,根据地理坐标加载到Google地图中显 示。

目录

1.1.2 正文

Index页面

首先,我们定义程序的Index页面,它用于加载显示Google地图,具体实现如下:

<!-- Weibo user map -->
<div id="map"></div>
<div class="weibo">
    <div class="inside"></div>
</div>
<div class="posts"></div>
<div class="get">
    <input type="hidden" value="优等生杜小明" />
    <input type="hidden" value="杨幂" />
    <input type="hidden" value="思想汇聚人生" />    
    <input type="hidden" value="KevinOriste" />            
    <input type="hidden" value="韩寒" />
    <input type="hidden" value="复古老照片" />    
    <input type="hidden" value="独立检察官2011" />    
    <input type="hidden" value="顾扯淡" />
    <input type="hidden" value="李开复"/>
</div>

上面,第一个div(map)用来加载显示Google 地图,第二个div(weibo)用来显示微博用户的头像、描述、用户名和个人信息,第三个div(posts)用来加载显示相应用户最近发的微博信息, 最后,一个div(get)用来存放微博用户名,我们的程序将根据这些用户名来获取相应的微博数据。

JavaScript实现

接下来,我们通过JQuery插件方式实现微博用户地图插件,我们定义了三个方法别是:weiboMap(),weiboMap.size()和weiboMap.init(),具体定义如下:

// Weibo user map plugin.
(function($) {
    $.fn.weiboMap = function(options) {
        // Your code here.
    };

    $.fn.weiboMap.size = function() {
        // Your code here.
    };

    $.fn.weiboMap.init = function() {
        // Your code here.
    };
})(jQuery);

weiboMap()方法通过调用微博API获取微博数据,然后将返回数据加载显到Index页面中;weiboMap.size()获取当前窗口 的大小,用来设置Google地图的初始大小;weiboMap.init()初始化Google地图,设置地图的zoom,地图中心位置(这里以北京为 中心),地图大小和地图类型。

上面,我们只给出了三个方法的定义,但还没有给出具体的实现,接下来让我们实现上面的方法吧!

// Gets the size of window .
$.fn.weiboMap.size = function() {
    var w = $(window).width(),
            h = $(window).height();
    return {
        width: w,
        height: h
    };
}

上面,我们实现了weiboMap.size()方法,它获取当前窗口的大小,然后返回一个包含长和宽属性的对象。

// Initalizes the google map
$.fn.weiboMap.init = function() {

    // Sets the size of map.
    var size = $.fn.weiboMap.size();
    $('#map').css({
        width: size.width,
        height: size.height
    });

    // Creates a google map instance.
    map = new google.maps.Map(document.getElementById('map'), $.fn.weiboMap.defaults.data);

    // Creates a geo coder instance.
    geocoder = new google.maps.Geocoder();
}

weibomap0

图1 Google地图

我们通过方法weiboMap.init()初始化Google地图,首先,我们设置了map div的长和宽,然后创建了Google地图和地理编码对象。

在创建新的地图实例时,我们需要在网页中指定一个 div 元素作为地图的容器;这里我们通过getElementById ()方法获取map元素。

构造函数:Map(mapDiv:Node, opts?:MapOptions)

说明:第一个参数设置地图的HTLM容器,第二参数可选,用于设置Google地图的zoom,显示位置,地图大小和地图类型等(具体请参考这里)。

上面,我们实现了方法weiboMap.size()和weiboMap.init(),接下来我们继续实现方法weiboMap()。

由于weiboMap()负责调用微博API获取微博数据,然后加载显示到Google地图上面,所以这里就涉及到两个功能的实现:调用微博API和Google地图地理定位。

首先,我们定义方法getUsers()获取在Index.html页面中设置的微博用户名,然后根据这些用户名获取相应的用户信息和微博信息。

// Gets the list of weibo screen name
// from the .get div.
function getUsers() {
    var arr = new Array();
    $('.get').find('input').each(function(i) {
        var $element = $(this);
        arr[i] = $element.val();
    });
    return arr;
}

上面,我们通过find()方法获取get元素中的用户名,然后储存在数组中并且返回该数组,接下来,我们实现show()方法,它根据微博用户名 调用微博API获取用户的基本信息和微博信息,由于用户的基本信息包含了地理信息,我们通过Google的地理编码服务将用户的地理信息转换为地理坐标, 例如:根据北京转换为相应的经纬度北纬39.90,东经116.41,具体实现如下:

// Get weibo user show and binding data
// with google map.
function show() {

    // Gets the weibo user screen name.
    var users = getUsers();
    for (var i = users.length - 1; i >= 0; i--) {

        // Invokes the weibo api to get data.
        $.getJSONP({
            url: opts.url,
            timeout: 30000,
            data: {
                source: opts.appKey,
                access_token: opts.accessToken,
                screen_name: users[i]
            },
            error: function(xhr, status, e) {
                console.log(e);
            },
            complete: function() {

            },
            success: function(json) {
                if (json.data.error) {
                    // log the error.
                    return;
                }

                var arr = new Array(),
                            img = json.data.profile_image_url,
                            screen_name = json.data.screen_name;

                // Initalizes the geo coder instance.    
                geocoder.geocode({
                    address: json.data.location
                }, function(response, status) {
                    if (status == google.maps.GeocoderStatus.OK) {

                        // Sets latitude and longitude by location name.
                        var x = response[0].geometry.location.lat(),
                                    y = response[0].geometry.location.lng(),
                                    blogUrl,
                                marker = new google.maps.Marker({
                                    icon: img,
                                    map: map,
                                    title: screen_name,
                                    animation: google.maps.Animation.DROP,
                                    position: new google.maps.LatLng(x, y)
                                });

                        // Creates user information.
                        blogUrl = json.data.url !== '' ? json.data.url : 'http://www.weibo.com/u/' + json.data.id;
                        arr.push('<div class="item">');
                        arr.push('<p class="img"><a href="#" class="open" rel="' + screen_name + '"><img src="' + img + '" alt="" /></a></p>');
                        arr.push('<div class="entry">');
                        arr.push('<a href="#" class="open title" rel="' + screen_name + '">' + json.data.name + '</a>');
                        arr.push('<p class="description">' + json.data.description + '</p>');
                        arr.push('<p class="url"><a href="' + blogUrl + '" target="_blank">' + blogUrl + '</a></p>');
                        arr.push('<p class="count">粉丝: ' + json.data.followers_count + ', 关注: ' + json.data.friends_count + '</p>');
                        arr.push('</div>');
                        arr.push('</div>');
                        var html = arr.join('');
                        arr = [];
                        $('.weibo').find('.inside').append(html);

                        // Clicks the user image showing relative user's weibo.
                        google.maps.event.addListener(marker, 'click', function() {
                            open(this.title);
                        });
                    }

                });
            }
        });
    };

}

上面,我们通过getJSONP()方法调用微博API获取微博用户数据,如名称,描述,地理位置和头像路径等,然后,我们使用Google的地理 编码服务将用户地理位置信息转换为具体的地理坐标,最后,我们将微博用户的头像加载到地图的相应坐标上并且添加用户的名称和描述信息。

接着,我们打开Chrome的开发者工具,在Network中,查看到getJSONP()方法通过向微博的users/show接口发送请求来获取微博数据。

weibomap2

图2 Ajax请求

当请求成功微博将返回JSON格式的数据,数据的结构如下:

weibomap3

图3 微博JSON数据

前面,我们取得了微博数据,我们根据用户的location值获取相应的地理坐标值,这里我们使用Google的地理编码服务可以将用户地理位置信息(location)转换为具体的地理坐标,具体实现如下:

// Sets latitude and longitude by location name.
var x = response[0].geometry.location.lat(),
        y = response[0].geometry.location.lng(),
        blogUrl,
        marker = new google.maps.Marker({
        icon: img,
        map: map,
        title: screen_name,
        animation: google.maps.Animation.DROP,
        position: new google.maps.LatLng(x, y)
    });

我们根据用户的微博头像,名称和地理坐标创建marker实例,它用于在地图上显示对应的微博用户的位置,然后,我们把用户的名称,描述,粉丝和关注数量加载到weibo div中。

weibomap4

图4 微博用户地图

上面,我们实现了根据微博用户的位置信息进行地理定位,这样我们可以在地图上查看到每个微博用户的地理位置了,在地图的下方,我们给出了微博用户的描述信息。

现在,我们已经实现了微博用户地图的功能了,随着,我们查询用户增加,但我们显示用户信息的空间是有限,难道我们要用整个窗口来显示用户的信息吗?

其实,我们可以通过滚动方式来查看微博用户的信息,具体实现如下:

// Gets mouse Y coordinate.
function getYCoordinate(e) {
    var y = e.pageY;
    return y;
}

// Checks move size.
function checkYCoordinate(y) {
    var all = $('.weibo').height(),
                inside = $('.weibo').find('.inside').height();
    // The max move size |all - inside|.    
    if (y < (all - inside)) {
        y = all - inside;
    } else if (y > 0) {
        y = 0;
    }
    return y;
}

// Updates inside top css.
function update(e) {
    var y = getYCoordinate(e),
                movey = y - my,

    // Changes Y coordinate.
                top = ey + movey,
            check = checkYCoordinate(top);
    console.log(top, check);
    $('.weibo').find('.inside').css({
        top: check + 'px'
    });
}

init();

function init() {
    $('.weibo').find('.inside').bind({
        mousedown: function(e) {
            e.preventDefault();
            mouseDown = true;
            var mouseY = getYCoordinate(e),
            // Gets element coordinate.
                    element = $(this).position();

            // Gets Y coordinate move.
            my = mouseY;
            ey = element.top;
            update(e);
        },
        mousemove: function(e) {
            if (mouseDown)
                update(e);
            return false;
        },
        mouseup: function() {
            if (mouseDown)
                mouseDown = false;
            return false;
        },
        mouseleave: function() {
            if (mouseDown)
                mouseDown = false;
            return false;
        }
    });
}

用户通过垂直拖拉weibo div来实现上下查看微博用户信息,首先init()方法绑定了mousedown,mousemove,mouseup和mouseleave事件,当 用户点击weibo div区域时,调用getYCoordinate()方法获取鼠标当前的Y坐标,当用户拖动鼠标时,调用update()方法更新inside div的top属性。

CSS样式

现在,我们可以通过垂直拖拉查看微博用户的信息,接下来,我们添加CSS效果调整一下界面布局,具体实现如下:

@import url("reset.css");

/* ------ layout
-----------------------------------------------*/

html, body {
margin:0;
padding:0;
}

body {
font-family:Arial, Helvetica, sans-serif;
font-size:12px;
color:#333;
line-height:18px;
}

#map {
float:left;
}

.weibo {
position:fixed;
left:0;
bottom:0;
background:#000;
background:rgba(0, 0, 0, .7);
width:100%;
height:180px;
color:#fff;
overflow:hidden;
}

.weibo .inside {
position:absolute;
top:0;
left:0;
cursor:n-resize;
}

.weibo .item {
float:left;
width:280px;
padding:20px;
}

.weibo .item .img {
float:left;
width:48px;
}

.weibo .img img {
-moz-box-shadow:0 0 5px #000;
-webkit-box-shadow:0 0 5px #000;
box-shadow:0 0 5px #000;
}

.weibo .item .entry {
float:right;
width:215px;
height:140px;
color:#eee;
font-size:11px;
position:relative;
}

.weibo .item .count {
position:absolute;
left:0;
bottom:-10px;
font-size:10px;
text-transform:uppercase;
}

.weibo .item .title {
font-size:13px;
font-weight:bold;
color:#fff;
}

.weibo .item .url a {
text-decoration:underline;
}

.weibo .item p {
margin-bottom:5px;
}

.posts {
display:none;
position:absolute;
left:50%;
margin-left:-310px;
width:580px;
bottom:180px;
background:#fff;
color:#fff;
background:#000;
background:rgba(0, 0, 0, .7);
padding:20px;
}

.posts .post {
float:left;
clear:both;
width:100%;
margin-bottom:20px;
font-size:12px;
font-weight:bold;
}

/* ------ anchors
-----------------------------------------------*/

a {
text-decoration:none;
color:#fff;
}

weibomap1

weibomap5

图5 微博用户地图

上面,实现了微博用户地图,我们可以在Google地图上查看到微博用户对应的地图位置,在下面给出了每个用户的描述信息。

1.1.3 总结

我们实现了微博用户地图程序,首先将Google地图加载程序当中,然后,我们通过ajax请求调用微博API,获取微博用户的基本信息,当成功返 回JSON数据时,从中获取用户的地址信息,然后通过Google的地理编码服务将地址信息转换为地理坐标,这样我们就可以定位每个微博用户的地理位置 了,最后,通过marker把每个用户的定位到Google地图上显示出来。

参考

Demo

[转载]Android 设置启动界面-博客园找找看

mikel阅读(979)

[转载]Android 设置启动界面-博客园找找看.

从网上搜集了一堆的Android代码,比如Android的Login程序和 Android的Helloworld程序,但是却总不能正确运行一个正确的程序,郁闷了很久,终于在一次一次的测试后成功的在Android模拟器中运 行了自建项目的程序。总结程序启动界面的设置经验如下:

在 MyEclipse建立的Android项目中,找到AndroidManifest.xml文件,双击打开。

设置程序运行后首先启动Login界面的AndroidManifest.xml文件代码如下:

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android
package=”com.gp.acitivity”
android:versionCode=”1″
android:versionName=”1.0″ >
<!– 设置模拟器中运行的Android SDK程序版本 –>
<uses-sdk android:minSdkVersion=”8″ android:targetSdkVersion=”18″ />
<!– 获取网络操作权限 –>
<uses-permission android:name=”android.permission.CHANGE_NEWWORK_STATE” />
<!– Android软件运行设置 –>
<application
android:allowBackup=”true”
android:icon=”@drawable/ic_launcher”
android:label=”@string/app_name”
android:theme=”@style/AppTheme” >
<!– 启动网上搜集整理的Login界面设置 –>
<activity
android:name=”com.gp.acitivity.LoginActivity”>
<!– 设置最先启动的程序,要启动哪个Activity就把下面的代码复制到指定的位置 –>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
<!– 启动网上搜集整理的Helloworld界面设置 –>
<activity
android:name=”com.gp.acitivity.HellowoldActivity”>
</activity>
</application>
</manifest>

设置程序运行后首先启动HelloWorld界面的AndroidManifest.xml文件代码如下:

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android
package=”com.gp.acitivity”
android:versionCode=”1″
android:versionName=”1.0″ >
<!– 设置模拟器中运行的Android SDK程序版本 –>
<uses-sdk android:minSdkVersion=”8″ android:targetSdkVersion=”18″ />
<!– 获取网络操作权限 –>
<uses-permission android:name=”android.permission.CHANGE_NEWWORK_STATE” />
<!– Android软件运行设置 –>
<application
android:allowBackup=”true”
android:icon=”@drawable/ic_launcher”
android:label=”@string/app_name”
android:theme=”@style/AppTheme” >
<!– 启动网上搜集整理的Login界面设置 –>
<activity
android:name=”com.gp.acitivity.LoginActivity”>
</activity>
<!– 启动网上搜集整理的Helloworld界面设置 –>
<activity
android:name=”com.gp.acitivity.HellowoldActivity”>
<!– 设置最先启动的程序,要启动哪个Activity就把下面的代码复制到指定的位置 –>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
</application>
</manifest>

系统Android模拟器界面截图

启动Login界面截图

启动HelloWorld界面截图