Android网络请求Get&Post

Http请求方式

方法                      描述
GET         请求指定url的数据,请求体为空(例如打开网页)。

POST        请求指定url的数据,同时传递参数(在请求体中)。

HEAD        类似于get请求,只不过返回的响应体为空,用于获取响应头。

PUT         从客户端向服务器传送的数据取代指定的文档的内容。

DELETE      请求服务器删除指定的页面。

CONNECT     HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

OPTIONS     允许客户端查看服务器的性能。

TRACE       回显服务器收到的请求,主要用于测试或诊断。

记:常用只有Post与Get
  • Get方式
    在url中填写参数:

    http://xxxx.xx.com/xx.php?params1=value1&params2=value2

  • Post方式
    参数是经过编码放在请求体中的。编码包括x-www-form-urlencodedform-data
    x-www-form-urlencoded的编码方式是这样:
    tel=13637829200&password=123456
    form-data的编码方式是这样:
    —-WebKitFormBoundary7MA4YWxkTrZu0gW
    Content-Disposition: form-data; name=”tel”

  13637829200
  ----WebKitFormBoundary7MA4YWxkTrZu0gW
  Content-Disposition: form-data; name="password"

  123456
  ----WebKitFormBoundary7MA4YWxkTrZu0gW

x-www-form-urlencoded的优越性就很明显了,不过x-www-form-urlencoded只能传键值对
但是form-data可以传二进制。

因为url是存在于请求行中的。
所以Get与Post区别本质就是参数是放在请求行中还是放在请求体中
当然无论用哪种都能放在请求头中。一般在请求头中放一些发送端的常量。

  • Get是明文,Post隐藏
    移动端不是浏览器,不用https全都是明文。
  • Get传递数据上限XXX
    胡说。有限制的是浏览器中的url长度,不是Http协议,移动端请求无影响。Http服务器部分有限制的设置一下即可。
  • Get中文需要编码
    是真的…要注意。URLEncoder.encode(params, “gbk”);

上面说的是请求。下面说响应。
请求是键值对,但返回数据我们常用Json。
对于内存中的结构数据,肯定要用数据描述语言将对象序列化成文本,再用Http传递,接收端并从文本还原成结构数据。
对象(服务器)<–>文本(Http传输)<–>对象(移动端) 。

服务器返回的数据大部分都是复杂的结构数据,所以Json最适合。
Json解析库有很多Google的Gson,阿里的FastJson,HiJson等等
Gson的用法看这里

HttpURLConnection

  • 这是我个人封装的一个简单的工具类 供参考:
public class NetUtils {
    public static String post(String url, String content) {
        HttpURLConnection conn = null;
        try {
            //创建一个URL对象
            URL mURL = new URL(url);
            //调用URL的openConnection()方法,获取HttpURLConnection对象
            conn = (HttpURLConnection) mURL.openConnection();

            //设置请求方法为post  注意:这里必须是大写 小写可能不识别
            conn.setRequestMethod("POST");
            //设置读取超时为5秒
            conn.setReadTimeout(5000);
            //设置连接网络超时为10秒
            conn.setConnectTimeout(10000);
            //设置此方法,允许向服务器输出内容
            conn.setDoOutput(true);

            //post请求的参数
            String data = content;
            //获得一个输出流,向服务器写数据,默认情况下,系统不允许向服务器输出任何内容。
            OutputStream out = conn.getOutputStream();
            out.write(data.getBytes());
            //刷新输入的内容 不刷新可能会不显示内容
            out.flush();
            //关闭流
            out.close();

            //调用此方法就不必再使用conn.connect()方法
            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                InputStream is = conn.getInputStream();
                String response = getStringFromInputStream(is);
                return response;
            } else {
                throw new NetworkErrorException("response status is" + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
            //最终要执行的步骤
        } finally {
            //记得关闭连接
            if (conn != null) {
                conn.disconnect();
            }
        }
        return null;
    }

    public static String get(String url) {
        HttpURLConnection conn = null;
        try {
            //利用String url构建URL对象
            URL mURL = new URL(url);
            conn = (HttpURLConnection) mURL.openConnection();

            conn.setRequestMethod("GET");
            conn.setReadTimeout(5000);
            conn.setConnectTimeout(10000);

            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                InputStream is = conn.getInputStream();
                String response = getStringFromInputStream(is);
                return response;
            } else {
                throw new NetworkErrorException("response status is " + responseCode);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
        return null;
    }


    private static String getStringFromInputStream(InputStream is) {
        String state = null;
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        //代码板块 必须熟练
        byte[] buf = new byte[1024];
        int len;
        try {
            while ((len = is.read(buf)) != -1) {
                os.write(buf, 0, len);
            }
            is.close();
            //把流中的数据转换成字符串,采用的编码是utf-8(模拟器默认编码)
            state = os.toString();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return state;
    }

}
  • 注意网络权限!!毛糙容易被坑
  <uses-permission android:name="android.permission.INTERNET"/>

同步&异步

  • 这2个概念仅存在于多线程编程中。
    android中默认只有一个主线程,也叫UI线程。因为View绘制只能在这个线程内进行。
    所以如果你阻塞了(某些操作使这个线程在此处运行了N秒)这个线程,这期间View绘制将不能进行,UI就会卡。所以要极力避免在UI线程进行耗时操作。
    网络请求是一个典型耗时操作。
    通过上面的Utils类进行网络请求只有一行代码。
NetUtils.get("http://www.baidu.com");//这行代码将执行几百毫秒。

如果你这样写

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String response = Utils.get("http://www.163.com");
    }

就会卡死线程
这就是同步方式。直接耗时操作阻塞线程直到数据接收完毕然后返回。Android不允许的。

  • 异步方式:
    //在主线程new的Handler,就会在主线程进行后续处理。
    private Handler handler = new Handler();
    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        new Thread(new Runnable() {
            @Override
            public void run() {
                    //从网络获取数据
                final String response = NetUtils.get("http://www.baidu.com");
                    //向Handler发送处理操作
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                            //在UI线程更新UI
                        textView.setText(response);
                    }
                });
            }
        }).start();
    }

在子线程进行耗时操作,完成后通过Handler将更新UI的操作发送到主线程执行。这就叫异步。
Handler是一个Android线程模型中重要的东西,与网络无关便不说了。关于Handler不了解就先去
Google一下。

  • 异步&回调。
    这是通过回调封装的Utils类。
public class AsyncNetUtils {
    public interface Callback {
        void onResponse(String response);
    }

    /**
     * GET方法
     *
     * @param url
     * @param callback
     */
    public static void get(final String url, final Callback callback) {
        final Handler handler = new Handler();
        new Thread(new Runnable() {
            @Override
            public void run() {
                final String response = NetUtils.get(url);
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onResponse(response);
                    }
                });
            }
        }).start();
    }

    /**
     * POST方法
     *
     * @param url
     * @param content
     * @param callback
     */
    public static void post(final String url, final String content, final Callback callback) {
        final Handler handler = new Handler();
        new Thread(new Runnable() {
            @Override
            public void run() {
                final String response = NetUtils.post(url, content);
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onResponse(response);
                    }
                });
            }
        }).start();

    }

}

然后使用方法:

public class MainActivity extends AppCompatActivity {
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.tv);
        // 给文本内容加滚动条
        tv.setMovementMethod(ScrollingMovementMethod.getInstance());
        AsyncNetUtils.get("http://www.163.com", new AsyncNetUtils.Callback() {
            @Override
            public void onResponse(String response) {
                tv.setText(response);
            }
        });

    }  

}
  • 需要优化的地方还很多:(待更…)
  • 每次都new Thread,new Handler消耗过大
  • 没有异常处理机制
  • 没有缓存机制
  • 没有完善的API(请求头,参数,编码,拦截器等)与调试模式
  • 没有Https

猜你喜欢

转载自blog.csdn.net/life_s/article/details/79705904