• Volly框架的使用基础版及使用中的一些坑 Ace 网络篇(三)


    直接把注释粘过来:


    * Volley使用讲解:
    * 要实现网络数据请求主要要记住下面三步骤:
    * 1.创建RequestQueue对象
    * 2.创建XXRequest对象(XX代表String,JSON,Image等等)
    * 3.把XXRequest对象添加到RequestQueue中即可
    * 该通过Volley的静态方法newRequestQueue(Context)来获取一个请求队列对象
    * 内部设计有请求缓存,系统版本区分请求
    * 并且设计适合于高并发

    第一步 新建一个application ,并创建

    RequestQueue
    /*
    *Acein20160202
    */
    public class MyApplication extends Application {
        private static RequestQueue mQueue;
        @Override
        public void onCreate() {
            // TODO Auto-generated method stub
            super.onCreate();
             mQueue = Volley.newRequestQueue(getApplicationContext());
        }
        public static RequestQueue getRequstQueue() {
            return mQueue;
        }
    
    }

    然后在   /VollyDemo/AndroidManifest.xml     <application> 标签中添加   : 添加红色部分 再添加一个网络请求权限

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.vollydemo"
        android:versionCode="1"
        android:versionName="1.0" >
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-sdk
            android:minSdkVersion="14"
            android:targetSdkVersion="18" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" 
            android:name="com.example.vollydemo.MyApplication">
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    创建StringRequest对象来发起HTTP请求,然后接收相应数据:
    *
    * 创建StringRequest对象传入四个参数:
    * 请求方法GET/POST/或者其他
    * 请求服务器的目标地址
    * 服务器数据成功响应回调
    * 服务器数据失败响应回调

    public class MainActivity extends Activity {
    
        private MyApplication mApplication;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            vollyGet();
            mApplication = new MyApplication();
        }
        
        public void vollyGet() {
            String url = "http://apis.juhe.cn/mobile/get?phone=15836300559&key=XXXXXXXXXXX你申请的keyXXXXXXXXXXXX";
            StringRequest stringRequest = new StringRequest(Method.GET, url, new Listener<String>() {
                //请求成功调用 
                @Override
                public void onResponse(String arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0, Toast.LENGTH_LONG).show();
                }
            }, new ErrorListener() {
                //请求失败调用
            
                @Override
                public void onErrorResponse(VolleyError arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            });
            stringRequest.setTag("getString");
            mApplication.getRequstQueue().add(stringRequest);
            
        }
    }

    这是最简单的String get 因为是给新手看的 所以 这样写很不优雅 但是给新手看很好,

    下面来看JSONget 

        public void vollyGet() {
            String url = "http://apis.juhe.cn/mobile/get?phone=15836300559&key=XXXXXXX你申请的keyXXXXXXXXXXXXX";
    
            
            JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Method.GET, url, null, new Listener<JSONObject>() {
    
                @Override
                public void onResponse(JSONObject arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            }, new ErrorListener() {
    
                @Override
                public void onErrorResponse(VolleyError arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            });
            jsonObjectRequest.setTag("jsonget");
            mApplication.getRequstQueue().add(jsonObjectRequest);
            
        }

    来看下StringRequst POST:跟GET唯一不同是 重写了 getParams方法 ,这样post的时候就会自动调用

            StringRequest stringRequest = new StringRequest(Method.POST, url, new Listener<String>() {
    
                @Override
                public void onResponse(String arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            }, new ErrorListener() {
    
                @Override
                public void onErrorResponse(VolleyError arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            }){
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("phone", "15836300559");
                    map.put("key", "f64ff5c4c517da17761f112d6c3c0da0");
                    return map;
                }
            };
            stringRequest.setTag("ace");
            mApplication.getRequstQueue().add(stringRequest);
        }

    来看JSonRequest的POST  非常有趣 JSonRequest 的Method.POST有很多的坑, 还有 网上那些写错的我就纳闷了 你是怎么得到返回数据的 ,或者说你真的实验了吗

    来! 看第一个坑:  跟StringRequst 一样 我重写了getparams方法.

       JsonObjectRequest  jsonObjectRequest = new JsonObjectRequest(Method.POST, url,null, new Listener<String>() {
    
                @Override
                public void onResponse(String arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            }, new ErrorListener() {
    
                @Override
                public void onErrorResponse(VolleyError arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            }){
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("phone", "15836300559");
                    map.put("key", "f64ff5c4c517da17761f112d6c3c0da0");
                    return map;
                }
            };
            stringRequest.setTag("ace");
            mApplication.getRequstQueue().add(stringRequest);
        }

    JsonObjectRequest构造中的参数传null,和StringRequest一样去重写getParams()方法来传参。貌似是没问题的?

    使用这段代码拿不到服务器返回的数据,反馈的结果是没有传参给服务器。那就看看参数最终是在哪里提交给服务器的。

    Debug HurlStack.java中的addBodyIfExists()这个方法,发现request.getBody()==null,也就是没有接收到参数。

    StringRequest可以重写getParams来传参是因为Request中的这个方法:

    public byte[] getBody() throws AuthFailureError {  
        Map<String, String> params = getParams();  
        if (params != null && params.size() > 0) {  
            return encodeParameters(params, getParamsEncoding());  
        }  
        return null;  
    }  

    重写的getParams的结果会传到这里。

    JsonObjectRequest不能重写getParams来传参是因为JsonRequest中的这个方法:

    JsonRequest.java

    @Override  
    public byte[] getBody() {  
        try {  
            return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);  
        } catch (UnsupportedEncodingException uee) {  
            VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",  
                    mRequestBody, PROTOCOL_CHARSET);  
            return null;  
        }  
    }  

    重写了Request.getBody(),这段代码说明 mRequestBody这个变量就是它的参数。这个变量就存在与JsonRequest的构造函数中。

    说明,JsonObjectRequest的传参必须通过构造来传,重写getParams()是无法传递的。

    下面按正常思路,来踩第二个坑。给JsonObjectRequest的构造传递参数。又会出现什么问题?

        private void vollyPost() {
            String url = "http://apis.juhe.cn/mobile/get?";
            
            Map<String,String> map = new HashMap<String, String>();
            map.put("phone", "15836300559");
            map.put("key", "f64ff5c4c517da17761f112d6c3c0da0");
            JSONObject jObject = new JSONObject(map);
            
            JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Method.POST, url, jObject ,new Listener<JSONObject>() {
    
                @Override
                public void onResponse(JSONObject arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            }, new ErrorListener() {
    
                @Override
                public void onErrorResponse(VolleyError arg0) {
                    // TODO Auto-generated method stub
                    Toast.makeText(MainActivity.this, arg0.toString(), Toast.LENGTH_LONG).show();
                }
            });
            jsonObjectRequest.setTag("json_post");
            mApplication.getRequstQueue().add(jsonObjectRequest);
    }


    JsonOnjectRequest Post 可能会出错的方式 :

    * 这里的思路是调用JsonObjectRequest带参构造,传参进入不就得了?
    * 但是这里还是请求不到数据。
    * 原因是使用JsonObjectRequest 如果服务器接受的参数类型是 http://....?key1=value1&key2=value2,
    * 而不是json串{key1 : value1,key2 : value2...},参数就会传不进去。
    * 可以在 HurlStack.java 的addBodyIfExists方法中看到你传入的参数信息。

    一个大写的坑爹,那些教程拜托请不要误导人好吗?特别像我这种菜鸟,很耗费时间的!

    怎么办呢?

     我找到这个方法 现在在写

    http://blog.csdn.net/onlysnail/article/details/47905375

    http://www.open-open.com/lib/view/open1434090628333.html

     

     上面的方法还在解决中,我的借口不支持JSON格式的提交所以要重新自定义JsonRequst

    接下来是ImageRequest:

    1. 第三第四个参数分别用于指定允许图片最大的宽度和高度,如果指定的网络图片的宽度或高度大于这里的最大值,则会对图片进行压缩, 
    2.   指定成0的话就表示不管图片有多大,都不会进行压缩。 
    3.    
    4.   @param url 
    5.              图片地址 
    6.   @param listener 
    7.   @param maxWidth 
    8.              指定允许图片最大的宽度 
    9.   @param maxHeight 
    10.              指定允许图片最大的高度 
    11.   @param decodeConfig 
    12.              指定图片的颜色属性,Bitmap.Config下的几个常量. 
    13.   @param errorListener 
    14.   
    public class MainActivity extends Activity {
    
        private MyApplication mApplication;
        private ImageView iv_image;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            String url ="http://pic.cnblogs.com/avatar/859887/20160120170921.png";
            mApplication = new MyApplication();
            initView();
            ImageRequest mRequest = new ImageRequest(url, new Listener<Bitmap>() {
    
                @Override
                public void onResponse(Bitmap arg0) {
                    // TODO Auto-generated method stub
                    iv_image.setImageBitmap(arg0);
                }
            }, 0, 0, Config.RGB_565, new ErrorListener() {
    
                @Override
                public void onErrorResponse(VolleyError arg0) {
                    // TODO Auto-generated method stub
                    iv_image.setImageResource(mipmap.sym_def_app_icon);
                }
            });
            mApplication.getRequstQueue().add(mRequest);
        }
    
        private void initView() {
            // TODO Auto-generated method stub
            iv_image = (ImageView) findViewById(R.id.iv_imag);
            
        }        
    }

    ImageLoad + LruCache 

    Lrucache 是图片的内存缓存

    public class BitmapCache implements ImageCache{
        
        public LruCache<String, Bitmap> cache;
        
        
        public BitmapCache() {
            // TODO Auto-generated constructor stub
            // 拿到最大内存  
            final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);  
            // 拿到内存的八分之一来做图片内存缓存  
            final int cacheSize = maxMemory / 8;  
            cache =new LruCache<String, Bitmap>(cacheSize){
                @Override
                protected int sizeOf(String key, Bitmap value) {
    
                    return  value.getRowBytes() * value.getHeight() / 1024;  
                }
            };
             
            
            
        }
    
        @Override
        public Bitmap getBitmap(String arg0) {
            // TODO Auto-generated method stub
            return cache.get(arg0);
        }
    
        @Override
        public void putBitmap(String arg0, Bitmap arg1) {
            cache.put(arg0, arg1);
            
        }
    
    }

    MainActivity

    public class MainActivity extends Activity {
    
        private MyApplication mApplication;
        private ImageView iv_image;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            String url ="http://pic.cnblogs.com/avatar/859887/20160120170921.png";
            mApplication = new MyApplication();
            initView();
            BitmapCache bCache = new BitmapCache();
            ImageLoader loader = new ImageLoader(mApplication.getRequstQueue(), bCache);
            // getImageListener(imageView控件对象,默认图片地址,失败图片地址); 
            ImageListener listener = ImageLoader.getImageListener(iv_image, R.drawable.ic_launcher, R.drawable.ic_launcher);
             // get(图片地址,listener,宽,高);自动帮你处理图片的宽高再也不怕大图片的oom了  
            loader.get(url, listener,160,160);  
        }
    
        private void initView() {
            // TODO Auto-generated method stub
            iv_image = (ImageView) findViewById(R.id.iv_imag);
            
        }        
    }
        

    Volley还提供的加载图片的控件com.android.volley.NetworkImageView。(这个控件在被从父控件detach的时候,会自动取消网络请求的,即完全不用我们担心相关网络请求的生命周期问题,而且NetworkImageView还会根据你对图片设置的width和heigh自动压缩该图片不会产生多的内存,还有NetworkImageView在列表中使用不会图片错误)

    <com.android.volley.toolbox.NetworkImageView  
        android:id="@+id/network_image_view"  
        android:layout_width="100dp"  
        android:layout_height="100dp" />  

    使用方法:

    private void networkImageViewUse(NetworkImageView iv, String url) {  
            ImageLoader imLoader = new ImageLoader(mQueue, new BitmapLruCache());  
            iv.setDefaultImageResId(R.drawable.ic_launcher);  
            iv.setErrorImageResId(R.drawable.ic_launcher);  
            iv.setImageUrl(url, imLoader);  
        }  

    我们说了这么多都是请求,那么如何取消请求呢?

    1.activity自动销毁时它会自定取消所有请求。

    2.给请求设置标签:

    request.setTag("My Tag");    

    取消所有指定标记的请求:

    request.cancelAll("My Tag"); 

    有兴趣的可以读下 Volly的架构 主线程啊 网络请求线程 缓存线程

    http://blog.csdn.net/superjimmy/article/details/45601661

    http://www.15yan.com/story/lHkq4Oi9Y2a/

    好了 今天的教程就到这里~

  • 相关阅读:
    使用System.Web.Mail通过需验证的邮件服务器发送邮件(转) dodo
    报错显示"从客户端检测到有潜在危险的Request.Form 值" dodo
    setting页面出现的原理 dodo
    action的原理 dodo
    dnn一些公用方法分析 dodo
    缓存依赖概述 dodo
    在Intranet环境中保护.NETWeb应用程序方案(转) dodo
    dnn中的用户密码设置 dodo
    Application_Start事件中修改配置文件内容 dodo
    “System.Data.OleDb.OleDbException: 未指定的错误” dodo
  • 原文地址:https://www.cnblogs.com/AceIsSunshineRain/p/5177713.html
Copyright © 2020-2023  润新知