使用Agera,gson,okhttp获取豆瓣读书数据
2016-05-29 22:27
483 查看
使用Agera,GSON和okhttp解析数据
本文使用的是豆瓣读书的API项目演示:
demo下载地址:AgeraDemo
实现在线查找图书的功能,整合了okhttp,gson,agera框架
API测试URL格式:
URl:https://api.douban.com/v2/book/search?q=
返回数据
{ "count":1, "start":0, "total":770, "books":[ { "rating":{ "max":10, "numRaters":199539, "average":"9.0", "min":0 }, "subtitle":"", "author":[ "[法] 圣埃克苏佩里" ], "pubdate":"2003-8", "tags":[ { "count":48852, "name":"小王子", "title":"小王子" }, { "count":40834, "name":"童话", "title":"童话" }, { "count":19514, "name":"圣埃克苏佩里", "title":"圣埃克苏佩里" }, { "count":17606, "name":"法国", "title":"法国" }, { "count":16728, "name":"经典", "title":"经典" }, { "count":12965, "name":"外国文学", "title":"外国文学" }, { "count":9317, "name":"哲学", "title":"哲学" }, { "count":6809, "name":"小说", "title":"小说" } ], "origin_title":"Le Petit Prince", "image":"https://img1.doubanio.com\/mpic\/s1237549.jpg", "binding":"平装", "translator":[ "马振聘" ], "catalog":"第一卷 南渡记出版说明人物表序曲第一章 第二章第三章第四章第五章第六章第七章间曲后记第二卷 东藏记人物表……间曲后记\n", "pages":"97", "images":{ "small":"https://img1.doubanio.com\/spic\/s1237549.jpg", "large":"https://img1.doubanio.com\/lpic\/s1237549.jpg", "medium":"https://img1.doubanio.com\/mpic\/s1237549.jpg" }, "alt":"https:\/\/book.douban.com\/subject\/1084336\/", "id":"1084336", "publisher":"人民文学出版社", "isbn10":"702004249X", "isbn13":"9787020042494", "title":"小王子", "url":"https:\/\/api.douban.com\/v2\/book\/1084336", "alt_title":"Le Petit Prince", "author_intro":"author_intor................", "summary":"sumary...........................", "price":"22.00元" } ] }
布局文件
main<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.yangtianrui.doubanapitest.MainActivity"> <EditText android:id="@+id/id_et_key_word" android:layout_width="200dp" android:layout_height="50dp" /> <Button android:id="@+id/id_btn_query" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="submit" android:layout_alignParentRight="true" /> <ListView android:id="@+id/id_lv_all_items" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/id_et_key_word" /> </RelativeLayout>
每个book的布局文件
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent"> <TextView android:id="@+id/id_tv_book_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="book_title" android:textSize="15sp" /> <TextView android:layout_marginTop="20dp" android:id="@+id/id_tv_book_author" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="9sp"/> <TextView android:id="@+id/id_tv_book_subtitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="9sp"/> <TextView android:id="@+id/id_tv_book_publisher" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="9sp"/> </LinearLayout> </android.support.v7.widget.CardView>
Book javaBean类
根据Json字符串抽取了几个关键属性组成Bean对象用作测试/** * Created by yangtianrui on 16-5-29. */ public class Book { private String title; private String alt_Title; private String[] author; private String publisher; public Book(String title, String alt_Title, String[] author, String publisher) { this.title = title; this.alt_Title = alt_Title; this.author = author; this.publisher = publisher; } public Book() { } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAlt_Title() { return alt_Title; } public void setAlt_Title(String alt_Title) { this.alt_Title = alt_Title; } public String[] getAuthor() { return author; } public void setAuthor(String[] author) { this.author = author; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } @Override public String toString() { return "Book{" + "title='" + title + '}'; } }
supplier的实现类,通过此类进行数据检索,Repository从此处获取数据
此处是数据获取的关键,我使用了GSON和okhttp框架来对json进行处理,将该类将返回一个Result对象/** * Created by yangtianrui on 16-5-29. * 根据关键字,提供书籍数据 */ public class BooksSupplier implements Supplier<Result<List<Book>>> { private String key; // 用于建立连接 private OkHttpClient client = new OkHttpClient(); private Gson gson = new Gson(); private static final String API_URL = "https://api.douban.com/v2/book/search"; public void setKey(String key) { this.key = key; } public String getKey() { return key; } public BooksSupplier(String key) { this.key = key; } public BooksSupplier() { } private List<Book> getBooks() { Log.v("LOG", "getBooks"); HttpUrl httpUrl = HttpUrl.parse(API_URL).newBuilder() // 设置查询参数 .addQueryParameter("q", key) .addQueryParameter("start", "0") .addQueryParameter("count", "15") .build(); Request request = new Request.Builder().url(httpUrl).build(); try { // 建立连接 Response response = client.newCall(request).execute(); // 获取返回的Json // Log.v("LOG",response.body().toString()); JSONObject jsonObject = new JSONObject(response.body().string()); JSONArray jsonArray = jsonObject.optJSONArray("books"); List<Book> list = gson.fromJson(jsonArray.toString(), new TypeToken<List<Book>>() { }.getType()); // Log.v("LOG", list.toString()); return list; } catch (Exception e) { Log.v("LOG","error in getBooks()"+e.getMessage()); e.printStackTrace(); return null; } } // 获取数据 @NonNull @Override public Result<List<Book>> get() { List<Book> list = getBooks(); if (list != null) { return Result.success(list); } else { return Result.failure(); } } }
MainActivity中,创建Observer,对Repository中的数据进行获取,同时更新UI
使用goTo方法指定获取数据执行的线程使用thenGetFrom方法指定获取数据的Supplier
这里我们还使用了observe方法指定了一个searchObservable,后续我们可以使用searchObservable来发起事件调用。
在按钮的点击事件中,发起事件调用
// MainActivity中使用观察者更新数据 public class MainActivity extends AppCompatActivity implements Updatable { private ListView mLvAllBooks; private EditText mEtKey; private Button mBtnQuery; private MyAdapter mAdapter; private List<Book> mBooks = new ArrayList<>(); private ExecutorService mExecutor; private BooksSupplier mSupplier; private Repository<Result<List<Book>>> mRepository; private SearchObserver mObserver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setupRepository(); initView(); } /** * 初始化Repository */ private void setupRepository() { // 单线程线程池 mExecutor = Executors.newSingleThreadExecutor(); mObserver = new SearchObserver(); mSupplier = new BooksSupplier("Hello"); mRepository = Repositories .repositoryWithInitialValue(Result.<List<Book>>absent()) .observe(mObserver) .onUpdatesPerLoop() .goTo(mExecutor) .thenGetFrom(mSupplier) .compile(); } private void initView() { mLvAllBooks = (ListView) findViewById(R.id.id_lv_all_items); mEtKey = (EditText) findViewById(R.id.id_et_key_word); mBtnQuery = (Button) findViewById(R.id.id_btn_query); mRepository.addUpdatable(MainActivity.this); mAdapter = new MyAdapter(this, mBooks); mLvAllBooks.setAdapter(mAdapter); mBtnQuery.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String key = mEtKey.getText().toString(); mObserver.doSearch(key); Log.v("LOG", "Activity onClick " + key); } }); } private class SearchObserver extends BaseObservable { public void doSearch(String key) { mSupplier.setKey(key); dispatchUpdate(); Log.v("LOG", "Activity doSearch"); } } // 执行查询操作,处理调用结果 @Override public void update() { Log.v("LOG", "Activity update"); if (mRepository.get().isPresent()) { ///TODO mBooks.clear(); mBooks.addAll(mRepository.get().get()); mAdapter.notifyDataSetChanged(); Log.v("LOG", mBooks.toString()); } } }
Adapter类
/** * Created by yangtianrui on 16-5-29. */ public class MyAdapter extends BaseAdapter { private List<Book> mBooks; private LayoutInflater mInflater; private Context mContext; public MyAdapter(Context context, List<Book> list) { mInflater = LayoutInflater.from(context); mContext = context; mBooks = list; } @Override public int getCount() { return mBooks.size(); } @Override public Object getItem(int position) { return mBooks.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.item_book, null); holder = new ViewHolder(); holder.mTvTitle = (TextView) convertView.findViewById(R.id.id_tv_book_title); holder.mTvAuthor = (TextView) convertView.findViewById(R.id.id_tv_book_author); holder.mTvSubTitle = (TextView) convertView.findViewById(R.id.id_tv_book_subtitle); holder.mTvPublisher = (TextView) convertView.findViewById(R.id.id_tv_book_publisher); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.mTvTitle.setText(mBooks.get(position).getTitle()); holder.mTvSubTitle.setText(mBooks.get(position).getAlt_Title()); if (mBooks.get(position).getAuthor().length != 0) holder.mTvAuthor.setText(mBooks.get(position).getAuthor()[0]); holder.mTvPublisher.setText(mBooks.get(position).getPublisher()); return convertView; } static class ViewHolder { TextView mTvTitle; TextView mTvAuthor; TextView mTvSubTitle; TextView mTvPublisher; } }
发现自己还是对观察者模式和Agera框架了解不够, 文章也许写的太过表面了,我会继续学习的:-)
相关文章推荐
- Chp6 域名系统DNS
- Tinyhttp源码分析
- 20159217《网络攻防实践》第十三周学习总结
- TCP延迟确认
- 图片的HTTP请求
- HttpClient get请求在HttpResponse中无法获得Location的问题
- Socket实现两台手机通信,定向转发数据
- SOCKET API和TCP STATE的对应关系__三次握手(listen,accept,connect)__四次挥手close及TCP延迟确认(调用一次setsockopt函数,设
- TCP/IP模型 ,Socket编程总结
- 或许是 Nginx 上配置 HTTP2 最实在的教程了
- Ubuntu l连接网络
- Go学习笔记二: 函数,文件操作及网络通信
- Tinyhttp服务器编译运行
- BSOJ: 1708 【USACO 2008 January Gold】Cell Phone Network手机网络
- Android学习(58) -- xUtils之HttpUtils
- 《matlab神经网络43个案例》第三章代码纠错
- Windows中附加IP引起的网络悬案
- http header mark to memory
- Tensorflow的MNIST进阶教程CNN网络参数理解
- 一张图说明CDN网络的原理