前言
本章,我们为PhotoGallery应用添加搜索功能。借此学习如何使用SearchView在应用中整合搜索功能。SearchView是个可以嵌入工具栏的操作视图类(action view)。点按SearchView,用户可以输入查询关键字,提交查询请求搜索Flickr,返回结果将显示在RecyclerView中,如图27-1所示。用户提交过的查询关键字会保存下来。这样,即便应用或设备重启,依然可以找回他们。
一、搜索 Flickr 网站
搜索Flickr网站需要调用flickr.photos.search方法。以下为搜索cat文本的GET请求示例:
https://api.flickr.com/services/rest/?method=flickr.photos.search
&api_key=xxx&format=json&nojsoncallback=1&text=cat
可以看到,搜索方法指定为flickr.photos.search。一个text新参数附加在请求后面,它的内容就是cat这样的搜索字符串。虽然搜索URL和图片下载请求URL不同,但网站返回的JSON数据格式是一样的。这方便了开发,因为不管是搜索还是下载图片,我们都可以使用同样的JSON数据解析逻辑。首先,重构FlickrFetchr代码以复用JSON数据解析逻辑。先添加一些URL复用相关的常量。再从fetchItems方法中剪切URI创建代码,复制作为ENDPOINT的值。注意,只应使用加亮部分的代码。ENDPOINT常量不应包括查询方法参数,build语句不应使用toString()方法。如代码清单27-1所示。
代码清单27-1 添加URL常量(FlickrFetchr.java)
public class FlickrFetchr {
private static final String TAG = "FlickrFetchr";
private static final String API_KEY = "yourApiKeyHere";
private static final String FETCH_RECENTS_METHOD = "flickr.photos.getRecent";
private static final String SEARCH_METHOD = "flickr.photos.search";
private static final Uri ENDPOINT = Uri
.parse("https://api.flickr.com/services/rest/")
.buildUpon()
.appendQueryParameter("api_key", API_KEY)
.appendQueryParameter("format", "json")
.appendQueryParameter("nojsoncallback", "1")
.appendQueryParameter("extras", "url_s")
.build();
...
public List<GalleryItem> fetchItems() {
List<GalleryItem> items = new ArrayList<>();
try {
String url = Uri.parse("https://api.flickr.com/services/rest/")
.buildUpon()
.appendQueryParameter("method", "flickr.photos.getRecent")
.appendQueryParameter("api_key", API_KEY)
.appendQueryParameter("format", "json")
.appendQueryParameter("nojsoncallback", "1")
.appendQueryParameter("extras", "url_s")
.build().toString();
String jsonString = getUrlString(url);
...
} catch (IOException ioe) {
Log.e(TAG, "Failed to fetch items", ioe);
} catch (JSONException je) {
Log.e(TAG, "Failed to parse JSON", je);
}
return items;
}
...
}
为了通用,重命名fetchItems()方法为downloadGalleryItems(String url)。新方法也
不应是公共的了,所以改成私有方法,如代码清单27-2所示。
代码清单27-2 重构Flickr代码(FlickrFetchr.java
)
public class FlickrFetchr {
...
public List<GalleryItem> fetchItems() {
private List<GalleryItem> downloadGalleryItems(String url) {
List<GalleryItem> items = new ArrayList<>();
try {
String jsonString = getUrlString(url);
Log.i(TAG, "Received JSON: " + jsonString);
JSONObject jsonBody = new JSONObject(jsonString);
parseItems(items, jsonBody);
} catch (IOException ioe) {
Log.e(TAG, "Failed to fetch items", ioe);
} catch (JSONException je) {
Log.e(TAG, "Failed to parse JSON", je);
}
return items;
}
...
}
downloadGalleryItems(String)新方法使用URL参数,不用再创建URL了。所以,在其内
部添加一个新方法基于用户功能(搜索或下载)和查询值创建URL,如代码清单27-3所示。
代码清单27-3 添加创建URL的辅助方法(FlickrFetchr.java)
public class FlickrFetchr {
...
private List<GalleryItem> downloadGalleryItems(String url) {
...
}
private String buildUrl(String method, String query) {
Uri