代码已经托管到码云上,感兴趣的小伙伴可以下载看看
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), p_w_picpath, view注解, 但依然很轻量级(246K), 并且特性强大, 方便扩展:
稳定的基石
:AbsTask
和统一的回调接口Callback
, 任何异常, 即使你的回调方法实现有异常都会进入onError
, 任何情况下onFinished
总会让你知道任务结束了.基于高效稳定的
orm
工具,http
模块得以更方便的实现cookie(支持domain, path, expiry等特性)和 缓存(支持Cache-Control, Last-Modified, ETag等特性)的支持.有了强大的
http
及其下载缓存的支持,p_w_picpath
模块的实现相当的简洁, 并且支持回收被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 添加权限
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,因此主页面与本地视频的主页面类似,
2)然后就是每个listview的item的布局,有图片和linearlayout
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 @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 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 progressJson(String json) { ArrayList 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
二、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 ArrayListmediaList; private Utils utils; private static Bitmap bitmap; public NetVideoAdapter(Context context, ArrayList 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.p_w_picpath().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 @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 @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()); }