首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > Android >

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

2013-04-02 
Android仿人人客户端(v5.7.1)——网络模块处理的架构转载请标明出处:http://blog.csdn.net/android_ls/artic

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

转载请标明出处:http://blog.csdn.net/android_ls/article/details/8732427
 声明:仿人人项目,所用所有图片资源都来源于官方人人android客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片。
       上一篇聊到了通过WebView组件加载人人的访问授权页面,接下来就是当用户输入人人访问账号和密码,点击“登录”按钮,成功后人人的服务器端会返回AccessToken的值。初次使用,我们本地是没有存储session Key的,我们需要通过AccessToken去服务器端请求数据,获得session Key、sessionSecret和用户的userId。存储当前获得的sessionKey, sessionSecret以备后用。这里就需要用到网络这块的知识,这一篇就来说下仿人人的网络模块是如何架构的,先来看下网络处理模块的类图:

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

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

  初始化时的参数列表:

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

 参数列表解释: 

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

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

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

       第四个参数:网络请求返回的结果回调接口;
  网络请求具体实现抽象方法:

protected abstract InputStream getRequestResult() throws IOException;

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

@Overridepublic 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请求的具体实现

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);}@Overrideprotected 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请求的具体实现

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);}@Overrideprotected 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;}}

四、线程池类

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");        }    }}

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

package com.everyone.android.callback;/** * 功能描述:网络请求返回的数据解析接口 * @author android_ls * */public interface ParseCallback {    /**     * 对网络请求返回的数据进行解析     * @param str 要解析的字符串,JSON格式或XML     * @return 解析的结果     */public Object parse(String str);}

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

package com.everyone.android.callback;/** * 功能描述:网络请求返回的结果回调接口 * @author android_ls * */public interface ResultCallback {public void onSuccess(Object obj);public void onFail(int errorCode);}

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

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的子类),方法的调用

    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的完整代码

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;@Overridepublic 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)——网络模块优化

13楼u0100984538小时前
高手呀!
Re: android_ls3小时前
回复u010098453n谢谢夸奖!
12楼u0101084128小时前
...
11楼mfkauko13小时前
赞一个,一直在学习中,希望更新。
Re: android_ls9小时前
回复mfkaukon谢谢支持!
10楼u010096450昨天 14:33
魂牵梦萦
9楼u010100919昨天 13:38
收益
Re: android_ls昨天 14:22
回复u010100919n能对你有帮助,我也很高兴。互相借鉴,共同进步。
8楼u010100919前天 22:29
还得学习
Re: android_ls昨天 00:34
回复u010100919n这一篇中的部分处理,是不太完美,我已意识到,在《Android仿人人客户端(v5.7.1)——网络模块优化 》中我已处理,你若觉得我哪里处理的不合适,欢迎提出你的意见,大家互相交流、借鉴,共同进步。
7楼hljstardust2012前天 22:24
谢谢分享,真的很好!,学习了
Re: android_ls前天 22:27
回复hljstardust2012n谢谢你的支持!
6楼liu_jun_y前天 20:50
LZn请问你画图使用的是那个工具呀。
Re: android_ls前天 20:50
回复liu_jun_ynAstah UML 绘图工具,你可以到网上搜下,下载一个试试,很好用的,呵呵。
5楼sunjunlaing52前天 17:32
分析的很翔实,受益了,关注中,能给一份跑通code吗? 谢谢!1449364567@qq.com
4楼goldseawu前天 16:40
能给code?最近在研究手机方面的代码,谢谢,511413077@qq.com
3楼witmind前天 15:02
代码写的很工整,异常处理准确,线程使用节省。楼主应该是位用心写代码的偏完美主义者。
Re: android_ls前天 15:42
回复witmindn看来你认真阅读我写的代码片段了,不过你说的那些我觉得是每个专业程序员都应该做到。我写的还不是很好,有些地方处理的还是不完美。谢谢你的评论和支持!
2楼fisherheng3天前 16:42
写的很好 学习了
Re: android_ls前天 23:09
回复fisherhengn谢谢夸奖!
1楼b879362603天前 14:38
直接用AsyncTask可以不?

热点排行