当前位置: 首页 > 编程日记 > 正文

如何独立开发一个网络请求框架

(原创出处为本博客:http://www.cnblogs.com/linguanh/)

目录:

    前言

  准备工作

     开发模式

    开发原则

    线程

    高并发

    TCP/UDP

  本类介绍

     开发选择

    功能列表

    优点

    拓展

  完整代码

   用法例子

     

前言:

  已开源到GitHub,希望大家能够和我一起来完善它,该类肯定有很多不足的,但总体来说,还是不错的。

  为什么要写这个东西?原因如下:

  在此之前已经有很多不错的网络请求框架广为人知了,例如 android-async-http,okHttp等,这类优秀的框架其底层的实现大部分也是基于系统的 线程池 和 httpClient 或 HttpUrlConnection,其中OK是自己解析http协议的,我相信很多开发者在使用这些框架的时候自己是没有去了解这些东西的。

  作为一个合格的Android开发者,我觉得必须要会自己使用系统的SDK提供的API来实现功能,并不是不建议使用框架,只是建议在能够在独立地,不依赖百度,完全断网的情况下去使用现有的资源来实现需求功能后,再去使用这些框架,这样不至于成为“框架工程师”,而且,在面试的时候,也能信心十足!

  本文不仅仅是对Java/Android而言,同样的建议可以折射到其他语言的开发上。

  

准备工作

  1,了解并使用一些常用的开发模式,例如单例、观察者、简单工厂等。要开发框架,使用开发模式的必须的,无论是从代码解耦或者是内存优化方面上去看都是必不可少,前者有ImageLoader采用了双从判断类型的单例模式,包括Android我们熟悉的事件机制,它是观察者模式,还有适配器模式。

  2,了解并使用一些开发原则,注意哦,这里是原则哦,例如接口分离,一个大的项目没几个接口怎么行,而且接口能够我们带来很大的方便。

  3,了解并学会使用线程以及优化,网络请求类框架,我们知道Android中是不能在主线程中(又称UI线程)进行网络操作的,那么我们的框架中必不可少地要使用到子线程,这就需要你掌握线程类知识,例如简单的 Thread + Runnable + Handler 组合拳,再重量级点的就使用 AsyncTask。

  4,处理好高并发,一个应用中往往要进行多线程操作,而Java虚拟机对于一个线程的内存分配大约在1M左右,具体多少要看它执行的任务而定。看到线程高并发这些字,第一想到的应该是 线程池,所以线程池你需要去了解并学会灵活使用。

  5,了解 Tcp/Udp 数据包的结构以及 Post 的方式差别。还记得有很多招聘条件里面有很多要求要了解 TCP协议的要求不?如果你看到这样的要求的时候,心里默念这个要求有什么用的话,那就证明你还没真正地去使用过它,这点等下留意下我的代码注释。

  6,其他 (例如一个编译器....)

本类介绍

  还是不要说框架了,说类吧,哈哈,不要那么高大上。接着在上面的准备工作中谈到的点,下面我来意义对应解释,它们是怎样被用到这个 Http工具类里面的。

  1,在开发模式上,我采用了静态内部类的单例模式,这样有两个好处,一个是保证了类不使用的时候不会想饿汉模式一样在开始就占用内存,而是懒汉模式,而静态内部类则是为了解决线程安全的问题,它仅会在使用的时候在JVM虚拟机类的加载第五步时初始化,此步骤中的clinit<>是线程安全的,同时又不会因为使用同步关键字 synchronized 而导致其他的问题,同步失败或耗资源等。 

public static LghHttp getInstance(){return LghHttpStatic.singleLghHttp;
}private static class LghHttpStatic{private static LghHttp singleLghHttp = new LghHttp();
}

  2,在开发原则上面,采用了接口分离,主要体现在数据处理方面。

    /** 接口分离 */private interface LghHttpBaseListenr{void onFailed(int type);
//        void onUrlFailed();
//        void onTimeOut();
//        void onProtocolFailed();
//        void onEncodingFailed();
//        void onIoFailed();
    }/** 全局有 requestCode 区分 */public interface LghHttpGlobleListener extends LghHttpBaseListenr{void onSuccess(int requestCode,String response);}/** 单一的没 requestCode 区分 */public interface LghHttpSingleListener extends LghHttpBaseListenr{void onSuccess(String response);}

  3,线程和并发方面,采用了newFixdThreadPool 类型的线程池,如果要考虑替换,建议换为 newCacheThreadPool,他们两个之间 newFixdThreadPool 可以控制并发数量,且在整个APP运行过程中有几个常驻线程在,避免使用时反复地new,退出时再销毁,而 newCacheThreadPool 则会在任务完成后,自动回收线程,它会帮你释放线程内存,也就不会有常驻线程。

 1 /** 初始化函数 */
 2     public synchronized void init(){
 3         this.threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
 4         this.handler = new Handler(){
 5             @Override
 6             public void handleMessage(Message msg) {
 7                 super.handleMessage(msg);
 8 
 9                 HttpDataBean bean = (HttpDataBean) msg.obj;
10                 LghHttpBaseListenr tempListener;
11                 if(GloblelghHttpListeners!=null){ /** 以全局的优先 */
12                     tempListener = GloblelghHttpListeners;
13                 }else if(bean.getListeners()!=null){
14                     tempListener = bean.getListeners();
15                 }else{
16                     return;
17                 }
18                 switch (msg.what){
19                     case Success:
20                         if(GloblelghHttpListeners!=null){ /** 以全局的优先 */
21                             GloblelghHttpListeners.onSuccess(msg.arg1,bean.getResponse());
22                         }else{
23                             bean.getListeners().onSuccess(bean.getResponse());
24                         }
25                         break;
26                     case UrlFailed:
27                         tempListener.onFailed(UrlFailed);
28                         break;
29                     case TimeOut:
30                         tempListener.onFailed(TimeOut);
31                         break;
32                     case ProtocolFailed:
33                         tempListener.onFailed(ProtocolFailed);
34                         break;
35                     case EncodingFailed:
36                         tempListener.onFailed(EncodingFailed);
37                         break;
38                     case IOFailed:
39                         tempListener.onFailed(IOFailed);
40                         break;
41                     default:
42                         /** 这里不可能会进入,也当作一个留给你自己的接口吧 */
43                         break;
44                 }
45             }
46         };
47     }
View Code

  4,功能方面,提供了三种常见操作:

    1)Get 请求操作    

 1     /** Get 请求整合 */
 2     public void doGet(final String url){
 3         doGet(-1, url, null);
 4     }
 5 
 6     public void doGet(final int requestCode,final String url){
 7         doGet(requestCode, url, null);
 8     }
 9 
10     public void doGet(
11             final int requestCode,
12             final String url,
13             final LghHttpSingleListener lghHttpListeners)
14     {
15         Runnable runnable = new Runnable() {
16             @Override
17             public void run() {
18                 get(requestCode, url, lghHttpListeners);
19             }
20         };
21         if(threadPool != null){
22             threadPool.execute(runnable);
23         }else{
24             Log.d(TAG,"do get threadPool is null");
25         }
26     }
27 
28     private void get(int requestCode,String url,LghHttpSingleListener lghHttpListener){
29         try {
30             HttpURLConnection httpURLConnection = getHttpUrlConnection(url,"GET");
31             httpURLConnection.setUseCaches(false);
32             sendMessage(Success,requestCode, commonGetResult(httpURLConnection,lghHttpListener));
33         } catch (MalformedURLException e) {
34             dealWithException(e,lghHttpListener);
35         } catch (IOException e) {
36             dealWithException(e,lghHttpListener);
37         }
38     }
View Code

    2)Post 请求操作

 1 /** Post 请求整合 */
 2     public void doPost(String url){
 3         doPost(-1, url);
 4     }
 5 
 6     public void doPost(int requestCode,String url){
 7         doPost(requestCode, url, null, null);
 8     }
 9 
10     public void doPost(int requestCode,String url,LghHttpSingleListener listener){
11         doPost(requestCode, url, null, null,listener);
12     }
13 
14     public void doPost(int requestCode,String url,String[] keys,String[] values){
15         doPost(requestCode, url, keys, values, null);
16     }
17 
18     public void doPost(
19             final int requestCode,
20             final String url,
21             final String[] keys,
22             final String[] values,
23             final LghHttpSingleListener listener
24     ){
25         Runnable runnable = new Runnable() {
26             @Override
27             public void run() {
28                 post(requestCode, url,keys,values, listener);
29             }
30         };
31         if(threadPool != null){
32             threadPool.execute(runnable);
33         }else{
34             Log.d(TAG,"do post threadPool is null");
35         }
36     }
37 
38     /** 采用第一种post协议,application/x-www-form-urlencoded */
39     private void post(
40             int requestCode,
41             String url,
42             String[] keys,
43             String[] values,
44             LghHttpSingleListener listener
45     ){
46         if(url==null){
47             return;
48         }
49         try{
50             HttpURLConnection httpURLConnection = getHttpUrlConnection(url,"POST");
51             httpURLConnection.setDoOutput(true); /** post 必不可少 */
52             httpURLConnection.setUseCaches(false);
53 
54             if(keys!=null && values!=null){
55                 OutputStream outputStream = httpURLConnection.getOutputStream();
56                 commonCombinePostText(keys,values,outputStream);
57                 outputStream.flush();
58                 outputStream.close();
59             }
60             sendMessage(Success,requestCode, commonGetResult(httpURLConnection,listener));
61         }catch (MalformedURLException e){
62             dealWithException(e,listener);
63         } catch (SocketTimeoutException e){
64             dealWithException(e,listener);
65         } catch (ProtocolException e) {
66             dealWithException(e,listener);
67         } catch (UnsupportedEncodingException e) {
68             dealWithException(e,listener);
69         } catch (IOException e) {
70             dealWithException(e,listener);
71         }
72     }
View Code

    3)上传图片操作,Tcp 数据包的一些知识,在这里有用到。

  1 /** 上传图片部分整合 */
  2     public void doUpLoadPic(
  3             String url,
  4             String picName,
  5             String streamName,
  6             Bitmap bit
  7     ){
  8         doUpLoadPic(-1, url, null, null, picName, streamName, bit, null);
  9     }
 10 
 11     public void doUpLoadPic(
 12             int requestCode,
 13             String url,
 14             String picName,
 15             String streamName,
 16             Bitmap bit
 17     ){
 18         doUpLoadPic(requestCode, url, null, null, picName, streamName, bit, null);
 19     }
 20 
 21     public void doUpLoadPic(
 22             int requestCode,
 23             String url,
 24             String picName,
 25             String streamName,
 26             Bitmap bit,
 27             LghHttpSingleListener listener
 28     ){
 29         doUpLoadPic(requestCode, url, null, null, picName, streamName, bit, listener);
 30     }
 31 
 32     public void doUpLoadPic(
 33             int requestCode,
 34             String url,
 35             String[] keys,
 36             String[] values,
 37             String picName,
 38             String streamName,
 39             Bitmap bit
 40     ){
 41         doUpLoadPic(requestCode, url, keys, values, picName, streamName, bit, null);
 42     }
 43 
 44     public void doUpLoadPic(
 45             final int requestCode,
 46             final String url,
 47             final String[] keys,
 48             final String[] values,
 49             final String picName,
 50             final String streamName,
 51             final Bitmap bit,
 52             final LghHttpSingleListener listener
 53     ){
 54         Runnable runnable = new Runnable() {
 55             @Override
 56             public void run() {
 57                 UpLoadPic(requestCode, url, keys, values, picName, streamName, bit, listener);
 58             }
 59         };
 60         if(threadPool != null){
 61             threadPool.execute(runnable);
 62         }else{
 63             Log.d(TAG,"do post threadPool is null");
 64         }
 65     }
 66 
 67     /**
 68      * 此函数用来上传图片
 69      * post 的 两种数据包格式:
 70      * 1,application/x-www-form-urlencoded;用来上传文字
 71      * 2,multipart/form-data; 二进制传输,除了文字之外,还可以用来传输 文件,例如图片!
 72      * 3,multipart/form-data; 必须要带有分隔符 boundary
 73      * 4,在http post请求的结尾,需要有一个分界线,但是是前后都有--的:--分隔符--
 74      * 参数:
 75      *      url
 76      *      picName    图片的名称
 77      *      streamName 流体值的名称
 78      *      例如采用 php 接收,那么在服务器获取图片名称的写法是:$_FILES['streamName']['picName']
 79      **/
 80     private void UpLoadPic(
 81             int requestCode,
 82             String url,
 83             String[] keys,
 84             String[] values,
 85             String picName,
 86             String streamName,
 87             Bitmap bit,
 88             LghHttpSingleListener listener
 89     ){
 90         String twoHyphens = "--";   /** 一定要是 2行 */
 91         String boundary = "******"; /** 数据包分割线可以自定义 */
 92         try{
 93             HttpURLConnection httpURLConnection = getHttpUrlConnection(url,"POST");
 94             httpURLConnection.setUseCaches(false);
 95             httpURLConnection.setDoOutput(true);
 96             httpURLConnection.setChunkedStreamingMode(1024 * 256); /** 一次传输的块大小 */
 97             /** 数据 --------包头-------- 格式组装 */
 98             httpURLConnection.setRequestProperty("Connection","Keep-Alive");
 99             httpURLConnection.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);
100             /** 数据 --------包体-------- 格式组装*/
101             DataOutputStream body = new DataOutputStream(httpURLConnection.getOutputStream());
102             /** \r\n 是换行 */
103             body.writeBytes(twoHyphens+boundary+"\r\n"); /** 先写分隔符,标志和上面的头分开 */
104             body.writeBytes(
105                     "Content-Disposition:form-data;" +
106                             "name=\"" + streamName + "\";" +
107                             "filename=\"" + picName + "\"" + "\r\n"
108             );
109             /** 写文本数据体 */
110             body.writeBytes("\r\n");
111             if(keys!=null && values!=null){
112                 body.writeBytes(twoHyphens+boundary+"\r\n");
113                 body.writeBytes("Content-Disposition:form-data;");
114                 commonCombinePostText(keys,values,body);
115                 body.writeBytes("\r\n");
116             }
117             /** -------下面开始写图片二进制------- */
118             /** 下面是先压缩 */
119             int compress = 100;
120             ByteArrayOutputStream baos = new ByteArrayOutputStream();
121             bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
122             if(IsOpenCompress){
123                 while (baos.toByteArray().length / 1024 > CompressLimit) {
124                     baos.reset();
125                     compress -= 10;
126                     if(compress==0){
127                         bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
128                         break;
129                     }
130                     bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
131                 }
132             }
133             /** 开始写 */
134             InputStream picStream = new ByteArrayInputStream(baos.toByteArray());
135             byte[] buffer = new byte[10*1024];
136             int count;
137             while((count = picStream.read(buffer))!=-1){
138                 body.write(buffer,0,count);
139             }
140             picStream.close();
141             body.writeBytes("\r\n");
142             body.writeBytes(twoHyphens + boundary + twoHyphens +"\r\n");
143             body.flush();
144             /** 写完 */
145             sendMessage(Success,requestCode,commonGetResult(httpURLConnection,listener));
146             body.close();
147         }catch (MalformedURLException e){
148             dealWithException(e,listener);
149         } catch (SocketTimeoutException e){
150             dealWithException(e,listener);
151         } catch (ProtocolException e) {
152             dealWithException(e,listener);
153         } catch (UnsupportedEncodingException e) {
154             dealWithException(e,listener);
155         } catch (IOException e) {
156             dealWithException(e,listener);
157         }
158     }
View Code

  5,优点:

    1)绝对的轻量级,可以提升APK 的体积优化,没依赖其他第三方库

    2)内存管理方面可以放心

    3)请求速度方面是纯系统的 HttpUrlConnection,没有过多的代码片段

  6,可以进一步解耦拆分类,为了方便我自己使用所以我写在了一个里面,可以分为:

    1)公共部分

 1     /** 公共部分,异常集合处理 */
 2     private void dealWithException(
 3             Exception e,
 4             LghHttpSingleListener lghHttpListeners)
 5     {
 6         HttpDataBean bean = new HttpDataBean();
 7         bean.setListeners(lghHttpListeners);
 8         if(e instanceof MalformedURLException){
 9             Log.d(TAG, "链接格式有问题 "+e.toString());
10             sendMessage(UrlFailed,bean);
11         }else if(e instanceof SocketTimeoutException){
12             Log.d(TAG, "连接超时 "+e.toString());
13             sendMessage(TimeOut,bean);
14         }else if(e instanceof ProtocolException){
15             Log.d(TAG, "协议异常,注意不要多次连接 " + e.toString());
16             sendMessage(ProtocolFailed, bean);
17         }else if(e instanceof UnsupportedEncodingException){
18             Log.d(TAG, "编码类型异常 " + e.toString());
19             sendMessage(EncodingFailed, bean);
20         }else if(e instanceof IOException){
21             Log.d(TAG, "io 异常 " + e.toString());
22             sendMessage(IOFailed,bean);
23         }
24     }
25 
26     /** 获取一个HttpUrlConnection,合并一些公共部分 */
27     private static HttpURLConnection getHttpUrlConnection
28             (String url,String requestWay) throws IOException {
29         Log.d(TAG,"url is "+url);
30         URL mRrl = new URL(url);
31         HttpURLConnection httpURLConnection = (HttpURLConnection) mRrl.openConnection();
32         httpURLConnection.setRequestMethod(requestWay);
33         httpURLConnection.setRequestProperty("Charset", "UTF-8");
34         httpURLConnection.setConnectTimeout(5 * 1000);
35         return httpURLConnection;
36     }
37 
38     /** 获取结果公共部分 */
39     private HttpDataBean commonGetResult(
40             HttpURLConnection httpURLConnection,
41             LghHttpSingleListener listener
42     ) throws IOException {
43         if(httpURLConnection==null){
44             return null;
45         }
46         BufferedReader br = new BufferedReader
47                 (
48                         new InputStreamReader(httpURLConnection.getInputStream(),"UTF-8"),
49                         8*1024
50                 );
51         StringBuffer resultBuffer = new StringBuffer("");
52         String line;
53         while ((line = br.readLine())!=null){
54             resultBuffer.append(line);
55         }
56         HttpDataBean bean = new HttpDataBean();
57         bean.setResponse(resultBuffer.toString());
58         bean.setListeners(listener);
59         br.close();
60         return bean;
61     }
62 
63     /** 组合 post 文本数据公共部分 */
64     private OutputStream commonCombinePostText(
65             String[] keys,
66             String[] values,
67             OutputStream outputStream) throws IOException
68     {
69         StringBuffer requestStr = new StringBuffer();
70         int keysLength = keys.length;
71         for(int i=0;i<keysLength;i++){
72             requestStr.append(keys[i]+"="+values[i]+"&");
73         }
74         outputStream.write(requestStr.toString().getBytes());
75         return outputStream;
76     }
View Code

    2)数据部分

 1 /**
 2      * LghHttp 基础数据类
 3      * 作为 handler 传递的数据种子,只在成功时传递
 4      * */
 5     private class HttpDataBean implements Serializable{
 6 
 7         private String response;
 8         private LghHttpSingleListener listeners;
 9 
10         public void setResponse(String response){
11             this.response = response;
12         }
13 
14         public void setListeners(LghHttpSingleListener listeners){
15             this.listeners = listeners;
16         }
17 
18         public String getResponse(){
19             return this.response;
20         }
21 
22         public LghHttpSingleListener getListeners(){
23             return this.listeners;
24         }
25     }
View Code

    3)请求核心部分

  7,拓展,加入视频上传部分。

完整代码:

  上面嵌套讲解拆分了,这里提供完整的。

  1 package com.lghsaleimage;
  2 
  3 import android.graphics.Bitmap;
  4 import android.os.Handler;
  5 import android.os.Message;
  6 import android.util.Log;
  7 
  8 import java.io.BufferedReader;
  9 import java.io.ByteArrayInputStream;
 10 import java.io.ByteArrayOutputStream;
 11 import java.io.DataOutputStream;
 12 import java.io.IOException;
 13 import java.io.InputStream;
 14 import java.io.InputStreamReader;
 15 import java.io.OutputStream;
 16 import java.io.Serializable;
 17 import java.io.UnsupportedEncodingException;
 18 import java.net.HttpURLConnection;
 19 import java.net.MalformedURLException;
 20 import java.net.ProtocolException;
 21 import java.net.SocketTimeoutException;
 22 import java.net.URL;
 23 import java.util.concurrent.Executors;
 24 import java.util.concurrent.ThreadPoolExecutor;
 25 
 26 /**
 27  * Created by 林冠宏(指尖下的幽灵) on 2016/8/11.
 28  *
 29  * Blog : http://www.cnblogs.com/linguanh/;
 30  *
 31  * Name : http 工具类
 32  *
 33  * 前言:
 34  *     希望大家能够和我一起来完善它,该类肯定有很多不足的,但总体来说,还是不错的。
 35  *
 36  * 下面是简介和拓展:
 37  *
 38  *     1, 考虑到网络请求必不可少,采用了静态内部类单例模式
 39  *
 40  *     2, 采用 newFixedThreadPool 线程池来管理并发线程,
 41  *        如果要替换,建议使用 newCacheThreadPool
 42  *
 43  *     3, 功能方面提供三种常见操作:
 44  *           1)Get请求
 45  *           2)Post请求
 46  *           3)图片上传
 47  *     4, 优点:
 48  *           1) 绝对的轻量级,可以提升 APK 体积优化
 49  *           2)内存管理方面可以放心
 50  *           3)请求速度方法是纯系统的 HttpUrlConnection 请求,
 51  *              没有过多的代码片段
 52  *
 53  *     5,可以进一步解耦拆分类,分为:
 54  *           1)公共部分
 55  *           2)数据部分
 56  *           3)请求核心部分
 57  *
 58  *     6, 加入视频上传部分
 59  *
 60  */
 61 
 62 public class LghHttp {
 63 
 64     private final static String TAG = "zzzzz";
 65 
 66     public final static int Success = 0x10;
 67     public final static int UrlFailed = 0x11;
 68     public final static int TimeOut = 0x12;
 69     public final static int ProtocolFailed = 0x13;
 70     public final static int EncodingFailed = 0x14;
 71     public final static int IOFailed = 0x15;
 72 
 73     private final static boolean IsOpenCompress = true;/** 是否开启压缩 */
 74     private final static int CompressLimit = 500;      /** 压缩级别,单位是 K */
 75 
 76     private ThreadPoolExecutor threadPool;
 77     private Handler handler;
 78     /**
 79      * 全局回调接口 GloblelghHttpListeners
 80      * 注意:
 81      *     个人建议,如果请求页面多的,那就不要使用全局接口。尽量采用singleInterface
 82      *     否则,你需要在用户层页面的每次onResume重新设置
 83      * */
 84     private LghHttpGlobleListener GloblelghHttpListeners;
 85 
 86     public static LghHttp getInstance(){
 87         return LghHttpStatic.singleLghHttp;
 88     }
 89 
 90     private static class LghHttpStatic{
 91         private static LghHttp singleLghHttp = new LghHttp();
 92     }
 93 
 94     /** 销毁,内存释放善后操作 */
 95     public void destroy(){
 96         if(threadPool!=null){
 97             if(!threadPool.isShutdown()){
 98                 threadPool.shutdown();
 99                 threadPool = null;
100             }
101         }
102         if(handler!=null){
103             handler.removeCallbacksAndMessages(null);
104             handler = null;
105         }
106         if(GloblelghHttpListeners!=null){
107             GloblelghHttpListeners = null;
108         }
109         LghHttpStatic.singleLghHttp = null;
110     }
111 
112     public void setGloblelghHttpListeners(LghHttpGlobleListener GloblelghHttpListeners){
113         this.GloblelghHttpListeners = GloblelghHttpListeners;
114     }
115 
116     /**
117      * LghHttp 基础数据类
118      * 作为 handler 传递的数据种子,只在成功时传递
119      * */
120     private class HttpDataBean implements Serializable{
121 
122         private String response;
123         private LghHttpSingleListener listeners;
124 
125         public void setResponse(String response){
126             this.response = response;
127         }
128 
129         public void setListeners(LghHttpSingleListener listeners){
130             this.listeners = listeners;
131         }
132 
133         public String getResponse(){
134             return this.response;
135         }
136 
137         public LghHttpSingleListener getListeners(){
138             return this.listeners;
139         }
140     }
141 
142     /** 初始化函数 */
143     public synchronized void init(){
144         this.threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
145         this.handler = new Handler(){
146             @Override
147             public void handleMessage(Message msg) {
148                 super.handleMessage(msg);
149 
150                 HttpDataBean bean = (HttpDataBean) msg.obj;
151                 LghHttpBaseListenr tempListener;
152                 if(GloblelghHttpListeners!=null){ /** 以全局的优先 */
153                     tempListener = GloblelghHttpListeners;
154                 }else if(bean.getListeners()!=null){
155                     tempListener = bean.getListeners();
156                 }else{
157                     return;
158                 }
159                 switch (msg.what){
160                     case Success:
161                         if(GloblelghHttpListeners!=null){ /** 以全局的优先 */
162                             GloblelghHttpListeners.onSuccess(msg.arg1,bean.getResponse());
163                         }else{
164                             bean.getListeners().onSuccess(bean.getResponse());
165                         }
166                         break;
167                     case UrlFailed:
168                         tempListener.onFailed(UrlFailed);
169                         break;
170                     case TimeOut:
171                         tempListener.onFailed(TimeOut);
172                         break;
173                     case ProtocolFailed:
174                         tempListener.onFailed(ProtocolFailed);
175                         break;
176                     case EncodingFailed:
177                         tempListener.onFailed(EncodingFailed);
178                         break;
179                     case IOFailed:
180                         tempListener.onFailed(IOFailed);
181                         break;
182                     default:
183                         /** 这里不可能会进入,也当作一个留给你自己的接口吧 */
184                         break;
185                 }
186             }
187         };
188     }
189 
190     /** handler 发消息部分整合 */
191     private void sendMessage(int what,int code,Object object){
192         Message msg = new Message();
193         msg.what = what;
194         msg.arg1 = code;
195         msg.obj = object;
196         handler.sendMessage(msg);
197     }
198 
199     private void sendMessage(int what,Object object){
200         sendMessage(what, -1, object);
201     }
202 
203     /**
204      * requestCode 请求标识符,方便区分
205      * */
206 
207     /** Get 请求整合 */
208     public void doGet(final String url){
209         doGet(-1, url, null);
210     }
211 
212     public void doGet(final int requestCode,final String url){
213         doGet(requestCode, url, null);
214     }
215 
216     public void doGet(
217             final int requestCode,
218             final String url,
219             final LghHttpSingleListener lghHttpListeners)
220     {
221         Runnable runnable = new Runnable() {
222             @Override
223             public void run() {
224                 get(requestCode, url, lghHttpListeners);
225             }
226         };
227         if(threadPool != null){
228             threadPool.execute(runnable);
229         }else{
230             Log.d(TAG,"do get threadPool is null");
231         }
232     }
233 
234     private void get(int requestCode,String url,LghHttpSingleListener lghHttpListener){
235         try {
236             HttpURLConnection httpURLConnection = getHttpUrlConnection(url,"GET");
237             httpURLConnection.setUseCaches(false);
238             sendMessage(Success,requestCode, commonGetResult(httpURLConnection,lghHttpListener));
239         } catch (MalformedURLException e) {
240             dealWithException(e,lghHttpListener);
241         } catch (IOException e) {
242             dealWithException(e,lghHttpListener);
243         }
244     }
245 
246     /** Post 请求整合 */
247     public void doPost(String url){
248         doPost(-1, url);
249     }
250 
251     public void doPost(int requestCode,String url){
252         doPost(requestCode, url, null, null);
253     }
254 
255     public void doPost(int requestCode,String url,LghHttpSingleListener listener){
256         doPost(requestCode, url, null, null,listener);
257     }
258 
259     public void doPost(int requestCode,String url,String[] keys,String[] values){
260         doPost(requestCode, url, keys, values, null);
261     }
262 
263     public void doPost(
264             final int requestCode,
265             final String url,
266             final String[] keys,
267             final String[] values,
268             final LghHttpSingleListener listener
269     ){
270         Runnable runnable = new Runnable() {
271             @Override
272             public void run() {
273                 post(requestCode, url,keys,values, listener);
274             }
275         };
276         if(threadPool != null){
277             threadPool.execute(runnable);
278         }else{
279             Log.d(TAG,"do post threadPool is null");
280         }
281     }
282 
283     /** 采用第一种post协议,application/x-www-form-urlencoded */
284     private void post(
285             int requestCode,
286             String url,
287             String[] keys,
288             String[] values,
289             LghHttpSingleListener listener
290     ){
291         if(url==null){
292             return;
293         }
294         try{
295             HttpURLConnection httpURLConnection = getHttpUrlConnection(url,"POST");
296             httpURLConnection.setDoOutput(true); /** post 必不可少 */
297             httpURLConnection.setUseCaches(false);
298 
299             if(keys!=null && values!=null){
300                 OutputStream outputStream = httpURLConnection.getOutputStream();
301                 commonCombinePostText(keys,values,outputStream);
302                 outputStream.flush();
303                 outputStream.close();
304             }
305             sendMessage(Success,requestCode, commonGetResult(httpURLConnection,listener));
306         }catch (MalformedURLException e){
307             dealWithException(e,listener);
308         } catch (SocketTimeoutException e){
309             dealWithException(e,listener);
310         } catch (ProtocolException e) {
311             dealWithException(e,listener);
312         } catch (UnsupportedEncodingException e) {
313             dealWithException(e,listener);
314         } catch (IOException e) {
315             dealWithException(e,listener);
316         }
317     }
318 
319     /** 上传图片部分整合 */
320     public void doUpLoadPic(
321             String url,
322             String picName,
323             String streamName,
324             Bitmap bit
325     ){
326         doUpLoadPic(-1, url, null, null, picName, streamName, bit, null);
327     }
328 
329     public void doUpLoadPic(
330             int requestCode,
331             String url,
332             String picName,
333             String streamName,
334             Bitmap bit
335     ){
336         doUpLoadPic(requestCode, url, null, null, picName, streamName, bit, null);
337     }
338 
339     public void doUpLoadPic(
340             int requestCode,
341             String url,
342             String picName,
343             String streamName,
344             Bitmap bit,
345             LghHttpSingleListener listener
346     ){
347         doUpLoadPic(requestCode, url, null, null, picName, streamName, bit, listener);
348     }
349 
350     public void doUpLoadPic(
351             int requestCode,
352             String url,
353             String[] keys,
354             String[] values,
355             String picName,
356             String streamName,
357             Bitmap bit
358     ){
359         doUpLoadPic(requestCode, url, keys, values, picName, streamName, bit, null);
360     }
361 
362     public void doUpLoadPic(
363             final int requestCode,
364             final String url,
365             final String[] keys,
366             final String[] values,
367             final String picName,
368             final String streamName,
369             final Bitmap bit,
370             final LghHttpSingleListener listener
371     ){
372         Runnable runnable = new Runnable() {
373             @Override
374             public void run() {
375                 UpLoadPic(requestCode, url, keys, values, picName, streamName, bit, listener);
376             }
377         };
378         if(threadPool != null){
379             threadPool.execute(runnable);
380         }else{
381             Log.d(TAG,"do post threadPool is null");
382         }
383     }
384 
385     /**
386      * 此函数用来上传图片
387      * post 的 两种数据包格式:
388      * 1,application/x-www-form-urlencoded;用来上传文字
389      * 2,multipart/form-data; 二进制传输,除了文字之外,还可以用来传输 文件,例如图片!
390      * 3,multipart/form-data; 必须要带有分隔符 boundary
391      * 4,在http post请求的结尾,需要有一个分界线,但是是前后都有--的:--分隔符--
392      * 参数:
393      *      url
394      *      picName    图片的名称
395      *      streamName 流体值的名称
396      *      例如采用 php 接收,那么在服务器获取图片名称的写法是:$_FILES['streamName']['picName']
397      **/
398     private void UpLoadPic(
399             int requestCode,
400             String url,
401             String[] keys,
402             String[] values,
403             String picName,
404             String streamName,
405             Bitmap bit,
406             LghHttpSingleListener listener
407     ){
408         String twoHyphens = "--";   /** 一定要是 2行 */
409         String boundary = "******"; /** 数据包分割线可以自定义 */
410         try{
411             HttpURLConnection httpURLConnection = getHttpUrlConnection(url,"POST");
412             httpURLConnection.setUseCaches(false);
413             httpURLConnection.setDoOutput(true);
414             httpURLConnection.setChunkedStreamingMode(1024 * 256); /** 一次传输的块大小 */
415             /** 数据 --------包头-------- 格式组装 */
416             httpURLConnection.setRequestProperty("Connection","Keep-Alive");
417             httpURLConnection.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);
418             /** 数据 --------包体-------- 格式组装*/
419             DataOutputStream body = new DataOutputStream(httpURLConnection.getOutputStream());
420             /** \r\n 是换行 */
421             body.writeBytes(twoHyphens+boundary+"\r\n"); /** 先写分隔符,标志和上面的头分开 */
422             body.writeBytes(
423                     "Content-Disposition:form-data;" +
424                             "name=\"" + streamName + "\";" +
425                             "filename=\"" + picName + "\"" + "\r\n"
426             );
427             /** 写文本数据体 */
428             body.writeBytes("\r\n");
429             if(keys!=null && values!=null){
430                 body.writeBytes(twoHyphens+boundary+"\r\n");
431                 body.writeBytes("Content-Disposition:form-data;");
432                 commonCombinePostText(keys,values,body);
433                 body.writeBytes("\r\n");
434             }
435             /** -------下面开始写图片二进制------- */
436             /** 下面是先压缩 */
437             int compress = 100;
438             ByteArrayOutputStream baos = new ByteArrayOutputStream();
439             bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
440             if(IsOpenCompress){
441                 while (baos.toByteArray().length / 1024 > CompressLimit) {
442                     baos.reset();
443                     compress -= 10;
444                     if(compress==0){
445                         bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
446                         break;
447                     }
448                     bit.compress(Bitmap.CompressFormat.JPEG, compress, baos);
449                 }
450             }
451             /** 开始写 */
452             InputStream picStream = new ByteArrayInputStream(baos.toByteArray());
453             byte[] buffer = new byte[10*1024];
454             int count;
455             while((count = picStream.read(buffer))!=-1){
456                 body.write(buffer,0,count);
457             }
458             picStream.close();
459             body.writeBytes("\r\n");
460             body.writeBytes(twoHyphens + boundary + twoHyphens +"\r\n");
461             body.flush();
462             /** 写完 */
463             sendMessage(Success,requestCode,commonGetResult(httpURLConnection,listener));
464             body.close();
465         }catch (MalformedURLException e){
466             dealWithException(e,listener);
467         } catch (SocketTimeoutException e){
468             dealWithException(e,listener);
469         } catch (ProtocolException e) {
470             dealWithException(e,listener);
471         } catch (UnsupportedEncodingException e) {
472             dealWithException(e,listener);
473         } catch (IOException e) {
474             dealWithException(e,listener);
475         }
476     }
477 
478     /** 公共部分,异常集合处理 */
479     private void dealWithException(
480             Exception e,
481             LghHttpSingleListener lghHttpListeners)
482     {
483         HttpDataBean bean = new HttpDataBean();
484         bean.setListeners(lghHttpListeners);
485         if(e instanceof MalformedURLException){
486             Log.d(TAG, "链接格式有问题 "+e.toString());
487             sendMessage(UrlFailed,bean);
488         }else if(e instanceof SocketTimeoutException){
489             Log.d(TAG, "连接超时 "+e.toString());
490             sendMessage(TimeOut,bean);
491         }else if(e instanceof ProtocolException){
492             Log.d(TAG, "协议异常,注意不要多次连接 " + e.toString());
493             sendMessage(ProtocolFailed, bean);
494         }else if(e instanceof UnsupportedEncodingException){
495             Log.d(TAG, "编码类型异常 " + e.toString());
496             sendMessage(EncodingFailed, bean);
497         }else if(e instanceof IOException){
498             Log.d(TAG, "io 异常 " + e.toString());
499             sendMessage(IOFailed,bean);
500         }
501     }
502 
503     /** 获取一个HttpUrlConnection,合并一些公共部分 */
504     private static HttpURLConnection getHttpUrlConnection
505             (String url,String requestWay) throws IOException {
506         Log.d(TAG,"url is "+url);
507         URL mRrl = new URL(url);
508         HttpURLConnection httpURLConnection = (HttpURLConnection) mRrl.openConnection();
509         httpURLConnection.setRequestMethod(requestWay);
510         httpURLConnection.setRequestProperty("Charset", "UTF-8");
511         httpURLConnection.setConnectTimeout(5 * 1000);
512         return httpURLConnection;
513     }
514 
515     /** 获取结果公共部分 */
516     private HttpDataBean commonGetResult(
517             HttpURLConnection httpURLConnection,
518             LghHttpSingleListener listener
519     ) throws IOException {
520         if(httpURLConnection==null){
521             return null;
522         }
523         BufferedReader br = new BufferedReader
524                 (
525                         new InputStreamReader(httpURLConnection.getInputStream(),"UTF-8"),
526                         8*1024
527                 );
528         StringBuffer resultBuffer = new StringBuffer("");
529         String line;
530         while ((line = br.readLine())!=null){
531             resultBuffer.append(line);
532         }
533         HttpDataBean bean = new HttpDataBean();
534         bean.setResponse(resultBuffer.toString());
535         bean.setListeners(listener);
536         br.close();
537         return bean;
538     }
539 
540     /** 组合 post 文本数据公共部分 */
541     private OutputStream commonCombinePostText(
542             String[] keys,
543             String[] values,
544             OutputStream outputStream) throws IOException
545     {
546         StringBuffer requestStr = new StringBuffer();
547         int keysLength = keys.length;
548         for(int i=0;i<keysLength;i++){
549             requestStr.append(keys[i]+"="+values[i]+"&");
550         }
551         outputStream.write(requestStr.toString().getBytes());
552         return outputStream;
553     }
554 
555     /** 接口分离 */
556     private interface LghHttpBaseListenr{
557         void onFailed(int type);
558 //        void onUrlFailed();
559 //        void onTimeOut();
560 //        void onProtocolFailed();
561 //        void onEncodingFailed();
562 //        void onIoFailed();
563     }
564 
565     /** 全局有 requestCode 区分 */
566     public interface LghHttpGlobleListener extends LghHttpBaseListenr{
567         void onSuccess(int requestCode,String response);
568     }
569 
570     /** 单一的没 requestCode 区分 */
571     public interface LghHttpSingleListener extends LghHttpBaseListenr{
572         void onSuccess(String response);
573     }
574 
575 }

用法例子

  1 package lgh.httpdemo;
  2 
  3 import android.graphics.BitmapFactory;
  4 import android.os.Bundle;
  5 import android.support.v7.app.AppCompatActivity;
  6 import android.util.Log;
  7 import android.widget.Toast;
  8 
  9 public class MainActivity extends AppCompatActivity {
 10 
 11     private LghHttp lghHttp = LghHttp.getInstance();
 12 
 13     @Override
 14     protected void onCreate(Bundle savedInstanceState) {
 15         super.onCreate(savedInstanceState);
 16         setContentView(R.layout.activity_main);
 17 
 18         /** Example 1 */
 19         /** 使用全局接口并发起 post 操作 */
 20         lghHttp.setGloblelghHttpListeners(new LghHttp.LghHttpGlobleListener() {
 21             @Override
 22             public void onFailed(int type) {
 23                 switch (type) {
 24                     case LghHttp.UrlFailed:
 25 
 26                         break;
 27                     case LghHttp.Success:
 28 
 29                         break;
 30                     case LghHttp.TimeOut:
 31 
 32                         break;
 33                     /**  .... */
 34                 }
 35             }
 36 
 37             @Override
 38             public void onSuccess(int requestCode, String response) {
 39                 Log.d("zzzzz", "LghHttpGlobleListener do post response "
 40                         + response + " requestCode is " + requestCode);
 41                 switch (requestCode) {
 42                     case 123:
 43                         /** 对应操作 */
 44                         break;
 45                 }
 46             }
 47 
 48         });
 49         for(int i=0;i<30;i++){
 50             final int j = i;
 51             lghHttp.doPost
 52                     (
 53                             j,
 54                             "http://121.42.190.18/ydnurse/Controller/noteController.php?func=GetNote",
 55                             null
 56                     );
 57         }
 58         // 带有键值
 59         lghHttp.doPost
 60                 (
 61                         145,
 62                         "http://121.42.190.18/ydnurse/Controller/noteController.php?func=GetNote",
 63                         new String[]{"userName","userAge","userSex"},
 64                         new String[]{"林冠宏","21","Box"},
 65                         null
 66                 );
 67         
 68         /** -----测试下面的例子,要把全局的接口 LghHttpGlobleListener 设置为 NUll----- */
 69         /** Example 2 */
 70         lghHttp.doGet
 71                 (
 72                         123,
 73                         "http://121.42.190.18/ydnurse/Controller/noteController.php?func=GetNote",
 74                         new LghHttp.LghHttpSingleListener() {
 75                             @Override
 76                             public void onSuccess(String response) {
 77 
 78                             }
 79 
 80                             @Override
 81                             public void onFailed(int type) {
 82 
 83                             }
 84                         }
 85                 );
 86         /** UpPic Example 3 */
 87 
 88         lghHttp.doUpLoadPic(
 89                 "http://www.xiangjiaoyun.com:8888/BCapp/BananaCloudServer/userPicUploadFile.php?" +
 90                         "account=13726204215&postid=0&type=2",
 91                 "123.jpg",
 92                 "uploadedfile",
 93                 BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)
 94         );
 95 
 96         lghHttp.doUpLoadPic(
 97                 1456,
 98                 "http://www.xiangjiaoyun.com:8888/BCapp/BananaCloudServer/userPicUploadFile.php?" +
 99                         "account=13726204215&postid=0&type=2",
100                 "123.jpg",
101                 "uploadedfile",
102                 BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher),
103                 new LghHttp.LghHttpSingleListener() {
104                     @Override
105                     public void onSuccess(String response) {
106                         Toast.makeText(MainActivity.this,"上传图片成功",Toast.LENGTH_SHORT).show();
107                     }
108 
109                     @Override
110                     public void onFailed(int type) {
111 
112                     }
113                 }
114         );
115     }
116 }

相关文章:

【ACM】杭电OJ 1284(待更)

#include<iostream> using namespace std; int main(){int n;while(cin>>n){int ans0; for(int i0;i<n/3;i){ //对3的个数进行枚举 int temp(n-3*i); //除了这i个3之外剩余的钱数 //temp/2,剩余部分换成2的总种类数&#xff0c;anstemp/21; //这…

c语言头文件中定义inline static相关函数的优劣

头文件中常见static inline函数&#xff0c;于是思考有可能遇到的问题&#xff0c;如头文件经常会被包含会不会产生很多副本&#xff1f;网上说法不一。于是自己验证。经过arm-none-eabi-gcc下测试后得出结论。 inline 关键字实际上仅是建议内联并不强制内联&#xff0c;gcc中O…

c语言inline详解

本文介绍了GCC和C99标准中inline使用上的不同之处。inline属性在使用的时候&#xff0c;要注意以下两点&#xff1a;inline关键字在GCC参考文档中仅有对其使用在函数定义&#xff08;Definition&#xff09;上的描述&#xff0c;而没有提到其是否能用于函数声明&#xff08;Dec…

【ACM】杭电OJ 2090

题目中给出的四舍五入的条件可以忽略不计了&#xff0c;因为提交的程序没有考虑四舍五入&#xff0c;照样AC了 printf("%.1lf\n",sum); AC代码&#xff1a; 写的有点复杂了&#xff0c;其实不用定义结构体也可以。 #include<iostream> #include <cstdi…

属性配置文件详解(2)(十七)

过命令行设置属性值 相信使用过一段时间Spring Boot的用户&#xff0c;一定知道这条命令&#xff1a;java -jar xxx.jar --server.port8888&#xff0c;通过使用–server.port属性来设置xxx.jar应用的端口为8888。 在命令行运行时&#xff0c;连续的两个减号--就是对applicatio…

git track远程分支

在本地初始化仓库&#xff0c;提交代码时会出现&#xff0c;上游为空&#xff0c;当前分支为选择&#xff0c;等错误提示。其实就是本地仓库分支和远程仓库分支并未进行关联&#xff0c;即本地分支未追踪到远程分支。 1.本地和远程的状态 本地&#xff1a; 本地所有的文…

HTMLDOM中三种元素节点、属性节点、文本节点的测试案例

HTML dom中常用的三种节点分别是元素节点、属性节点、文本节点。 具体指的内容可参考下图&#xff1a; 以下为测试用例: <!DOCTYPE html> <html><head><title>元素节点、属性节点、文本节点的测试</title><meta name"Author" conte…

【ACM】DFS 全排列 回溯

深入体会一下DFS&#xff0c;回溯 在一些OJ上endl和“\n”还是有区别的&#xff01;&#xff01;&#xff01; 题目链接&#xff1a;http://codevs.cn/problem/1294/ 方法一&#xff1a; #include <iostream> #include <cstdio> #include <cstring> usin…

(轉貼) 友達光電第五屆【A+種子暑期實習計畫】開始辦理報名 (News)

友達光電第五屆【A種子暑期實習計畫】開始辦理報名 友達光電以絕佳的團隊執行力&#xff0c;帶領台灣光電產業進入世界級的領域! 還在就學的你/妳&#xff0c;想成為世界級光電產業的A種子嗎? 把握最後的暑假加入友達的A種子實習團隊吧!! 【2008 A種子募集計畫】 實習期間&am…

binutils工具集用法

addr2line用于得到程序指令地址所对应的函数&#xff0c;以及函数所在的源文件名和行号。 在不少嵌入式开发环境中&#xff0c;编译器的名称往往不是gcc&#xff0c;而是想arm-rtems-gcc这样的&#xff0c;对于这种命名形式的编译器&#xff0c;读者通常可以找到arm-rtems-add…

【ACM】CODE[VS] 1215 (DFS)

题目描述 Description 在N*N的迷宫内&#xff0c;“#”为墙&#xff0c;“.”为路&#xff0c;“s”为起点&#xff0c;“e”为终点&#xff0c;一共4个方向可以走。从左上角&#xff08;(0,0)“s”&#xff09;位置处走到右下角&#xff08;(n-1,n-1)“e”&#xff09;位置处…

#大学#SQL基础学习笔记(02)

*数据分组select FAge,count(*) from TableName group by FAge (根据年龄进行分组)一般和聚合函数一起使用 *Having语句select FAge,count(*) from TableName group by FAge having count(*)>1 *聚合函数不能出现在where语句中 *having是对分组后的信息进行过滤&#xff0c;…

socket connect阻塞和非阻塞处理

建立socket后默认connect()函数为阻塞连接状态&#xff0c;在大多数实现中&#xff0c;connect的超时时间在75s至几分钟之间&#xff0c;想要缩短超时时间&#xff0c;可解决问题的两种方法&#xff1a;方法一、将socket句柄设置为非阻塞状态&#xff0c;方法二、采用信号处理函…

【ACM】CODE[VS] 2806(DFS)

感觉有点入了DFS的门槛&#xff0c;距离完全掌握还差得远呢 AC代码&#xff1a;运行时间为7ms #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn 26; int vis[maxn][maxn],col,line,flag,count; char map[…

scala学习手记34 - trait方法的延迟绑定

trait的方法的延迟绑定就是先混入的trait的方法会后调用。这一点从上一节的实例中也可以看出来。 下面再来看一个类似的例子&#xff1a; abstract class Writer {def write(message: String): String }trait UpperWriter extends Writer {abstract override def write(message…

(原創) Altera Technology Roadshow 2011 Taipei (SOC) (Quartus II) (Nios II) (Qsys)

Abstract這是我第一次參加Altera一年一度的Technology Roadshow。 Introduction 今年的Altera Technology Roadshow是在台北喜來登大飯店舉行。 位置在喜來登飯店的B2。 講師的講台。 當天的會場布置。 當天的演講內容&#xff0c;主要是台灣Altera兩家代理商Galaxy與Arrow的FA…

git-flow工作流说明

本文以一虚拟项目为例&#xff0c;描述了Git Flow在项目中的应用&#xff1b;还以此为主线&#xff0c;以表格形式给出了速查手册&#xff1b;最后&#xff0c;结合这两点介绍了一个基于Git Flow的项目实例。 希望这篇文章能够帮助Git初学者尽快上手。 1.1 什么是Git Fl…

2015湖南省省赛 阶乘除法 暴力

阶乘除法Time Limit:5000MS Memory Limit:65535KB 64bit IO Format: NBUT 1643Description 输入两个正整数 n, m,输出 n!/m!,其中阶乘定义为 n! 1*2*3*...*n (n>1)。 比如,若 n6, m3,则 n!/m!6!/3!720/6120。 是不是很简单?现在让我们把问题反过来:输入 kn!/m!,找到…

【ACM】POJ 1664

现在还不能理解为什么 至少有一个盘子用f(m,n-1)表示就可以了 AC: #include <iostream> #include <cstdio> using namespace std; int f(int m,int n) {if(m1 || n1 || m0) return 1;else if(m<n) return f(m,m);else{return f(m-n,n)f(m,n-1);} } int mai…

高效程序员的 7 个共同特征

导读&#xff1a;要想成为一个伟大的程序员&#xff0c;需要的可不仅仅是能够编写出可以正常运行的代码。Justin James给出了能够成为业内顶尖高手的程序员应该具有的几个典型特质。 要想成为高效的程序员&#xff0c;你需要具备一定的综合素质才能够让你用你所掌握的技能、经验…

Openstack组件实现原理 — Keystone认证功能

前言Keystone实现始终围绕着Keystone所实现的功能来展开&#xff0c;所以在理解其实现之前&#xff0c;建议大家尝试通过安装Keystone这一个过程来感受Keystone在Openstack架构中所充当的角色。下面给出了Keystone-M的安装过程。Keystone安装列表Openstack组件部署 — Overview…

unity test相关

http://www.throwtheswitch.org/unity

【小贴士】在线画流程图工具

https://c.runoob.com/more/shapefly-diagram/

Unity3D笔记 GUI 一

要实现的功能&#xff1a; 1、个性化Windows界面  2、减少个性化的背景图片尺寸  3、个性化样式ExitButton和TabButton  4、实现三个选项卡窗口 一、个性化Windows界面 1.1、创建一个空的GameObject、在Project中新建GUI Skin 用于绘制Windows图片 1.2 GUI Skin设置 1.3效…

gdb相关(栈和寄存器)

GDB的常用调试命令大家可以查阅gdb手册就可以快速的上手了&#xff0c;在这儿就不给大家分享了&#xff0c;需要的可以到GDB的官网去下载手册。这里重点分享下GDB调试中的一些寄存器和栈的相关知识用于解决下列gdb调试时的问题&#xff1a; 优化的代码在printf或其它glibc函数…

bzoj1688[Usaco2005 Open]Disease Manangement 疾病管理*

bzoj1688[Usaco2005 Open]Disease Manangement 疾病管理 题意&#xff1a; n头牛&#xff0c;d种疾病&#xff0c;每头牛都患一些疾病&#xff0c;现在要求选出最多的牛&#xff0c;使这些牛患病的种类数不超过k。n≤1000&#xff0c;d≤15 题解&#xff1a; 状压dp。f[i][S]表…

【数据结构】二叉树的应用。

1、分别采用递归和非递归的方式编写两个函数&#xff0c;求一棵给定二叉树中叶子节点的个数 2、返回一棵给定二叉树在中序遍历下的最后一个结点 3、假设二叉树采用链式方式存储&#xff0c;root为其根节点&#xff0c;p和q分别指向二叉树中任意两个结点&#xff0c;编写一个函…

我为我Windows Home Server 预热

这两天在下载Windows Home Server,所以找一些资料来看. 微软宣布Windows Home Server&#xff08;WHS&#xff09;正式推出&#xff0c;WHS是一个帮助家庭保护&#xff0c;连接并共享他们的数字媒体与文档的新解决方案。用户可以从各大在线商店进行预订&#xff0c;之后会在本月…

c 宏定义用法#define

转自&#xff1a;https://blog.csdn.net/boring_wednesday/article/details/78756696 宏定义 语法 #define name Stuff #define PI 3.14 //定义一个M&#xff0c;值为3.14 #define DO_FOREVER for(;;) //定义一个死循环 #define REG register //定义REG来作为register的别…

Linux学习笔记—— 权限及权限管理

权限及权限管理权限管理&#xff1a;r&#xff1a;w&#xff1a;x&#xff1a;三类用户&#xff1a;u&#xff1a;属主g&#xff1a;属组o&#xff1a;其他用户chown&#xff1a;改变文件属主&#xff08;只有管理员可以使用此命令&#xff09;# chown USERNAME file,...-R&…