程序中实现网络连接和获取网络数据是通过JamendoGet2Api这个接口中的方法实现的,他的实现类是JamendoGet2ApiImpl.这里就从getPopularAlbumsWeek()这个获取本周最受欢迎的专辑为例分析如何实现的,其实这个返回的数据就是在HomeActivity中最上面显示的Gallery中的数据。
这个图还真是不会画,索性就将用到的相关类都列出来。
@Override public Album[] getPopularAlbumsWeek() throws JSONException, WSError { String jsonString = doGet("id+name+url+image+rating+artist_name/album/json/?n=20&order=ratingweek_desc"); if (jsonString == null) return null; try { JSONArray jsonArrayAlbums = new JSONArray(jsonString); return AlbumFunctions.getAlbums(jsonArrayAlbums); } catch (NullPointerException e) { e.printStackTrace(); throw new JSONException(e.getLocalizedMessage()); } }首先通过doGet方法根据指定的url通过HTTP协议获取网络数据
private static String GET_API = "http://api.jamendo.com/get2/"; private String doGet(String query) throws WSError{ return Caller.doGet(GET_API + query); }
/** * Performs HTTP GET using Apache HTTP Client v 4 * * @param url * @return * @throws WSError */ public static String doGet(String url) throws WSError{ String data = null; if(requestCache != null){ data = requestCache.get(url); if(data != null){ Log.d(JamendoApplication.TAG, "Caller.doGet [cached] "+url); return data; } } URI encodedUri = null; HttpGet httpGet = null; try { encodedUri = new URI(url); httpGet = new HttpGet(encodedUri); } catch (URISyntaxException e1) { // at least try to remove spaces String encodedUrl = url.replace(' ', '+'); httpGet = new HttpGet(encodedUrl); e1.printStackTrace(); } // initialize HTTP GET request objects HttpClient httpClient = new DefaultHttpClient(); HttpResponse httpResponse; try { // execute request try { httpResponse = httpClient.execute(httpGet); } catch (UnknownHostException e) { throw new WSError("Unable to access " + e.getLocalizedMessage()); } catch (SocketException e){ throw new WSError(e.getLocalizedMessage()); } // request data HttpEntity httpEntity = httpResponse.getEntity(); if(httpEntity != null){ InputStream inputStream = httpEntity.getContent(); data = convertStreamToString(inputStream); // cache the result if(requestCache != null){ requestCache.put(url, data); } } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } Log.d(JamendoApplication.TAG, "Caller.doGet "+url); return data; }根据返回的字符串数据创建JSONArray对象,然后根据AlbumFunctions的静态函数getAlbums将封装在JSONArray中字符串数据转换为Album对象,然后放在数组中返回
public class AlbumFunctions { public static Album[] getAlbums(JSONArray jsonArrayAlbums) throws JSONException { int n = jsonArrayAlbums.length(); Album[] albums = new Album[n]; AlbumBuilder albumBuilder = new AlbumBuilder(); for(int i=0; i < n; i++){ albums[i] = albumBuilder.build(jsonArrayAlbums.getJSONObject(i)); } return albums; } }albums[i] = albumBuilder.build(jsonArrayAlbums.getJSONObject(i));这里又使用到了封装Album对象的AlbumBuilder类
public class AlbumBuilder extends JSONBuilder<Album> { @Override public Album build(JSONObject jsonObject) throws JSONException { Album album = new Album(); album.setImage(jsonObject.getString(root+"image")); album.setName(jsonObject.getString(root+"name")); album.setId(jsonObject.getInt(root+"id")); try { album.setArtistName(jsonObject.getString(root+"artist_name")); } catch (JSONException e) { // if we miss artist name an we are not in a subquery, abort! if(root.length()==0) throw e; } try { album.setRating(jsonObject.getDouble(root+"rating")); } catch (JSONException e) { album.setRating(-1); } return album; } }将JSONObject封装成Album对象
备注一:
以上只是对getPopularAlbumsWeek()这个函数的分析,但是具有通用性,其他的函数也都是这样实现的,首先通过HTTP根据url获取网络数据将流数据转换成字符串数据,然后通过JSON进行封装,然后通过相应的构造类如上面的AlbumBuilder将JSONArray中的JSONObject封装成相应的Album对象。
现在对这个代码最大的感觉是,这个代码写的很规范,无论是包结构还是类结构以及代码都非常规范,让人很容易就能了解整个程序的概貌,确实是值得好好学习的一个开源项目。