Leo仿【DOTA视频站】项目实践【三】---- 获取DOTA2视频已经XListView实现上拉加载更多、下拉刷新

本文介绍了如何使用优酷API根据视频种类进行搜索,并特别针对搜索DOTA2视频的问题进行了详细说明。通过解析视频网址获取ID,利用此ID打印视频信息,发现视频tag属性可用于搜索。实现搜索功能后,文章进一步解决ListView显示问题,通过引用XListView框架实现了下拉刷新和上拉加载更多功能。最后,文章展示了主界面显示DOTA2视频列表的代码,包括获取视频列表、上下拉刷新和加载更多功能的实现,以及点击事件跳转至优酷Demo中的播放界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在前一篇文章《优酷SDK学习》中使用优酷API根据视频种类进行搜索,可是优酷设置的视频种类中只有游戏,没有我想要搜索的DOTA2视频。于是为了弄懂怎么去搜索DOTA2视频,专门在优酷网页上打开了一个DOTA2视频,把他的网址记下来,然后解析出该视频的id,再运用id将该视频所用的具体信息打印出来。我发现在该视频的信息中有一个tag属性,记录了该视频是一个DOTA2视频。于是我就在想能不能根据这个tag去进行搜索。查看优酷API之后,果真发现有根据tag搜索视频的。多个tag之间用逗号分开。

public static final String TAG_URL = "https://openapi.youku.com/v2/searches/video/by_tag.json";

        在解决了这个问题之后,然后就是listview显示的问题了。对于ListView的上下拉刷新加载问题,我直接引用了开源框架XListView。下面直接上主界面显示DOTA2视频列表的代码。

package com.jgh.watchdota;



import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.jgh.cache.FileService;
import com.jgh.util.DotaItemAdapter;
import com.jgh.util.ItemDate;
import com.jgh.util.StaticsUtil;
import me.maxwin.view.XListView;
import me.maxwin.view.XListView.IXListViewListener;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;

public class HomeFragment extends Fragment implements IXListViewListener,
		OnItemClickListener {
	public static final String TAG_URL = "https://openapi.youku.com/v2/searches/video/by_tag.json";// 优酷API搜索url

	public Activity mActivity;
	private XListView mListView;// ListView
	private DotaItemAdapter mAdapter;// 自定义适配器
	private static List<Map<String, Object>> items = new ArrayList<Map<String, Object>>();// ListView中的Item集合
	private Map<String, String> params;// 搜索的参数
	private Handler mHandler;
	private Handler handler;
	private int page = 1;// 搜索的当前页数
	private static int pageCount = 20;// 每页搜索的item条数
	private boolean isOnRefresh = false;// 标记是否正处于下拉刷新状态

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view = inflater.inflate(R.layout.layout_home, container, false);
		params = new HashMap<String, String>();// 初始化搜索参数
		params.put("client_id", StaticsUtil.CLIENT_ID);// APK申请的client_id
		params.put("category", "游戏");
		params.put("tag", "DOTA2");
		params.put("orderby", "published");
		params.put("page", page+"");
		params.put("count", pageCount+"");
		mActivity = getActivity();
		initList(view);// 初始化ListView
		return view;
	}

	private void initList(View view) {
		// TODO Auto-generated method stub
		getItems();// 开启异步线程获取item
		mListView = (XListView) view.findViewById(R.id.xListView);
		mListView.setPullLoadEnable(true);// 上拉加载更多
		mListView.setPullRefreshEnable(false);// 下拉刷新,这里暂时关闭该功能
		mListView.setXListViewListener(this);
		mListView.setOnItemClickListener(this);
		handler = new Handler();
		mHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				switch (msg.what) {
				case 0:// 加载失败
					page --;
					onLoad();
					Toast.makeText(mActivity, "网络异常,加载失败!", Toast.LENGTH_SHORT).show();
					break;
				case 1:
					mAdapter = new DotaItemAdapter(mActivity, items);
					mListView.setAdapter(mAdapter);
					break;
				case 2:
					Log.i("jiangguohu","handler case 2");
					mAdapter.notifyDataSetChanged();
					onLoad();
					break;
				default:
					break;
				}
			}
		};
	}

	private void getItems() {
		// TODO Auto-generated method stub
		thread.start();
	}

	@Override
	public void onRefresh() {// 下拉刷新时会调用的方法
		// TODO Auto-generated method stub
		handler.postDelayed(new Runnable() {
			@Override
			public void run() {
				mListView.setAdapter(mAdapter);
				onLoad();
			}
		}, 2000);
	}

	@Override
	public void onLoadMore() {// 上拉加载更多的方法
		// TODO Auto-generated method stub
		handler.postDelayed(new Runnable() {
			@Override
			public void run() {
				Log.i("jiangguohu","isOnRefresh = "+isOnRefresh);
				if (checkNetWork(mActivity)) {// 检查网络,没有联网时停止加载
					if (!isOnRefresh) {
						isOnRefresh = true;
						page ++;// 加载下一页数据
						final Map<String, String> params2 = new HashMap<String, String>();
						params2.put("client_id", StaticsUtil.CLIENT_ID);
						params2.put("category", "游戏");
						params2.put("tag", "DOTA2");
						params2.put("orderby", "published");
						params2.put("page", page+"");
						params2.put("count", pageCount+"");
						new Thread(new Runnable() {
							public void run() {
								boolean b = false;
									try {
										b = sendGETRequest(TAG_URL, params2, mActivity);
										Log.i("jiangguohu", "b2 = " + b);
									} catch (Exception e) {
										// TODO Auto-generated catch block
										e.printStackTrace();
									}
								if (b) {// 运用handler返回处理结果,刷新界面
									mHandler.sendEmptyMessage(2);
								} else {
									mHandler.sendEmptyMessage(0);
								}
							}
						}).start();
					}
				} else {
					Toast.makeText(mActivity, "请检查网络设置!", Toast.LENGTH_SHORT).show();
					onLoad();
				}
			}
		}, 2000);
	}

	private void onLoad() {// 下拉刷新或者上拉加载结束时候手动调用该方法,结束刷新
		mListView.stopRefresh();
		mListView.stopLoadMore();
		mListView.setRefreshTime("刚刚");
		isOnRefresh = false;
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {// ListView的点击事件,在这里我直接跳转到优酷Demo中的播放界面
		// TODO Auto-generated method stub
		if (!checkNetWork(mActivity)) {
			Toast.makeText(mActivity, "请检查网络设置!", Toast.LENGTH_SHORT).show();
			return;
		}
		Intent i = new Intent(
				mActivity, PlayerActivity.class);
		String id = (String) items.get(arg2-1).get("id");
		i.putExtra("vid", id.trim());
		startActivity(i);
	}

	Thread thread = new Thread(new Runnable() {
		public void run() {
			boolean b = false;
				try {
					b = sendGETRequest(TAG_URL, params, mActivity);
					Log.i("jiangguohu", "b = " + b);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			if (b) {
				mHandler.sendEmptyMessage(1);
			} else {
				mHandler.sendEmptyMessage(0);
			}
		}
	});

	private static boolean sendGETRequest(String path,
			Map<String, String> params, Context context) throws Exception {// GET方式访问网络获取数据
		StringBuilder sb = new StringBuilder();
		sb.append(path).append("?");
		if (params != null && params.size() != 0) {
			for (Map.Entry<String, String> entry : params.entrySet()) {
				sb.append(entry.getKey()).append("=")
						.append(URLEncoder.encode(entry.getValue(), "utf-8"));
				sb.append("&");
			}
			sb.deleteCharAt(sb.length() - 1);
		}

		if (checkNetWork(context)) {
			URL url = new URL(sb.toString());
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setRequestMethod("GET");
			Log.i("jiangguohu","sendGETRequest conn.getResponseCode() = "+conn.getResponseCode());
			if (conn.getResponseCode() == 200) {
				InputStream is = conn.getInputStream();
				byte[] data = readStream(is);
				String json = new String(data);
				loadDate(json);
				FileService fileService = new FileService(context);// 文件缓存,保存当前页面从网络获取的json数据
				fileService.clear();
				fileService.save(json);
				return true;
			}
			return false;
		} else {// 没有网络时,加载本地缓存数据
			items.clear();
			loadDate(new FileService(context).read());

			if (items.size() != 0) {
				return true;
			} else {
				return false;
			}
		}
	}

	public static byte[] readStream(InputStream inputStream) throws Exception {
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = 0;
		while ((len = inputStream.read(buffer)) != -1) {
			bout.write(buffer, 0, len);
		}
		bout.close();
		inputStream.close();
		return bout.toByteArray();
	}

	/**
	 * 将json数据存入list
	 * @param string
	 */
	public static void loadDate(String string) {
		JSONObject jsonObject;
		try {
			jsonObject = new JSONObject(string);
			JSONArray jsonArray = (JSONArray) jsonObject.opt("videos");
			Map<String, Object> map = null;
			for (int i = 0; i < jsonArray.length(); i++) {
				JSONObject item = jsonArray.getJSONObject(i);
				ItemDate itemDate = new ItemDate();// 自己写的ItemDate类,用于封装item信息
				map = itemDate.getHashMap(item);
				if (map != null) {
					items.add(map);
				}
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 检查网络连接
	 * @param mContext
	 * @return
	 */
	public static boolean checkNetWork(Context mContext) {
        ConnectivityManager connectivityManager = (ConnectivityManager) mContext
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info == null || !info.isAvailable()) {
            return false;
        } else {
            return true;
        }
    }

}

下面再让我们来看看ItemDate这个类吧:

package com.jgh.util;

import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;

/**
 * 查询网页,返回结果进行处理的包装类
 * 
 * @author jiangguohu
 * 
 */
public class ItemDate {

	private String id;// 视频的id
	private String title;// 视频的标题
	private String link;// 视频的链接地址
	private String duration;// 视频的总shichang
	private String thumbnail;// 视频截图
	private String published;// 视频发布的时间

	public ItemDate() {
		super();
	}

	public ItemDate(String id, String title, String link, String duration,
			String thumbnail, String published) {
		super();
		this.id = id;
		this.title = title;
		this.link = link;
		this.duration = duration;
		this.thumbnail = thumbnail;
		this.published = published;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getLink() {
		return link;
	}

	public void setLink(String link) {
		this.link = link;
	}

	public String getDuration() {
		return duration;
	}

	public void setDuration(String duration) {
		this.duration = duration;
	}

	public String getThumbnail() {
		return thumbnail;
	}

	public void setThumbnail(String thumbnail) {
		this.thumbnail = thumbnail;
	}

	public String getPublished() {
		return published;
	}

	public void setPublished(String published) {
		this.published = published;
	}

	public Map<String, Object> getHashMap(JSONObject item) {// 将从网络中获取的json信息处理为Map对象,然后存放在List中
		// TODO Auto-generated method stub
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			if (10*60 > item.getInt("duration")) {// 排除十分钟一下的视频
				Log.i("jiangguohu","时间太短,排除!");
				return null;
			}
			title = item.getString("title");
			id = item.getString("id");
			link = item.getString("link");
			duration = String.valueOf(item.getInt("duration"));
			thumbnail = item.getString("thumbnail");
			published = item.getString("published");
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		map.put("id", id);
		map.put("title", title);
		map.put("link", link);
		map.put("thumbnail", thumbnail);
		map.put("published", published);
		map.put("duration", changeTimeFormat(duration + ""));// 更改视频总时长显示的格式
		return map;
	}

	/**
	 * 将从网络中获取的时间进行转化
	 * @param time
	 * @return
	 */
	public static String changeTimeFormat(String time) {
		if (time != null) {
			int timeInt = Integer.parseInt(time);
			int second = timeInt % 60;
			int minute = (timeInt / 60) % 60;
			int hour = (timeInt / 60) / 60;
			return "" + (hour < 10 ? ("0" + hour) : hour + "") + ":"
					+ (minute < 10 ? ("0" + minute) : minute + "") + ":"
					+ (second < 10 ? ("0" + second) : second);
		}
		return time;
	}

	public static ItemDate getItemDate(Map<String, Object> map) {// 将一个Map对象处理为一个ItemDate类对象
		return new ItemDate((String) map.get("id"), (String) map.get("title"),
				(String) map.get("link"), (String) map.get("duration"),
				(String) map.get("thumbnail"), (String) map.get("published"));
	}

}

再来看看我们自定义的Adapter吧:

package com.jgh.util;


import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import com.jgh.cache.ImageLoader;
import com.jgh.watchdota.R;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class DotaItemAdapter extends BaseAdapter {
	private Activity mActivity;
	private List<Map<String, Object>> items;
	ImageLoader imageLoader;

	public DotaItemAdapter(Activity mActivity, List<Map<String, Object>> items) {
		// TODO Auto-generated constructor stub
		this.mActivity = mActivity;
		this.items = items;
		imageLoader = new ImageLoader(mActivity);// 图片缓存处理类
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return items.size();
	}

	@Override
	public Object getItem(int arg0) {
		// TODO Auto-generated method stub
		return items.get(arg0);
	}

	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return arg0;
	}

	@Override
	public View getView(int arg0, View arg1, ViewGroup arg2) {
		// TODO Auto-generated method stub
		ItemDate itemMap = ItemDate.getItemDate(items.get(arg0));// 将List中获取Map然后转化为ItemDate
		LayoutInflater inflater = mActivity.getLayoutInflater();
		View itemView = inflater.inflate(R.layout.list_item, null);
		TextView title = (TextView) itemView.findViewById(R.id.title);
		TextView published = (TextView) itemView.findViewById(R.id.published);
		TextView duration = (TextView) itemView.findViewById(R.id.duration);
		ImageView imageView = (ImageView) itemView.findViewById(R.id.image);
		title.setText(itemMap.getTitle());
		published.setText(itemMap.getPublished());
		duration.setText(itemMap.getDuration()+"");
		//Log.i("jiangguohu","itemMap.get(thumbnail) = "+itemMap.get("thumbnail"));
		//imageView.setImageURI(Uri.parse(itemMap.get("thumbnail")));
		//imageView.setImageBitmap((Bitmap) itemMap.get("thumbnail"));
		imageLoader.displayImage(itemMap.getThumbnail(), imageView);// 加载缓存图片,如若没有缓存,从网络获取
		return itemView;
	}
}

好啦,以上就是现阶段的分享啦。下一章将会讲解缓存部分。等到做的差不多的时候再发布源码。欢迎大家留言讨论,共同进步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值