您的位置:首页 > 理论基础 > 计算机网络

Android仿人人客户端(v5.7.1)——网络模块处理的架构

2013-12-15 18:53 781 查看


Android仿人人客户端(v5.7.1)——网络模块处理的架构

分类: 仿人人Android客户端(v5.7.1)2013-03-28
17:55 7407人阅读 评论(27) 收藏 举报

网络处理ANDROID仿人人网络模块架构类图

转载请标明出处:/article/7739542.html

声明:仿人人项目,所用所有图片资源都来源于官方人人android客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片。

上一篇聊到了通过WebView组件加载人人的访问授权页面,接下来就是当用户输入人人访问账号和密码,点击“登录”按钮,成功后人人的服务器端会返回AccessToken的值。初次使用,我们本地是没有存储session Key的,我们需要通过AccessToken去服务器端请求数据,获得session Key、sessionSecret和用户的userId。存储当前获得的sessionKey, sessionSecret以备后用。这里就需要用到网络这块的知识,这一篇就来说下仿人人的网络模块是如何架构的,先来看下网络处理模块的类图:



一、网络请求基类(AsyncBaseRequest),是一个实现Runnable接口的线程类。

初始化时的参数列表:

[java] view
plaincopy

public AsyncBaseRequest(String url, Map<String, String> parameter, ParseCallback handler, ResultCallback requestCallback) {}

参数列表解释:

第一个参数:网络请求URL;

第二个参数:网络请求的参数;

第三个参数:网络请求返回数据的解析器;

第四个参数:网络请求返回的结果回调接口;

网络请求具体实现抽象方法:

[java] view
plaincopy

protected abstract InputStream getRequestResult() throws IOException;

线程核心run()方法里面的实现:

[java] view
plaincopy

@Override

public void run() {

try {

mInStream = getRequestResult();

if (mInStream != null) {

String result = new String(readInputStream(mInStream));

Object obj = parseHandler.parse(result);

requestCallback.onSuccess(flag, obj);

} else {

System.out.println("get InputStream By HttpURLConnection return result is NULL.");

}

} catch (IOException e) {

requestCallback.onFail(flag, Constant.NETWORK_REQUEST_IOEXCEPTION_CODE); // IO异常标识

e.printStackTrace();

}

}

二、通过HTTP协议发送GET请求的具体实现

[java] view
plaincopy

package com.everyone.android.net;

import java.io.IOException;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import java.net.URLEncoder;

import java.util.Map;

import org.apache.http.protocol.HTTP;

import com.everyone.android.callback.ParseCallback;

import com.everyone.android.callback.ResultCallback;

/**

* 功能描述:通过HTTP协议发送GET请求

* @author android_ls

*

*/

public class AsyncHttpGet extends AsyncBaseRequest {

/**

*

*/

private static final long serialVersionUID = 2L;

public AsyncHttpGet(String url, Map<String, String> parameter,

ParseCallback handler, ResultCallback requestCallback) throws IOException {

super(url, parameter, handler, requestCallback);

}

@Override

protected InputStream getRequestResult() throws IOException {

StringBuilder sb = new StringBuilder(requestUrl);

sb.append('?');

for(Map.Entry<String, String> entry : parameter.entrySet()){

sb.append(entry.getKey()).append('=')

.append(URLEncoder.encode(entry.getValue(), HTTP.UTF_8)).append('&');

}

sb.deleteCharAt(sb.length()-1);

URL url = new URL(sb.toString());

mHttpURLConn = (HttpURLConnection)url.openConnection();

mHttpURLConn.setConnectTimeout(connectTimeout);

mHttpURLConn.setRequestMethod("GET");

if(mHttpURLConn.getResponseCode()== HttpURLConnection.HTTP_OK){

return mHttpURLConn.getInputStream();

}

return null;

}

}

三、通过HTTP协议发送POST请求的具体实现

[java] view
plaincopy

package com.everyone.android.net;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import java.net.URLEncoder;

import java.util.Map;

import org.apache.http.protocol.HTTP;

import com.everyone.android.callback.ParseCallback;

import com.everyone.android.callback.ResultCallback;

/**

* 功能描述:通过HTTP协议发送POST请求

* @author android_ls

*

*/

public class AsyncHttpPost extends AsyncBaseRequest {

/**

*

*/

private static final long serialVersionUID = 3L;

public AsyncHttpPost(String url, Map<String, String> parameter,

ParseCallback handler, ResultCallback requestCallback) {

super(url, parameter, handler, requestCallback);

}

@Override

protected InputStream getRequestResult() throws IOException {

StringBuilder sb = new StringBuilder();

if(parameter!=null && !parameter.isEmpty()){

for(Map.Entry<String, String> entry : parameter.entrySet()){

sb.append(entry.getKey()).append('=')

.append(URLEncoder.encode(entry.getValue(), HTTP.UTF_8)).append('&');

}

sb.deleteCharAt(sb.length()-1);

}

// 得到实体的二进制数据

byte[] entitydata = sb.toString().getBytes();

URL url = new URL(requestUrl);

mHttpURLConn = (HttpURLConnection)url.openConnection();

mHttpURLConn.setRequestMethod("POST");

mHttpURLConn.setConnectTimeout(5 * 1000);

// 如果通过post提交数据,必须设置允许对外输出数据

mHttpURLConn.setDoOutput(true);

mHttpURLConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

mHttpURLConn.setRequestProperty("Content-Length", String.valueOf(entitydata.length));

OutputStream outStream = mHttpURLConn.getOutputStream();

outStream.write(entitydata);

outStream.flush();

outStream.close();

if(mHttpURLConn.getResponseCode()== HttpURLConnection.HTTP_OK){

return mHttpURLConn.getInputStream();

}

return null;

}

}

四、线程池类

[java] view
plaincopy

package com.everyone.android.net;

import java.util.concurrent.AbstractExecutorService;

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

import android.util.Log;

/**

* 功能描述:网络请求线程池类

* @author android_ls

*/

public class DefaultThreadPool {

/**

* 用于保存等待执行的任务的阻塞队列。(有序的先进先出阻塞队列)

*/

private static ArrayBlockingQueue<Runnable> mBlockingQueue = new ArrayBlockingQueue<Runnable>(15, true);

/**

* 线程池

*/

private static AbstractExecutorService mThreadPoolExecutor

= new ThreadPoolExecutor(5, 7, 10, TimeUnit.SECONDS, mBlockingQueue,

new ThreadPoolExecutor.DiscardOldestPolicy());

private static DefaultThreadPool instance = null;

public static DefaultThreadPool getInstance() {

if (instance == null) {

instance = new DefaultThreadPool();

}

return instance;

}

/**

* 执行任务

* @param r

*/

public void execute(Runnable r) {

mThreadPoolExecutor.execute(r);

}

/**

* 关闭,并等待任务执行完成,不接受新任务

*/

public static void shutdown() {

if (mThreadPoolExecutor != null) {

mThreadPoolExecutor.shutdown();

Log.i(DefaultThreadPool.class.getName(), "DefaultThreadPool shutdown");

}

}

/**

* 关闭,立即关闭,并挂起所有正在执行的线程,不接受新任务

*/

public static void shutdownRightnow() {

if (mThreadPoolExecutor != null) {

mThreadPoolExecutor.shutdownNow();

try {

// 设置超时极短,强制关闭所有任务

mThreadPoolExecutor.awaitTermination(1, TimeUnit.MICROSECONDS);

} catch (InterruptedException e) {

e.printStackTrace();

}

Log.i(DefaultThreadPool.class.getName(), "DefaultThreadPool shutdownRightnow");

}

}

}

五、网络请求返回的数据解析接口

[java] view
plaincopy

package com.everyone.android.callback;

/**

* 功能描述:网络请求返回的数据解析接口

* @author android_ls

*

*/

public interface ParseCallback {

/**

* 对网络请求返回的数据进行解析

* @param str 要解析的字符串,JSON格式或XML

* @return 解析的结果

*/

public Object parse(String str);

}

六、网络请求返回的结果回调接口

[java] view
plaincopy

package com.everyone.android.callback;

/**

* 功能描述:网络请求返回的结果回调接口

* @author android_ls

*

*/

public interface ResultCallback {

public void onSuccess(Object obj);

public void onFail(int errorCode);

}

七、应用中界面(Activity)的基类

[java] view
plaincopy

package com.everyone.android;

import java.net.HttpURLConnection;

import java.util.ArrayList;

import java.util.List;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.widget.Toast;

import com.everyone.android.net.AsyncBaseRequest;

import com.everyone.android.net.DefaultThreadPool;

/**

* 功能描述:应用中界面(Activity)的基类

* 对原有的Activity类进行扩展

* @author android_ls

*/

public abstract class AppBaseActivity extends Activity {

/**

* 当前activity所持有的所有网络请求

*/

protected List<AsyncBaseRequest> mAsyncRequests;

protected Handler mHandler;

protected DefaultThreadPool mDefaultThreadPool;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(getLayoutId());

((EveryoneApplication) this.getApplication()).addActivity(this);

mHandler = new Handler();

mAsyncRequests = new ArrayList<AsyncBaseRequest>();

mDefaultThreadPool = DefaultThreadPool.getInstance();

// 初始化组件

setupView();

// 初始化数据

initializedData();

}

/**

* 布局文件ID

* @return

*/

protected abstract int getLayoutId();

/**

* 初始化组件

*/

protected abstract void setupView();

/**

* 初始化数据

*/

protected abstract void initializedData();

@Override

protected void onPause() {

/**

* 在activity销毁的时候同时设置停止请求,停止线程请求回调

*/

cancelRequest();

super.onPause();

}

private void cancelRequest() {

if (mAsyncRequests != null && mAsyncRequests.size() > 0) {

for (AsyncBaseRequest request : mAsyncRequests) {

HttpURLConnection conn = request.getRequestConn();

if (conn != null) {

try {

conn.disconnect();

System.out.println("onDestroy disconnect URL: " + conn.getURL());

mAsyncRequests.remove(request);

} catch (UnsupportedOperationException e) {

//do nothing .

}

}

}

}

}

/**

* 显示Toast形式的提示信息

* @param message

*/

protected void show(String message) {

Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();

}

@Override

protected void onDestroy() {

/**

* 在activity销毁的时候同时设置停止请求,停止线程请求回调

*/

cancelRequest();

super.onDestroy();

}

}

八、测试(继承自AppBaseActivity的子类),方法的调用

[java] view
plaincopy

String url = "http://www.baidu.com/";

Map<String, String> parameter = new HashMap<String, String>();

parameter.put("name", "android_ls");

parameter.put("age", "23");

AsyncBaseRequest asyncBaseRequest = new AsyncHttpPost(url, parameter, new ParseCallback(){

@Override

public Object parse(String str) {

// TODO Auto-generated method stub

return null;

}

},

new ResultCallback(){

@Override

public void onSuccess(int flag, Object obj) {

// TODO Auto-generated method stub

}

@Override

public void onFail(int flag, int errorCode) {

// TODO Auto-generated method stub

}

});

mDefaultThreadPool.execute(asyncBaseRequest);

mAsyncRequests.add(asyncBaseRequest);

AsyncBaseRequest的完整代码

[java] view
plaincopy

package com.everyone.android.net;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.Serializable;

import java.net.HttpURLConnection;

import java.util.Map;

import com.everyone.android.callback.ParseCallback;

import com.everyone.android.callback.ResultCallback;

import com.everyone.android.utils.Constant;

/**

* 功能描述:通过HTTP协议发送网络请求线程类

* @author android_ls

*

*/

public abstract class AsyncBaseRequest implements Runnable, Serializable {

/**

*

*/

private static final long serialVersionUID = 1L;

/**

* 网络连接超时,默认值为5秒

*/

protected int connectTimeout = 5 * 1000;

/**

* 网络数据读取超时,默认值为5秒

*/

protected int readTimeout = 5 * 1000;

protected void setConnectTimeout(int connectTimeout) {

this.connectTimeout = connectTimeout;

}

protected void setReadTimeout(int readTimeout) {

this.readTimeout = readTimeout;

}

protected String requestUrl;

protected Map<String, String> parameter;

private ParseCallback parseHandler;

private ResultCallback requestCallback;

protected HttpURLConnection mHttpURLConn;

protected InputStream mInStream;

public AsyncBaseRequest(String url, Map<String, String> parameter,

ParseCallback handler, ResultCallback requestCallback) {

this.parseHandler = handler;

this.requestUrl = url;

this.parameter = parameter;

this.requestCallback = requestCallback;

}

/**

* 发送网络请求

*

* @return 网络请求返回的InputStream数据流

* @throws IOException

*/

protected abstract InputStream getRequestResult() throws IOException;

@Override

public void run() {

try {

mInStream = getRequestResult();

if (mInStream != null) {

String result = new String(readInputStream(mInStream));

Object obj = parseHandler.parse(result);

requestCallback.onSuccess(obj);

} else {

System.out.println("get InputStream By HttpURLConnection return result is NULL.");

}

} catch (IOException e) {

requestCallback.onFail(Constant.NETWORK_REQUEST_IOEXCEPTION_CODE); // IO异常标识

e.printStackTrace();

}

}

/**

* 从输入流读取数据

*

* @param inStream

* @return

* @throws IOException

* @throws Exception

*/

protected byte[] readInputStream(InputStream inStream) throws IOException {

ByteArrayOutputStream outSteam = new ByteArrayOutputStream();

byte[] buffer = new byte[1024];

int len = 0;

while ((len = inStream.read(buffer)) != -1) {

outSteam.write(buffer, 0, len);

}

outSteam.close();

inStream.close();

return outSteam.toByteArray();

}

public HttpURLConnection getRequestConn() {

return mHttpURLConn;

}

}

好了就到这里吧,后面的待续。。。

吐槽下:在CSDN上写文章,写完后你若想删除掉之前写的一部分内容,就得一行一行删,不能选中某个区域,之后一次性删除,真郁闷。我记得之前不是这样的,现在为什么会这样呢?我刚才删除写错的文字和代码就用了我五分钟左右,真的想说粗话了,但想了下,算了。我是一个文明的人,呵呵。

这一篇网络模块处理有些地方有待优化,优化处理部分请阅读下篇Android仿人人客户端(v5.7.1)——网络模块优化
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: