最近遇到一个问题:我想用HttpClient来访问网络,发现怎么都无法new出HttpClient的对象,这我就有点摸不着头脑了。记得我之前都是可以使用这个类的,怎么突然间就用不了了。因为不知情,一下子就有点慌了。是我的写法不对?是Android studio开发工具出bug了?还是我的人品积累的不够?我想都没想,立即否定了第三点。(玩笑)
后来到网上查了下资料,发现在最新的Android SDK中,这个类已经被移除了。就是说Google在最新的SDK中不再支持使用HttpClient来访问网络了。这里就告诉我们一个十分重要的道理:在开发项目的时候,我们要尽量的不用或者是少用那些已经过时了(deprecated)的方法了,因为在后来更新的SDK版本中,我们可能就没法使用某些被Google丢弃的封装类了,然后程序就会报错。像我遇到的httpclient这个类就无法使用的情况。还有一点就是我们要时刻关注Google对Android 像是开发工具和SDK的更新情况等,这是作为一名Android 开发人员应该有的修养---目光要在技术的前端。

为什么HttpClient不可以使用了?这段时间里,到底发生了什么事?

原来,之前我们使用的HttpURLConnection和HttpClient的用法还是挺复杂的,而且其中的API多,不易扩展,容易出bug,稍不注意就会写出不少重复代码和error。所以,在2013年Google I/O大会上推出了一个新的网络通信框架——Volley。这套框架主要是用于一些不是很大量但是很频繁的网络访问,对于有大量下载的网络访问,它就表现的不行不行的了,这个是要注意的地方。

下面我们先开始来对volley作一个简单的介绍和简单的使用。

一、下载volley 的jar包。

这个jar包是开源的,网上一搜有大把,这里我提供一个下载的地址:点击打开链接 就可以下载了

二、把volley包导入我们的项目中。

copy到项目的libs目录下,右键--->add as libarary,最后ok。

三、开始使用volley框架。

在这里,我自己写了一个类,主要是用来使用volley几个常用的方法来访问网络,获取数据,以及每个方法的源码解释。


先上效果截图:

以及两个图片加载的方法效果图



然后,直接上代码吧,代码里面都有详细的解释了。

先是布局代码:很简单的一个scrollview包含一个多个控件的linearlayout,因为要显示的内容比较长,所用要scrollview。

<span style="font-size:14px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity">    <ScrollView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:scrollbars="vertical">        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical">            <EditText                android:id="@+id/ed_input"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_gravity="center_horizontal"                android:singleLine="true"                android:text="https://www.baidu.com"                android:textSize="20sp" />            <Button                android:id="@+id/btn_getdate"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:text="URLConnection方式获取网络数据" />            <Button                android:id="@+id/btn_volleyget"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginTop="3dp"                android:text="volley-GET方式获取网络数据" />            <Button                android:id="@+id/btn_volleypost"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginTop="3dp"                android:text="volley-POST方式获取网络数据" />            <Button                android:layout_marginTop="3dp"                android:id="@+id/btn_volleyJSON_obj"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:text="volleyJSONobject获取网络object对象数据" />            <Button                android:id="@+id/btn_volleyJSON_arr"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginTop="3dp"                android:text="volley-JSONarray获取往array对象数据" />            <Button                android:id="@+id/btn_getimg"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginTop="3dp"                android:text="volley-ImageLoader加载图片" />            <Button                android:id="@+id/btn_NetworkImageView"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginTop="3dp"                android:text="volley-NetworkImageView加载图片" />            <ImageView                android:id="@+id/img_show1"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:scaleType="fitCenter" />            <ImageView                android:id="@+id/img_show"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:scaleType="fitCenter" />            <com.android.volley.toolbox.NetworkImageView                android:id="@+id/networkImageView"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_centerHorizontal="true"                android:layout_marginTop="10dp" />            <TextView                android:id="@+id/tv_show"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:gravity="center"                android:text="@string/hello_world"                android:textSize="20sp" />        </LinearLayout>    </ScrollView></LinearLayout></span>


再然后是主要的java代码实现,里面有很详细的用法介绍和源码解释了,大家可以认真看看。

<span style="font-size:14px;">package com.yaojt.com.httptest;import android.app.Activity;import android.graphics.Bitmap;import android.os.AsyncTask;import android.os.Bundle;import android.support.v4.util.LruCache;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.ImageView;import android.widget.TextView;import com.android.volley.Request;import com.android.volley.RequestQueue;import com.android.volley.Response;import com.android.volley.VolleyError;import com.android.volley.toolbox.ImageLoader;import com.android.volley.toolbox.JsonArrayRequest;import com.android.volley.toolbox.JsonObjectRequest;import com.android.volley.toolbox.NetworkImageView;import com.android.volley.toolbox.StringRequest;import com.android.volley.toolbox.Volley;import org.json.JSONArray;import org.json.JSONObject;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLConnection;public class MainActivity extends Activity {        private TextView tv_show;    private Button btn_getdate;    private String URL = "https://www.baidu.com";    private String URL1 = "http://m.weather.com";    private EditText ed_input;    private Button btn_volleyget;    private Button btn_volleypost;    private Button btn_volleyJSONobject, btn_volleyJSONarray;    private Button btn_getimg;    private ImageView img_show, img_show1;    private Button btn_NetworkImageView;    private HttpURLConnection conn;    private RequestQueue requestQueue;    private JsonObjectRequest jsonObjectRequest;    private JsonArrayRequest jsonArrayRequest;    private StringRequest requestPOST;    private StringRequest requestGET;    private NetworkImageView mNetworkImageView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        requestQueue = Volley.newRequestQueue(this); //一开始得到一个请求队列,主要是用于对网络请求的派件工作        initViews();        initListener();    }    /**     * 初始化控件     */    private void initViews(){        tv_show = (TextView) findViewById(R.id.tv_show);        btn_getdate = (Button) findViewById(R.id.btn_getdate);        ed_input = (EditText) findViewById(R.id.ed_input);        btn_volleyget = (Button) findViewById(R.id.btn_volleyget);        btn_volleypost = (Button) findViewById(R.id.btn_volleypost);        btn_volleyJSONobject = (Button) findViewById(R.id.btn_volleyJSON_obj);        btn_volleyJSONarray = (Button) findViewById(R.id.btn_volleyJSON_arr);        btn_getimg = (Button) findViewById(R.id.btn_getimg);        img_show = (ImageView) findViewById(R.id.img_show);        img_show = (ImageView) this.findViewById(R.id.img_show);        mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);        btn_NetworkImageView = (Button) findViewById(R.id.btn_NetworkImageView);        img_show1 = (ImageView) findViewById(R.id.img_show1);    }    /**     * 初始化监听器     */    private void initListener(){        btn_NetworkImageView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                NetworkImageViewGetImg(); //直接调用此方法,然后再布局中直接显示图片            }        });        btn_getimg.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                ImageLoaderGetImg();            }        });        btn_volleyJSONarray.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                URL1 = ed_input.getText().toString().trim();                volleyJSONarray();            }        });        btn_volleyJSONobject.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                URL = ed_input.getText().toString().trim();                volleyJSONobject();            }        });        btn_volleypost.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                URL = ed_input.getText().toString().trim();                volleyPOST();            }        });        btn_volleyget.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                URL = ed_input.getText().toString().trim();                volleyGET();            }        });        btn_getdate.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                URL = ed_input.getText().toString().trim();                asynctaskLOAD(URL);            }        });    }    /**     * 利用JsonObjectRequest来得到JSONObject对象     *     * Constructor which defaults to <code>GET</code> if <code>jsonRequest</code> is     * <code>null</code>, <code>POST</code> otherwise.     *     * //@see #JsonObjectRequest(int, String, JSONObject, Response.Listener, Response.ErrorListener)     * public JsonObjectRequest(String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener,         Response.ErrorListener errorListener) {            this(jsonRequest == null ? Request.Method.GET : Request.Method.POST, url, jsonRequest, listener, errorListener); //可以看到源码            //如果第二个参数传入的值!= null 的话,它会选择是post方式        }     */    private void volleyJSONobject() {        String url = "http://pipes.yahooapis.com/pipes/pipe.run?_id=giWz8Vc33BG6rQEQo_NLYQ&_render=json";        jsonObjectRequest = new JsonObjectRequest(url, null, new Response.Listener<JSONObject>() { //这里传入null,会选择是get方式            @Override            public void onResponse(JSONObject response) {                tv_show.setText("利用JsonObjectRequest得到的object对象为:" + response);            }        }, new Response.ErrorListener() {            @Override            public void onErrorResponse(VolleyError error) {                tv_show.setText("===>>利用JsonObjectRequest访问网络错误,错误信息为:" + error);            }        });        requestQueue.add(jsonObjectRequest);    }    /**     * 利用JsonArrayRequest得到JSONArray对象     *     * 源码:     * Creates a new request. 创建一个新的请求     *     * //@param url URL to fetch the JSON from     * //@param listener Listener to receive the JSON response     * //@param errorListener Error listener, or null to ignore errors.     *public JsonArrayRequest(String url, Response.Listener<JSONArray> listener, Response.ErrorListener errorListener) {            super(Request.Method.GET, url, null, listener, errorListener); //这里使用的是Request.Method.GET 方式      }     */    private void volleyJSONarray() {        jsonArrayRequest = new JsonArrayRequest(URL1, new Response.Listener<JSONArray>() { //它这里只有get方式            @Override            public void onResponse(JSONArray response) {                tv_show.setText("利用volley-JsonArrayRequest方式获取的的网络数据为:" + response.toString());            }        }, new Response.ErrorListener() {            @Override            public void onErrorResponse(VolleyError error) {                //因为我这里没有一个返回jsonarrayrequest的接口,所以这里返回的数据老是提示错误                tv_show.setText("利用volley-JsonArrayRequest方式访问错误,错误信息为:" + error);            }        });        requestQueue.add(jsonArrayRequest); //将请求加入到请求队列中区    }    /**     * 利用StringRequest得到String对象     *     * Creates a new request with the given method. 创建一个给定方式的请求     *     * //@param method the request {@link Request.Method} to use 参数一:请求方式get或者post     * //@param url URL to fetch the string at     * //@param listener Listener to receive the String response     * //@param errorListener Error listener, or null to ignore errors     * public StringRequest(int method, String url, Response.Listener<String> listener,            Response.ErrorListener errorListener) {                super(method, url, errorListener);                mListener = listener;            }     */    private void volleyPOST() {        requestPOST = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() { //指定为post方式            @Override            public void onResponse(String s) { //这里指定的是post方法                tv_show.setText("利用volley--POST方式得到的网络数据:" + s);            }        }, new Response.ErrorListener() {            @Override            public void onErrorResponse(VolleyError volleyError) {                tv_show.setText("利用volley--POST方式访问网络错误,错误信息为:" + volleyError.toString());            }        });        requestQueue.add(requestPOST); //最后要记得加入到请求队列中去    }    /**     * 默认利用GET方式得到string对象     * 看下面源码:     *     * Creates a new GET request. 创建一个新的get方式的请求     *     * //@param url URL to fetch the string at     * //@param listener Listener to receive the String response 这个是Response接口类里面的Listener方法     * //@param errorListener Error listener, or null to ignore errors 这个是Response接口类里面的ErrorListener方法     * public StringRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {          this(Request.Method.GET, url, listener, errorListener); //这里是默认的get方式       }     */    private void volleyGET() {        requestGET = new StringRequest(URL, new Response.Listener<String>() { //这个是默认的利用get方式访问网络 看注释源码            @Override            public void onResponse(String s) { //源码中默认的是get的方式                tv_show.setText("利用volley--GET方式得到的网络数据:" + s);            }        }, new Response.ErrorListener() {            @Override            public void onErrorResponse(VolleyError volleyError) {                tv_show.setText("利用volley--GET方式访问网络error,错误信息为:" + volleyError.toString());            }        });        requestQueue.add(requestGET); //最后要记得加入到请求队列中去    }    /**     * 利用AsyncTask异步任务来加载图片     *     * @param url     */    private void asynctaskLOAD(String url) {        new AsyncTask<String, String, String>() { //new一个匿名异步任务类实例,参数一:传入值;参数二:过程传出值;参数三:结果返回值;            @Override            protected String doInBackground(String... params) {                String str = "";                try {                    URL url = new URL(params[0]); //取得第一个参数URL地址                    URLConnection connection = url.openConnection(); //打开连接                    InputStream in = connection.getInputStream(); //得到输入流                    InputStreamReader isr = new InputStreamReader(in, "utf-8"); //将输入流包装成字符流,并指定编码格式                    BufferedReader br = new BufferedReader(isr);                    String line;                    while ((line = br.readLine()) != null) {                        str += line;                    }                    br.close(); //这里要关闭流,是先打开后关闭                    isr.close();                    in.close();                } catch (IOException e) {                    e.printStackTrace();                }                return str; //这里是结果返回值            }            @Override            protected void onPostExecute(String string) { //接收到结果返回值,并作处理                tv_show.setText("利用AsyncTask异步任务方式得到的网络数据:" + string);            }        }.execute(url); //记得要执行,这个异步任务才会执行    }    /**     * 利用ImageLoader来加载网络图片     * getImageListener(ImageView view, int defaultImageResId, int errorImageResId) //这个方法就是传入一个请求队列和一个图片的缓存即可     * 第一个参数:显示图片的ImageView     * 第二个参数:默认显示的图片资源     * 第三个参数:加载错误时显示的图片资源     *     * 我们关键来看看ImageListener getImageListener(final ImageView view,final int defaultImageResId, final int errorImageResId)这个方法是得到     * 一个图片加载的监听器和两个回调函数     * 看到第一个参数的解释:The imageView that the listener is associated with.和监听器关联的img,其实这个是你加载了的图片要显示的位置     * 我们可以直接看到它的关键源码:     * view.setImageResource(errorImageResId); //当错误时显示的图片,第三个参数     * view.setImageBitmap(response.getBitmap()); //成功加载的图片显示     * view.setImageResource(defaultImageResId); //在加载过程中显示的默认图片,代替失败或者是成功前的图片显示     * 所以,我们只要将我们显示图片的控件传进去就可以了     */    //这里加载一张图片在imgv上显示    public void ImageLoaderGetImg() {        final LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>(8); //缓存为8m        //这里new一个缓存空间,也可以使用在最后面一个继承自ImageLoader.ImageCache的类来做,这里就不演示了        ImageLoader imageLoader = new ImageLoader(requestQueue, new ImageLoader.ImageCache() { //传入网络请求队列和图片的缓存对象            @Override            public Bitmap getBitmap(String key) {                return lruCache.get(key);            } //将图片存储起来,下次运行时会优先选择在内存中是否有这个图片的缓存,有则直接读取出来,没有再到网上去取数据            @Override            public void putBitmap(String key, Bitmap bitmap) {                lruCache.put(key, bitmap);            }        });        String url = "http://e.hiphotos.baidu.com/image/pic/item/d0c8a786c9177f3e6bf9623a75cf3bc79f3d5633.jpg";        ImageLoader.ImageListener listener = ImageLoader.getImageListener(img_show, R.drawable.imgv1, R.drawable.imgv2); //传入URL,默认图片和失败图片        imageLoader.get(url, listener); //最后要运行调用get方法,传入url和监听器        //指定图片允许的最大宽度和高度//        imageLoader.get(url,listener, 200, 200);    }    /**     *     * 利用NetworkImageView显示网络图片,这里要在布局中创建一个com.android.volley.toolbox.NetworkImageView控件,看布局代码     * 我们来看下setImageUrl这个方法的执行流程     *     * 方法的解释:给NetworkImageView这个控件设置一个给定URL路径的图片。     * 此方法会立即在缓存中查找有无此图片;有则显示,没有则通过调用NetworkImageView     * 方法显示一个默认加载图片并且去加载此图片。     *     * 在方法内部会调用     * loadImageIfNecessary(false); // The URL has potentially changed. See if we need to load it.     * 我们来走下这个方法:     * 1、先得到此控件的宽高;如果宽高为0,则返回;     * 2、判断传入url是否为空;为空则将请求取消,设置控件的图片为null,并返回;     * 3、判断此控件的前一个请求是否要取消它(前提是有前一个请求),这里有两个情况:一、同一个     * url请求,返回;二、不是同一个url请求,取消前一个请求,然后下一步;     * 4、调用ImageContainer newContainer = ImageLoader.get()方法去加载新的url图片,new一个ImageListener图片监听方法,成功则显示     * 加载的图片,不成功则加载错误显示的图片;(这里面还有一个布尔值参数isInLayoutPass = false     * 重新开新线程去回调onRespose方法,默认是没有调用的);     * 5、最后将控件的mImageContainer更新为新的newContainer ;     *     */    //此方法是在布局的NetworkImageView控件上加载显示一张图片    private void NetworkImageViewGetImg() {        String imageUrl = "http://f.hiphotos.baidu.com/image/pic/item/c9fcc3cec3fdfc03777a357fd03f8794a5c226f3.jpg";        final LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>(8);        ImageLoader.ImageCache imageCache = new ImageLoader.ImageCache() { //创建一个图片缓存实例            @Override            public void putBitmap(String key, Bitmap value) {                lruCache.put(key, value);            }            @Override            public Bitmap getBitmap(String key) {                return lruCache.get(key);            }        };        ImageLoader imageLoader = new ImageLoader(requestQueue, imageCache);        mNetworkImageView.setTag("url");        mNetworkImageView.setImageUrl(imageUrl, imageLoader);    }    /**     * bitmap存储类,继承自ImageLoader.ImageCache。这里没有用到     */    private class BitmapCache implements ImageLoader.ImageCache {        private LruCache<String, Bitmap> cache;        public BitmapCache() {            cache = new LruCache<String, Bitmap>(8 * 1024 * 1024) { //缓存空间为8m                @Override                protected int sizeOf(String key, Bitmap bitmap) {                    return bitmap.getRowBytes() * bitmap.getHeight();                }            };        }        @Override        public Bitmap getBitmap(String url) {            return cache.get(url);        }        @Override        public void putBitmap(String url, Bitmap bitmap) {            cache.put(url, bitmap);        }    }}</span>
以上是volley框架的代码示例,比较长,但是是比较实用的。

总的来讲,volley框架并不会很难懂,因为开发volley框架本来就是让大家的开发过程变得很简练简约。所以学习此框架还是很不错的。

到此为止了,若哪里理解有偏差,请指教!


更多相关文章

  1. Android设计模式系列--模板方法模式
  2. android ndk生成第三方库的so方法(ndk-build,Application.mk,Andro
  3. Android之Activity之间的数据通信方式大全(一)
  4. Android中WebView加载本地Html,与JavaScript与Android方法相互传
  5. [Android]应用界面创建控件的两种方式
  6. Android的JNI总结
  7. Android中Fragment碎片解析
  8. Android从系统Gallery获取图片具体实现
  9. Android开源项目分包方式学习(eoe、oschina、github)

随机推荐

  1. Gradle使用手册
  2. linux 下编译 vlc
  3. FregClient进程,创建一个BpFregService类
  4. 【转】android让普通app不被其他程序kill
  5. Android 阻断adb install
  6. android中webview开启了硬件加速后会出现
  7. android Vibrator使用示例
  8. android:style.xml
  9. Android(安卓)icon files
  10. Android实现多层级Spinner列表选项实时更