程序中实现网络连接和获取网络数据是通过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对象。
现在对这个代码最大的感觉是,这个代码写的很规范,无论是包结构还是类结构以及代码都非常规范,让人很容易就能了解整个程序的概貌,确实是值得好好学习的一个开源项目。