android--网络编程

2016-08-25  本文已影响127人  MrMagicWang
Http请求方式
方法 描述
GET 请求指定url的数据,请求体为空(例如打开网页)。
POST 请求指定url的数据,同时传递参数(在请求体中)。
HEAD 类似于get请求,只不过返回的响应体为空,用于获取响应头。
PUT 从客户端向服务器传送的数据取代指定的文档的内容。
DELETE 请求服务器删除指定的页面。
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS 允许客户端查看服务器的性能。
TRACE 回显服务器收到的请求,主要用于测试或诊断。

常用只有Post与Get。

HttpURLConnection的用法

申明网络权限!

<uses-permission android:name="android.permission.INTERNET"/>

使用post请求方式

public String post(String url, String content) {
    HttpURLConnection conn = null;
    try {
        // 创建一个URL对象
        URL mURL = new URL(url);
        // 调用URL的openConnection()方法,获取HttpURLConnection对象
        conn = (HttpURLConnection) mURL.openConnection();

        conn.setRequestMethod("POST");// 设置请求方法为post
        conn.setReadTimeout(5000);// 设置读取超时为5秒
        conn.setConnectTimeout(10000);// 设置连接网络超时为10秒
        conn.setDoOutput(true);// 设置此方法,允许向服务器输出内容

        // post请求的参数
        String data = content;
        // 获得一个输出流,向服务器写数据,默认情况下,系统不允许向服务器输出内容
        OutputStream out = conn.getOutputStream();// 获得一个输出流,向服务器写数据
        out.write(data.getBytes());
        out.flush();
        out.close();

        int responseCode = conn.getResponseCode();// 调用此方法就不必再使用conn.connect()方法
        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;
}

使用GET请求方式

public 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;
}

getStringFromInputStream方法

private String getStringFromInputStream(InputStream is)
        throws IOException {
    //字节数组输出流在内存中创建一个字节数组缓冲区,
    //所有发送到输出流的数据保存在该字节数组缓冲区中。
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len = -1;
    while ((len = is.read(buffer)) != -1) {
        os.write(buffer, 0, len);
       //将指定字节数组中从偏移量off开始的len个字节写入此字节数组输出流。
    }
    is.close();
    // 把流中的数据转换成字符串,采用的编码是utf-8(模拟器默认编码)
    String state = os.toString();
    os.close();
    return state;
}

网络请求响应码
200:表示成功,正常结果;
302:表示重定向,转到别的站点;
304:表示未修改;
404:表示找不到资源;
500:表示内部服务器错误;

使用AsyncTask异步任务

做Android应用的时候,进程需要在一个子线程执行一些耗时的操作,例如下载等。这种情况我们一般使用Handler和线程结合处理,子线程负责处理耗时操作,然后通知Handler处理UI更新。Handler和子线程结合处理适合对精度控制要求比较高或者任务耗时比较长或者比较反复的情况。除了Handler和线程结合使用,Android也为我们提供了另外一种选择,也就是AsyncTask。

AsyncTask被设计为Thread 和 Handler一个帮助类并且不会建立一个通用的线程框架。AsyncTasks适用于耗时较短的操作。

如果需要保持线程长时间运行,android官方开发者网站推荐使用java.util.concurrent包里提供的不同的API,例如Executor,ThreadPoolExecutor 和 FutureTask。

1.android.os.AsyncTask的定义

public abstract class AsyncTask<Params, Progress, Result>

这些参数都是泛型定义,所以我们可以定义自己的数据类型作为参数,另外如果不需要相关传输,可以传入Void即可。

2.AsyncTask中的方法

执行异步任务,启动异步任务方法:excute(Params... params)

public final AsyncTask<Params, Progress, Result> execute(Params... params) 
{
   return executeOnExecutor(sDefaultExecutor, params);
}

execute()被调用后立即执行的方法onPreExecute(),可以做一些任务初始化

// 在后台work之前
 // 主线程
protected void onPreExecute() { }

在onPreExecute()执行后执行的方法doInBackground( )
在此方法中可以执行一些耗时操作,方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress()来更新进度信息

//不能在里面更新UI,否则有异常。
protected abstract Result doInBackground(Params... params);
protected void onProgressUpdate(Progress... values){ }

doInBackground执行完后,会回调onPostExecute方法,用于更新界面信息

//执行完之后在主线程中
protected void onPostExecute(Result result) { }
3.使用AsyncTask

使用AsyncTask必须创建一个子类。子类至少重写一个方法 (doInBackground(Params…)),通常重写的第二个是(onPostExecute(Result))。

使用AsyncTask下载图片

private class DownLoad extends AsyncTask<String, Integer, String> 
{
    //onPreExecute方法在execute()后执行
    @Override  
    protected void onPreExecute() 
    {  
        Log.i(TAG, "onPreExecute() enter");  
        mShowLogTextView.setText("onPreExecute。。。begin downLoad");  
    }  
      
    //doInBackground方法内部执行后台任务,不能在里面更新UI,否则有异常。
    @Override  
    protected String doInBackground(String... params) 
    {  
        Log.i(TAG, "doInBackground(String... params) enter");  
        
        URL imageUrl=null;
        try 
        {
            imageUrl=new URL(params[0]);
        } 
        catch (MalformedURLException e) 
        {
            e.printStackTrace();
            Log.e(TAG, e.getMessage());
        }
        try
        {
            //使用HttpURLConnection打开连接
            HttpURLConnection urlConn=(HttpURLConnection)imageUrl.openConnection();
            urlConn.setDoInput(true);
            urlConn.connect();
            //将得到的数据转化成InputStream
            InputStream is=urlConn.getInputStream();
            //将InputStream转换成Bitmap
            mDownLoadBtBitmap=BitmapFactory.decodeStream(is);
            is.close();
            //不能在这里更新UI,否则有异常******
            //mNetImageView.setImageBitmap(bitmap);
        }catch(IOException e)
        {
            Log.e(TAG,e.getMessage());
        }
        
        return "ok";
    }  
      
    //onProgressUpdate方法用于更新进度信息  
    @Override  
    protected void onProgressUpdate(Integer... progresses) 
    {  
        Log.i(TAG, "onProgressUpdate(Integer... progresses) enter");  

        mShowLogTextView.setText("onProgressUpdate Downloading...");  
    }  
      
    //onPostExecute用于doInBackground执行完后,更新界面UI。
    //result是doInBackground返回的结果
    @Override  
    protected void onPostExecute(String result) 
    {  
        Log.i(TAG, "onPostExecute(Result result) called");  
        mShowLogTextView.setText("Down load finish result="+result);  
          
        mNetImageView.setImageBitmap(mDownLoadBtBitmap);
    }  
      
    //onCancelled方法用于取消Task执行,更新UI
    @Override  
    protected void onCancelled() 
    {  
        Log.i(TAG, "onCancelled() called");  
        mShowLogTextView.setText("onCancelled");  
    }  
}
public void onClick(View v)
{
    if (v==mPlayMusicButton)
    {
        //传入下载图片的地址 
         mDownLoad.execute("http://www.baidu.com/img/bdlogo.gif");
    } 
} 

AsyncTask使用的时候需要注意的事项

AsyncTask的doInBackground方法默认是返回 true ,表示任务完成,如果想返回具体的数据呢,怎么做。如果Activity被销毁了,还会执行到postexcutd方法吗?
如果需要返回具体的数据,在创建子类继承AsyncTask时,指定泛型的时候将第三个泛型值指定为需要返回具体数据的类型,然后在doInBackground任务完成时,return具体的数据即可。

AsyncTask会一直执行, 直到doInBackground()方法执行完毕。然后,如果 cancel(boolean)被调用, 那么onCancelled(Result result) 方法会被执行;否则,执行onPostExecute(Result result) 方法。如果我们的Activity销毁之前,没有取消 AsyncTask,这有可能让我们的AsyncTask崩溃(crash)。因为它想要处理的view已经不存在了。所以,我们总是必须确保在销毁活动之前取消任务。总之,我们使用AsyncTask需要确保AsyncTask正确地取消。另外,即使我们正确地调用了cancle() 也未必能真正地取消任务。因为如果在doInBackgroud里有一个不可中断的操作,比如BitmapFactory.decodeStream(),那么这个操作会继续下去。

上一篇 下一篇

猜你喜欢

热点阅读