1. 程式人生 > >手機影音第十三天,xutils3、Glide的使用獲取網絡圖片;下拉、上滑刷新;緩存網絡資源

手機影音第十三天,xutils3、Glide的使用獲取網絡圖片;下拉、上滑刷新;緩存網絡資源

xutils、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的使用獲取網絡圖片;下拉、上滑刷新;緩存網絡資源