您的位置:首页 > 理论基础 > 计算机网络

手机影音第十三天,xutils3、Glide的使用获取网络图片;下拉、上滑刷新;缓存网络资源

2017-07-26 22:29 507 查看
代码已经托管到码云上,感兴趣的小伙伴可以下载看看
https://git.oschina.net/joy_yuan/MobilePlayer
本次的网络资源地址使用的是时光网的api接口,地址如下:
http://api.m.mtime.cn/PageSubArea/TrailerList.api
效果如下:




一、Xutils3 的使用
去github上看详解:https://github.com/wyouflf/xUtils3

xUtils3简介

xUtils 包含了orm, http(s), image, view注解, 但依然很轻量级(246K), 并且特性强大, 方便扩展:
稳定的基石
:
AbsTask
和统一的回调接口
Callback
, 任何异常, 即使你的回调方法实现有异常都会进入
onError
, 任何情况下
onFinished
总会让你知道任务结束了.

基于高效稳定的
orm
工具,
http
模块得以更方便的实现cookie(支持domain, path, expiry等特性)和 缓存(支持Cache-Control, Last-Modified, ETag等特性)的支持.

有了强大的
http
及其下载缓存的支持,
image
模块的实现相当的简洁, 并且支持回收被view持有, 但被Mem Cache移除的图片, 减少页面回退时的闪烁..

view
注解模块仅仅400多行代码却灵活的支持了各种View注入和事件绑定, 包括拥有多了方法的listener的支持.

其他特性

支持超大文件(超过2G)上传

更全面的http请求协议支持(11种谓词)

拥有更加灵活的ORM, 和greenDao一致的性能

更多的事件注解支持且不受混淆影响...

图片绑定支持gif(受系统兼容性影响, 部分gif文件只能静态显示), webp; 支持圆角, 圆形, 方形等裁剪, 支持自动旋转...

从3.5.0开始不再包含libwebpbackport.so, 需要在Android4.2以下设备兼容webp的请使用3.4.0版本.

1.1、在Android studio中添加xutils3的方法:

a 在build.gradle里添加依赖
compile 'org.xutils:xutils:3.5.0'
b 添加权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
c 新建一个MyApplication类extends Application ,然后重写里面的onCreate()方法,在里面初始化xutils

package com.yuanlp.mobileplayer;

import android.app.Application;

import org.xutils.x;

/**
* Created by 原立鹏 on 2017/7/26.
*/

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
x.Ext.init(this);
x.Ext.setDebug(BuildConfig.DEBUG); // 是否输出debug日志, 开启debug会影响性能.
}
}
d 、利用xutils的注解方法,来实例化布局里的控件

1)、网络视频也是一个listview,因此主页面与本地视频的主页面类似,

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.yuanlp.mobileplayer.view.XListView
android:divider="@null"
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"></com.yuanlp.mobileplayer.view.XListView>
<TextView
android:visibility="gone"
android:textSize="18sp"
android:textColor="#000000"
android:id="@+id/tv_nonet"
android:text="没有网络"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

<ProgressBar
android:layout_centerInParent="true"
android:id="@+id/pb_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</RelativeLayout>
2)然后就是每个listview的item的布局,有图片和linearlayout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
android:gravity="center_vertical"
>
<RelativeLayout
android:layout_centerVertical="true"
android:id="@+id/rl_image"
android:layout_width="120dp"
android:layout_height="80dp">
<ImageView
android:id="@+id/iv_icon"
android:scaleType="fitXY"
android:src="@drawable/video_default"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:src="@drawable/center_collect_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</RelativeLayout>
<LinearLayout
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/rl_image"
android:orientation="vertical"
android:layout_marginLeft="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/tv_name"
android:text="视频名称"
android:textSize="18sp"
android:maxLines="1"
android:textColor="#000000"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tv_videotitle"
android:text="视频描述"
android:textSize="18sp"
android:layout_marginTop="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</LinearLayout>

</RelativeLayout>


1.2、 利用xutils获取网络资源

a 利用xutils的x.http().get(params,callback);来获取网络资源,不管获取成功与否,都在callback里有回调方法:

Constants.NET_URL="http://api.m.mtime.cn/PageSubArea/TrailerList.api";
RequestParams params=new RequestParams(Constants.NET_URL);
x.http().get(params, new Callback.CommonCallback<String>() {  //回调公用的一个String
@Override
public void onSuccess(String result) {
LogUtil.e("联网成功"+result);

//解析数据,获取数据并展示adapter
progressData(result);

//将获取的数据保存
CacheUtils.putString(context,Constants.NET_URL,result);

//设置item点击事件
listview.setOnItemClickListener(new MyOnItemClickListener());

}

@Override
public void onError(Throwable ex, boolean isOnCallback) {
LogUtil.e("联网失败"+ex.getMessage());
nonet.setVisibility(View.VISIBLE); //文本显示没网络数据
pb_loading.setVisibility(View.GONE);
}

@Override
public void onCancelled(CancelledException cex) {
LogUtil.e("onCancelled"+cex.getMessage());
}

@Override
public void onFinished() {
LogUtil.e("onFinished");
}
});

private void progressData(String result) {
if (!isloadMore){
mediaList=progressJson(result);
showData();
pb_loading.setVisibility(View.GONE);  //progressbar隐藏
}else{
//加载更多,那么就把新的list加入到原有的list中
ArrayList<MediaItem> moreMediaList=progressJson(result);
mediaList.addAll(moreMediaList);

//刷新适配器
netvideoAdap.notifyDataSetChanged();
isloadMore=false;
onLoad();

}
}

private void showData() {
if (mediaList!=null&&mediaList.size()>0){
nonet.setVisibility(View.GONE);  //隐藏文本

netvideoAdap = new NetVideoAdapter(context,mediaList);
//设置适配器
listview.setAdapter(netvideoAdap);

onLoad(); //重新加载listview数据
}else {
nonet.setVisibility(View.VISIBLE); //文本显示没网络数据
}
}

/**
* 解析json有2中方法:
* 1、利用系统接口
* 2、利用第三方接口,如gson,fastjson
* @param json
* @return
*/
private ArrayList<MediaItem> progressJson(String json) {
ArrayList<MediaItem> mediaItems=new ArrayList<>();
//利用系统来解析json
try {
JSONObject jsonObject=new JSONObject(json);
JSONArray trailers = jsonObject.optJSONArray("trailers");//利用这个方法,来获取一个数组
if (trailers!=null&&trailers.length()>0){
for (int i=0;i<trailers.length();i++){
JSONObject object = (JSONObject) trailers.get(i);
if (object!=null){
MediaItem item=new MediaItem();
String movieName = object.getString("movieName");
item.setName(movieName);
String videoTitle=object.getString("videoTitle");
item.setVideoTitle(videoTitle);
String coverImg=object.getString("coverImg");
item.setCoverImg(coverImg);
String hightUrl=object.getString("hightUrl");
item.setData(hightUrl);
LogUtil.e("电影名字:"+movieName);
mediaItems.add(item);
}
}
}

} catch (JSONException e) {
e.printStackTrace();
}
return mediaItems;

}


二、Glide的使用
在build.gradle里添加依赖,然后sync一下就可以了
compile 'com.github.bumptech.glide:glide:3.6.1'


在网络资源的adapter里,设置图片的网络资源时,用Glide最好,这样子模拟机与真机里都可以获取到图片。

Glide.().load(item.getCoverImg()).into(viewHolder.);


具体的adapter代码如下:

package com.yuanlp.mobileplayer.adapter;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.yuanlp.mobileplayer.R;
import com.yuanlp.mobileplayer.bean.MediaItem;
import com.yuanlp.mobileplayer.utils.Utils;

import java.util.ArrayList;

/**
* Created by 原立鹏 on 2017/7/26.
*/

public class NetVideoAdapter extends BaseAdapter {

private Context context;
private ArrayList<MediaItem> mediaList;
private Utils utils;
private static Bitmap bitmap;

public NetVideoAdapter(Context context, ArrayList<MediaItem> mediaList){
this.context=context;
this.mediaList=mediaList;

}

@Override
public int getCount() {
return mediaList.size();
}

@Override
public Object getItem(int position) {
return mediaList.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder=null;
if (convertView==null){
View view = LayoutInflater.from(context).inflate(R.layout.netmedialayout, null);
convertView=view;
viewHolder=new ViewHolder();
viewHolder.iv_icon= (ImageView) convertView.findViewById(R.id.iv_icon);
viewHolder.tv_name= (TextView) convertView.findViewById(R.id.tv_name);
viewHolder.tv_videotitle= (TextView) convertView.findViewById(R.id.tv_videotitle);

convertView.setTag(viewHolder);
}else{
viewHolder= (ViewHolder) convertView.getTag();
}

//得到数据
MediaItem item=mediaList.get(position);
viewHolder.tv_name.setText(item.getName());

viewHolder.tv_videotitle.setText(item.getVideoTitle());

Glide.with(context).load(item.getCoverImg()).into(viewHolder.iv_icon);
// x.image().bind(viewHolder.iv_icon,item.getCoverImg());
return convertView;
}

/**
* 公共的控件类,里面包含每一行要显示的控件
*/
private static class ViewHolder{
ImageView iv_icon;
TextView tv_name;
TextView tv_time;
TextView tv_size;

TextView tv_videotitle;
}
}


三、下拉刷新,xListView
在这里下拉刷新我用的是网络上的一个Xlistview,可以到github上下载

下载好之后,把src文件夹里的XListView 、XListViewFooter、XListViewHeader拷贝到自己的项目里,然后把res里对应的布局文件拷贝过去。

然后把上面的自定义的网络资源里的布局文件的listview的类,指向我们刚才拷贝的XlistView

当设置好listview的setAdapter后,我们要设置listview的上拉、下拉刷新

listview.setPullLoadEnable(true);

listview.setXListViewListener(new MyXListViewListener());

class MyXListViewListener implements XListView.IXListViewListener {

@Override
public void onRefresh() {
getData();

}

@Override
public void onLoadMore() {

RequestParams params=new RequestParams(Constants.NET_URL);
x.http().get(params, new Callback.CommonCallback<String>() {  //回调公用的一个String
@Override
public void onSuccess(String result) {
LogUtil.e("联网成功"+result);
isloadMore=true;
//解析数据,获取数据并展示adapter
progressData(result);

listview.setOnItemClickListener(new MyOnItemClickListener());

}

@Override
public void onError(Throwable ex, boolean isOnCallback) {
LogUtil.e("联网失败"+ex.getMessage());
isloadMore=false;
nonet.setVisibility(View.VISIBLE); //文本显示没网络数据
pb_loading.setVisibility(View.GONE);

}

@Override
public void onCancelled(CancelledException cex) {
LogUtil.e("onCancelled"+cex.getMessage());
isloadMore=false;
}

@Override
public void onFinished() {
LogUtil.e("onFinished");
isloadMore=false;
}
});
}
}

/**
* 重新加载adapter里的数据
*/
private void onLoad() {
listview.stopRefresh();
listview.stopLoadMore();
listview.setRefreshTime("更新时间"+getSystemTime());
}


在这里我们写了listview的上拉下拉监听回调方法。

a 、 当下拉时,重新去刷新数据,相当于去重新请求该api地址的数据。

b 、在上拉时,去获取新的数据,放到list里,然后setAdapter。这里由于数据固定,就每次上拉时,把原先的list拷贝一份加进去,相当于2个list的数据。

四、当有网络时,把网络资源保存到本地,断网后,再打开应用可以将资源展现。

定义一个CacheUtils类,来实现get/set网络资源

package com.yuanlp.mobileplayer.utils;

import android.content.Context;
import android.content.SharedPreferences;

/**
* Created by 原立鹏 on 2017/7/26.
*
* 当网络断掉时,之前访问的网络视频资源保存到本地
*/

public class CacheUtils {

public static void putString(Context context,String key,String values){
//创建一个私有的文件
SharedPreferences sharedPreferences=context.getSharedPreferences("yuan",Context.MODE_PRIVATE);
sharedPreferences.edit().putString(key,values).commit();
}

public static String  getString(Context context,String key){
SharedPreferences sharedPreferences=context.getSharedPreferences("yuan",Context.MODE_PRIVATE);

return sharedPreferences.getString(key,""); //默认返回空字符串
}
}


这样在有网络时,就把数据存到本地

/**
* 获取网络数据
*/
public void getData() {

RequestParams params=new RequestParams(Constants.NET_URL);
x.http().get(params, new Callback.CommonCallback<String>() {  //回调公用的一个String
@Override
public void onSuccess(String result) {
LogUtil.e("联网成功"+result);

//解析数据,获取数据并展示adapter
progressData(result);

//将获取的数据保存到本地
CacheUtils.putString(context,Constants.NET_URL,result);

//设置item点击事件
listview.setOnItemClickListener(new MyOnItemClickListener());

}

。
。
。
。
当初始化时,回去读取本地视频,如果有,则去读取并展示

@Override
public void initData() {
super.initData();
//获取网络数据
getData();
LogUtil.e("网络视频页面的数据被初始化了");

//获取之前有网络时保存的数据
String jsonResult=CacheUtils.getString(context,Constants.NET_URL);
//当有本地数据时,去解析本地数据
if (!TextUtils.isEmpty(jsonResult)){
progressData(jsonResult);
}

listview.setPullLoadEnable(true);

listview.setXListViewListener(new MyXListViewListener());

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐