【Android前端】Bing每日图片列表应用制作记录——4.获取网络数据(下)
2017-09-16 16:54
681 查看
第四篇:获取网络数据(下)
上次我们成功获得了来自网络的Json字符串,但是显然还需要对json字符串进行处理,使其变成我们需要的url和文字说明。而GSON恰好就是我们需要的工具。GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库,它可以将一个Json字符转成一个Java对象,或者将一个Java对象转化为Json字符串。 它具有以下几个特点:快速、高效 ;代码量少、简洁 ;面向对象;数据传递和解析方便。
正好借着这个机会我们也可以学习外部库的使用。
第一部分:GSON
为了使用GSON库,首先在app/build.gradle中添加依赖,这也是使用其他外部库的第一步:dependencies { ... compile 'com.google.code.gson:gson:2.6.2' }
如果你使用的是Eclipse,那么请去Google官网下载相应的jar包,效果完全一样。
然后GSON是基于事件驱动的,根据所需要取的数据通过建立一个对应于JSON数据的JavaBean类才能解析出所需JSON数据,也就是为GSON提供处理后的格式标准。关于JavaBean类我推荐想了解的看一下这一篇博文,说得很简单易懂。不过使用AS的话并不需要人工编写Bean类,因为已经有非常懒人的插件GsonFormat了,下面讲一讲怎么用:
首先在菜单里找到File->Settings..->Plugins–>Browse repositores..,然后搜索GsonFormat
然后点击右边的Install安装,完成后重启AS,这样这个插件就可以用了。
实际使用时我们需要先新建一个类BingPic(名称可以自行改动),然后在菜单里找到Code->Generate..->GsonFormat,然后把json字符串粘贴进弹出的窗口就可以生成相应的Bean类了,实际效果就像下面这样:
最后就是在DataAsyncTask里重新实现doInBackground()方法了,直接上代码:
@Override protected Void doInBackground(Integer... param) { try{ String path = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=5&mkt=zh-CN"; URL url = new URL(path); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); urlConn.setConnectTimeout(5000); urlConn.connect(); if (urlConn.getResponseCode() == 200) { String data = readStream(urlConn.getInputStream()); Type type= new TypeToken<BingPic>(){}.getType(); Gson gson = new Gson(); BingPic bingPic = gson.fromJson(data,type); Log.i(TAG, "请求成功"); } else { Log.i(TAG, "请求失败"); } urlConn.disconnect(); }catch (Exception e){ e.printStackTrace(); } return null; }可以看到实际过程分为三步:获取Bean类格式->声明Gson变量->调用fromJson()方法生成BingPic类型的变量。这样我们需要的数据就存储在这个bingPic变量里了。
第二部分:信息的处理
转换是完成了,可是我们还需要把这些转换后的数据展现出来。首先回到getData()方法,上次我们把DataAsyncTask放在了这里,但是我们知道这里应该返回一个List,那么DataAsyncTask就应该返回一个List。而为了让它能够返回数据,这里就要用到AsyncTask的get()方法了,使用方法如下:
public List<Map<String,Object>> getData() { try{ myTask = new DataAsyncTask(); list.addAll(myTask.execute(0).get()); }catch (Exception e){ e.printStackTrace(); } return list; }addAll()我们上次已经讲过了,不过添加上这行代码编译器也会立刻提醒你类型不对,仔细一看就能发现get()实际返回的是onPostExecute(Result)里的Result参数,也就是doInBackground()的返回值。这样的话我们就在doInBackground()里完成List的构建就可以了,需要注意的是DataAsyncTask本身的继承和构造方法都要相应修改:
package com.xugino.bingpicanother; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.util.Log; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static android.content.ContentValues.TAG; class DataAsyncTask extends AsyncTask<Integer,Void,List<Map<String,Object>>> { private List<Map<String,Object>> list; DataAsyncTask(){ super(); list = new ArrayList<>(); } @Override protected List<Map<String,Object>> doInBackground(Integer... param) { try{ String path = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=5&mkt=zh-CN"; URL url = new URL(path); HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); urlConn.setConnectTimeout(5000); urlConn.connect(); if (urlConn.getResponseCode() == 200) { int i; Map<String,Object> map; String data = readStream(urlConn.getInputStream()); Type type= new TypeToken<BingPic>(){}.getType(); Gson gson = new Gson(); BingPic bingPic = gson.fromJson(data,type); for(i=0;i<5;i++){ map=new HashMap<>(); map.put("pic",getBitmap("http://cn.bing.com"+bingPic.getImages().get(i).getUrl())); map.put("text",bingPic.getImages().get(i).getCopyright()); map.put("time",bingPic.getImages().get(i).getEnddate()); list.add(map); } Log.i(TAG, "请求成功"); } else { Log.i(TAG, "请求失败"); } urlConn.disconnect(); }catch (Exception e){ e.printStackTrace(); } return list; } private static Bitmap getBitmap(String path) throws IOException { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); if (conn.getResponseCode() == 200){ InputStream inputStream = conn.getInputStream(); Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(inputStream),150,150,true); conn.disconnect(); return bitmap; } conn.disconnect(); return null; } private String readStream(InputStream inputStream) throws IOException{ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while((len=inputStream.read(buffer))!=-1){ outputStream.write(buffer,0,len); outputStream.flush(); } outputStream.close(); inputStream.close(); return outputStream.toString(); } }新增添的getBitmap()方法用于从图片的url得到可以显示的bitmap,需要注意createScaledBitmap()方
4000
法是带有缩放变形的生成,这也是为了能把整张图都放进来。
当然Adapter也要相应的修改一下:
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if(convertView==null){ viewHolder = new ViewHolder(); convertView=mInflater.inflate(R.layout.list_item,null); viewHolder.pic=convertView.findViewById(R.id.item_pic); viewHolder.text=convertView.findViewById(R.id.item_text); viewHolder.time=convertView.findViewById(R.id.item_time); viewHolder.btn=convertView.findViewById(R.id.download_btn); convertView.setTag(viewHolder); }else{ viewHolder=(ViewHolder)convertView.getTag(); } viewHolder.pic.setImageBitmap((Bitmap) data.getList().get(position).get("pic")); viewHolder.text.setText((CharSequence) data.getList().get(position).get("text")); viewHolder.time.setText((CharSequence) data.getList().get(position).get("time")); viewHolder.btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { } }); return convertView; }
为了方便访问减少冗余操作,重新实现DataResource()和initData():
public class DataResource { private List<Map<String,Object>> list; private DataAsyncTask myTask; public DataResource(){ list=new ArrayList<>(); } public List<Map<String,Object>> getList() { return list; } public void getData() { try{ myTask = new DataAsyncTask(); list.addAll(myTask.execute(0).get()); }catch (Exception e){ e.printStackTrace(); } } }
private void initData(){ data.getData(); mList.addAll(data.getList()); mAdapter.notifyDataSetChanged(); }
最后调试一下来看看效果:
可以说是符合预期了,不过瑕疵多了点。
下一期的话先暂停一点进度,做一点面子工程来让用户用着舒服一点。
(说明:这次做的很多已经跟最初贴上去的那个git项目有不少出入了,基本都是改良和规范,新的代码我也贴上github了大家自取)
相关文章推荐
- 【Android前端】Bing每日图片列表应用制作记录——2.列表的实现
- 【Android前端】Bing每日图片列表应用制作记录——1.从零开始
- Android数据存储:获取网络图片把图片保存到SD卡中并从SDk卡中读取(通过Bitmap方法)
- 【android基础】之Android获取网络上的图片结合ImageView的简单应用
- android 网络编程--URL获取数据/图片
- Android HttpURLConnection(Get,Post方式)进行网络通信 获取数据和网络图片
- Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)
- Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)
- android 从网络上获取数据(图片,网页,xml,json等)
- android ViewPager实现的轮播图广告自定义视图,网络获取图片和数据
- android_学习—获取网络数据(图片,html)
- 【android初级】之Android之从网络上获取数据(图片,网页,xml,json等)
- Android获取网络图片应用示例
- android 网络编程--URL获取数据/图片
- Android获取网络图片应用示例
- Android异步加载获取网络数据(图片)
- android volley获取网络图片制作圆头像
- Android成长之路-获取网络数据(图片)
- 我们的应用或多或少都会从网络获取图片数据然后进行显示,下面就将实现一个这样的例子,获取网络中的图片!
- android端获取网络数据添加到二级列表ExpandableListView