Android学习记录(十四)

1.Volley概述

Volley是google在2013年IO大会上发布的一个网络通信工具包,对在android平台上通过消息队列,异步处理,线程池,缓存等方式对http请求的一些常见方法进行了优化,同时对大数据量的请求并发也作了一定的处理,可以随时取消消息的请求。

Volley主要分为两个包:核心包和工具包。核心包主要对消息请求常用的方法进行了封装;工具包则提供了一些常见的消息请求如图片,json。

Volley对消息请求处理的主要流程如下:

1 创建消息请求并放入消息缓存队列,消息缓存处理器在本地缓存里检查该消息是否有缓存,如果有,则直接将消息响应返回;

2 如消息缓存里没有该消息,则将该消息放入消息请求队列;

3 消息请求处理器从队列里依次取出消息请求,

4 消息请求处理器通过网络发送请求;

5 网络对请求作出响应,消息队列处理器对网络响应进行解析处理;

6 将解析后消息响应存入缓存,同时通知发出请求的主线程对响应进行处理。

2.Volley框架使用方法

2.1 网络请求

2.1.1 使用get方法请求数据

// 1 创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(VolleyActivity.this);
 
// 2 创建一个请求
String url = "http://api.m.mtime.cn/PageSubArea/TrailerList.api";
 
StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() {
    
    
  // 正确接收数据回调
  @Override
  public void onResponse(String s) {
    
    
    tv_volley_result.setText(s);
  }
}, new Response.ErrorListener() {
    
    // 发生异常后的监听回调
  @Override
  public void onErrorResponse(VolleyError volleyError) {
    
    
    tv_volley_result.setText("加载失败" + volleyError);
  }
});
 
// 3 将创建的请求添加到请求队列中
requestQueue.add(stringRequest);

2.1.2 使用post方式请求数据

一般我们的POST都是要带一些参数的,Volley没有提供附加参数的方法,所以我们必须要在StringRequest的匿名类中重写getParams()方法,代码如下:

// 1 创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(VolleyActivity.this);
 
// 2 创建一个post请求
String url = "http://api.m.mtime.cn/PageSubArea/TrailerList.api";
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
    
    
  @Override
  public void onResponse(String s) {
    
    
    tv_volley_result.setText(s);
  }
}, new Response.ErrorListener() {
    
    
  @Override
  public void onErrorResponse(VolleyError volleyError) {
    
    
    tv_volley_result.setText("请求失败" + volleyError);
  }
}) {
    
    
  @Override
  protected Map<String, String> getParams() throws AuthFailureError {
    
    
 
    Map<String, String> map = new HashMap<String, String>();
//            map.put("value1","param1");
 
    return map;
  }
};
 
// 3 将post请求添加到队列中
requestQueue.add(stringRequest);

2.1.3 请求Json数据

类似于StringRequest,JsonRequest也是继承自Request类的,不过由于JsonRequest是一个抽象类,因此我们无法直接创建它的实例,那么只能从它的子类入手。JsonRequest有两个直接的子类,JsonObjectRequest和JsonArrayRequest,一个是用于请求一段JSON数据的,一个是用于请求一段JSON数组的。

// 1 创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(VolleyActivity.this);
 
// 2 创建一个请求
String url = "http://api.m.mtime.cn/PageSubArea/TrailerList.api";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, new Response.Listener<JSONObject>() {
    
    
  @Override
  public void onResponse(JSONObject jsonObject) {
    
    
    tv_volley_result.setText(jsonObject.toString());
  }
}, new Response.ErrorListener() {
    
    
  @Override
  public void onErrorResponse(VolleyError volleyError) {
    
    
    tv_volley_result.setText("请求失败" + volleyError);
  }
});
 
// 3 将创建的请求添加到请求队列中
requestQueue.add(jsonObjectRequest);   

2.2 图片加载

2.2.1 使用ImageRequest加载图片

// 1 创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(VolleyActivity.this);
 
// 2 创建一个图片的请求
String url = "http://img5.mtime.cn/mg/2016/10/11/160347.30270341.jpg";
ImageRequest imageRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {
    
    
  @Override
  public void onResponse(Bitmap bitmap) {
    
    
    // 正确接收到图片
    iv_volley_result.setImageBitmap(bitmap);
  }
}, 0, 0, Bitmap.Config.RGB_565, new Response.ErrorListener() {
    
    
  @Override
  public void onErrorResponse(VolleyError volleyError) {
    
    
    iv_volley_result.setImageResource(R.drawable.atguigu_logo);
  }
});
 
// 3 将请求添加到请求队列中
requestQueue.add(imageRequest); 

2.2.2 使用Imageloader加载图片

ImageLoader也可以用于加载网络上的图片,不过ImageLoader明显要比ImageRequest更加高效,因为它不仅可以帮我们对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。
由于ImageLoader已经不是继承自Request的了,所以它的用法也和我们之前学到的内容有所不同,总结起来大致可以分为以下四步:

创建一个RequestQueue对象。
创建一个ImageLoader对象。
获取一个ImageListener对象。
调用ImageLoader的get()方法加载网络上的图片。

// 创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(VolleyActivity.this);
 
ImageLoader imageLoader = new ImageLoader(requestQueue, new BitmapCache());
 
// 加载图片
String url = "http://img5.mtime.cn/mg/2016/10/11/160347.30270341.jpg";
ImageLoader.ImageListener imageListener = imageLoader.getImageListener(iv_volley_result, R.drawable.atguigu_logo, R.drawable.atguigu_logo);
imageLoader.get(url, imageListener);  

BitmapCache.java

public class BitmapCache implements ImageLoader.ImageCache {
    
    
  private LruCache<String, Bitmap> mCache;

  public BitmapCache() {
    
    
    int maxSize = 10 * 1024 * 1024;// 10m
    mCache = new LruCache<String, Bitmap>(maxSize) {
    
    
      @Override
      protected int sizeOf(String key, Bitmap bitmap) {
    
    
        return bitmap.getRowBytes() * bitmap.getHeight();
      }
    };
  }

  @Override
  public Bitmap getBitmap(String url) {
    
    
    return mCache.get(url);
  }

  @Override
  public void putBitmap(String url, Bitmap bitmap) {
    
    
    mCache.put(url, bitmap);
  }
}


2.2.3 使用NetworkImageView加载图片

NetworkImageView继承自ImageView,你可以认为它是一个可以实现加载网络图片的imageview,十分简单好用。这个控件在被从父控件分离的时候,会自动取消网络请求的,即完全不用我们担心相关网络请求的生命周期问题。

<com.android.volley.toolbox.NetworkImageView
  android:id="@+id/iv_volley_networkimagview"
  android:layout_width="200dp"
  android:layout_height="200dp"
  android:visibility="gone">
 
</com.android.volley.toolbox.NetworkImageView>
 

// 创建一个请求队列
RequestQueue requestQueue = Volley.newRequestQueue(VolleyActivity.this);
 
// 创建一个Imageloader
ImageLoader imageLoader = new ImageLoader(requestQueue, new BitmapCache());
 
// 默认图片和异常图片设置
iv_volley_networkimagview.setDefaultImageResId(R.drawable.atguigu_logo);
iv_volley_networkimagview.setErrorImageResId(R.drawable.atguigu_logo);
 
// 加载图片
String url = "http://img5.mtime.cn/mg/2016/10/11/160347.30270341.jpg";
iv_volley_networkimagview.setImageUrl(url, imageLoader);

3.案例演示

3.1 新建安卓项目

在这里插入图片描述
在这里插入图片描述

3.2 添加背景图片

在这里插入图片描述

3.3 activity_main.xml

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background"
    android:orientation="vertical"
    android:padding="20dp">

    <EditText
        android:id="@+id/edtUrl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/input_url"
        android:textSize="20sp"
        android:lines="2" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnDownload"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="doDownload"
            android:textSize="20sp"
            android:text="@string/download" />

        <Button
            android:id="@+id/btnClear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="doClear"
            android:textSize="20sp"
            android:text="@string/clear" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#bbbbbb" />

    <ScrollView
        android:id="@+id/svContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/tvContent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#0000ff"
            android:textSize="18sp" />
    </ScrollView>
</LinearLayout>

3.4 strings.xml

在这里插入图片描述

<resources>
    <string name="app_name">利用Volley下载网页</string>
    <string name="input_url">请输入网址</string>
    <string name="download">下载</string>
    <string name="clear">清空</string>
</resources>

3.5 添加对Volley的依赖

在这里插入图片描述
在这里插入图片描述

3.6 在项目清单中授权访问

在这里插入图片描述

3.7 MainActivity.java

在这里插入图片描述

package net.nell.downloadwebpagebyvolley;

import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import java.io.UnsupportedEncodingException;

public class MainActivity extends AppCompatActivity {
    
    

    private EditText edtUrl; // 网址编辑框
    private TextView tvContent; // 显示网页内容的标签
    private RequestQueue mRequestQueue; // 请求队列

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        // 利用布局资源文件设置用户界面
        setContentView(R.layout.activity_main);

        // 通过资源标识符获取控件实例
        edtUrl = findViewById(R.id.edtUrl);
        tvContent = findViewById(R.id.tvContent);

        // 创建请求队列
        mRequestQueue = Volley.newRequestQueue(getApplicationContext());
    }

    /**
     * 下载按钮单击事件处理方法
     *
     * @param view
     */
    public void doDownload(View view) {
    
    
        // 获取用户输入的网址
        String strUrl = edtUrl.getText().toString();
        // 网址非空校验
        if (strUrl.length() == 0) {
    
    
            Toast.makeText(getApplicationContext(), "请输入网址", Toast.LENGTH_SHORT).show();
            edtUrl.requestFocus();
            return;
        }

        // 创建字符串请求对象
        final StringRequest stringRequest = new StringRequest(
                strUrl, // 参数1:目标服务器的URL地址
                new Response.Listener<String>() {
    
     // 参数2:服务器响应成功的回调
                    @Override
                    public void onResponse(String response) {
    
    
                        try {
    
    
                            // 获取响应内容
                            String content = new String(response.toString().getBytes("iso8859-1"), "utf-8");
                            // 将响应内容显示到标签里
                            tvContent.setText(content);
                        } catch (UnsupportedEncodingException e) {
    
    
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
    
     // 参数3:服务器响应失败的回调
                    @Override
                    public void onErrorResponse(VolleyError error) {
    
    
                        Toast.makeText(MainActivity.this, "服务器响应失败!", Toast.LENGTH_SHORT).show();
                    }
                });

        // 添加字符串请求到请求队列
        mRequestQueue.add(stringRequest);
    }

    /**
     * 清空单击事件处理方法
     *
     * @param view
     */
    public void doClear(View view) {
    
    
        // 清空网址编辑框
        edtUrl.setText("");
        // 清空网页内容标签
        tvContent.setText("");
        // 让网址编辑框获取焦点
        edtUrl.requestFocus();
    }
}

3.8 运行效果

在这里插入图片描述
在这里插入图片描述

4.案例演示(二)

4.1 新建项目添加背景图片

在这里插入图片描述
在这里插入图片描述

4.2 activity_main.xml

在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background"
    android:orientation="vertical"
    android:padding="20dp">

    <EditText
        android:id="@+id/edtImageUrl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/input_image_url"
        android:textSize="20sp"
        android:lines="2" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnDownload"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="doDownload"
            android:textSize="20sp"
            android:text="@string/download" />

        <Button
            android:id="@+id/btnClear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="doClear"
            android:textSize="20sp"
            android:text="@string/clear" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#bbbbbb" />

    <ScrollView
        android:id="@+id/svContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/ivImage"/>


    </ScrollView>
</LinearLayout>

在这里插入图片描述

4.3 strings.xml

在这里插入图片描述

<resources>
    <string name="app_name">利用Volley下载网络图片</string>
    <string name="download">下载</string>
    <string name="input_image_url">输入图片网址</string>
    <string name="clear">清空</string>
</resources>

4.4 添加依赖授权访问因特网

在这里插入图片描述
在这里插入图片描述

4.5 MainActivity.java

在这里插入图片描述

package net.nell.downloadimagebyvolley;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.Volley;

/**
 * 功能:利用Volley下载网络图片
 * 作者:华卫
 * 日期:2021年01年03日
 */
public class MainActivity extends AppCompatActivity {
    
    

    private EditText edtImageUrl; // 网址编辑框
    private ImageView ivImage; // 显示网络图片的图像控件
    private RequestQueue mRequestQueue; // 请求队列

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        // 利用布局资源文件设置用户界面
        setContentView(R.layout.activity_main);

        // 通过资源标识符获取控件实例
        edtImageUrl = findViewById(R.id.edtImageUrl);
        ivImage = findViewById(R.id.ivImage);

        // 创建请求队列
        mRequestQueue = Volley.newRequestQueue(getApplicationContext());
    }

    /**
     * 下载按钮单击事件处理方法
     *
     * @param view
     */
    public void doDownload(View view) {
    
    
        // 获取用户输入的网址
        String strImageUrl = edtImageUrl.getText().toString();
        // 网址非空校验
        if (strImageUrl.length() == 0) {
    
    
            Toast.makeText(getApplicationContext(), "请输入网址", Toast.LENGTH_SHORT).show();
            edtImageUrl.requestFocus();
            return;
        }

        // 创建图像请求对象
        final ImageRequest imageRequest = new ImageRequest(
                strImageUrl, // 参数1:目标服务器的URL地址
                new Response.Listener<Bitmap>() {
    
     // 参数2:服务器响应成功的回调
                    @Override
                    public void onResponse(Bitmap response) {
    
    
                        ivImage.setImageBitmap(response);
                    }
                },
                0, // 参数3:指定允许图片最大的宽度(指定成0,不压缩图片)
                0, // 参数4:指定允许图片最大的高度(指定成0,不压缩图片)
                Bitmap.Config.RGB_565, // 参数5:指定图片颜色属性(RGB_565表示每个图片像素占据2个字节)
                new Response.ErrorListener() {
    
     // 参数6:服务器响应失败的回调
                    @Override
                    public void onErrorResponse(VolleyError error) {
    
    
                        Toast.makeText(MainActivity.this, "服务器响应失败!", Toast.LENGTH_SHORT).show();
                    }
                });

        // 添加图像请求到请求队列
        mRequestQueue.add(imageRequest);
    }

    /**
     * 清空单击事件处理方法
     *
     * @param view
     */
    public void doClear(View view) {
    
    
        // 清空网址编辑框
        edtImageUrl.setText("");
        // 清空图像控件内容
        ivImage.setImageBitmap(null);
        // 让网址编辑框获取焦点
        edtImageUrl.requestFocus();
    }
}

4.6 寻找目标图片网址

在这里插入图片描述

4.7 运行效果

在这里插入图片描述
在这里插入图片描述

4.8 采用ImageLoader来下载网络图片

ImageLoader明显要比ImageRequest更加高效,因为它不仅可以对图片进行缓存,还可以过滤掉重复的链接,避免重复发送请求。

在这里插入图片描述

package net.nell.downloadimagebyvolley;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.LruCache;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;


public class MainActivity extends AppCompatActivity {
    
    

    private EditText edtImageUrl; // 网址编辑框
    private ImageView ivImage; // 显示网络图片的图像控件
    private RequestQueue mRequestQueue; // 请求队列
    private ImageLoader imageLoader; // 图像加载器
    private ImageLoader.ImageListener imageListener; // 图像监听器

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        // 利用布局资源文件设置用户界面
        setContentView(R.layout.activity_main);

        // 通过资源标识符获取控件实例
        edtImageUrl = findViewById(R.id.edtImageUrl);
        ivImage = findViewById(R.id.ivImage);

        // 创建请求队列
        mRequestQueue = Volley.newRequestQueue(getApplicationContext());
    }

    /**
     * 下载按钮单击事件处理方法
     *
     * @param view
     */
    public void doDownload(View view) {
    
    
        // 获取用户输入的网址
        String strImageUrl = edtImageUrl.getText().toString();
        // 网址非空校验
        if (strImageUrl.length() == 0) {
    
    
            Toast.makeText(getApplicationContext(), "请输入网址", Toast.LENGTH_SHORT).show();
            edtImageUrl.requestFocus();
            return;
        }
        // 创建图像加载器对象
        imageLoader = new ImageLoader(mRequestQueue, new BitmapCache());
        // 获取图像监听器对象
        imageListener = imageLoader.getImageListener(
                ivImage, // 参数1:指定用于显示图片的ImageView控件
                R.drawable.ic_launcher_background, // 参数2:指定图片加载过程中显示的图片
                android.R.drawable.ic_delete // 参数3:指定图片加载失败时显示的图片
        );
        // 加载网络图片
        imageLoader.get(strImageUrl, imageListener);
    }

    /**
     * 清空单击事件处理方法
     *
     * @param view
     */
    public void doClear(View view) {
    
    
        // 清空网址编辑框
        edtImageUrl.setText("");
        // 清空图像控件内容
        ivImage.setImageBitmap(null);
        // 让网址编辑框获取焦点
        edtImageUrl.requestFocus();
    }

    /**
     * 绘图缓存类
     */
    class BitmapCache implements ImageLoader.ImageCache {
    
    

        private LruCache<String, Bitmap> mCache;

        public BitmapCache() {
    
    
            int maxSize = 10 * 1024 * 1024;
            mCache = new LruCache<String, Bitmap>(maxSize) {
    
    
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
    
    
                    return bitmap.getRowBytes() * bitmap.getHeight();
                }
            };
        }

        @Override
        public Bitmap getBitmap(String url) {
    
    
            return mCache.get(url);
        }

        @Override
        public void putBitmap(String url, Bitmap bitmap) {
    
    
            mCache.put(url, bitmap);
        }
    }
}

使用上述代码可以在下载图片时进行优化,但运行效果于上述方法相同,在此便不进行演示。

以上是任务五所涉及到的一部分内容,接下来的时间我将会进行Gson的学习,这部分的学习内容将会明天进行展示。

猜你喜欢

转载自blog.csdn.net/weixin_46705517/article/details/112982809