手機影音第十三天,xutils3、Glide的使用獲取網絡圖片;下拉、上滑刷新;緩存網絡資源
代碼已經托管到碼雲上,感興趣的小夥伴可以下載看看
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()); }
本文出自 “YuanGuShi” 博客,請務必保留此出處http://cm0425.blog.51cto.com/10819451/1951257
手機影音第十三天,xutils3、Glide的使用獲取網絡圖片;下拉、上滑刷新;緩存網絡資源