技术要点及实现方法:
1.Json数据的获取--HttpUrlConnection或xUtils第三方类库
2.Json数据的解析--Gson第三方类库
3.更新UI的三种方式--runOnUIThread、post、handleMessage
4.数据展示--RecyclerView
5.菜单栏切换ListView、GridView、瀑布流效果
准备工作:
1.需要Json数据,数据来源:聚合天气城市的接口数据,下载地址:http://pan.baidu.com/s/1kVc2mz1,提取码:7wpj,将json文件放置在apache-tomcat-7.0.42\webapps\ROOT目录下
2.电脑上需要搭建tomcat服务器(若有接口调用,不需tomcat服务器,但是个人建议,搭建一个服务器有利于个人开发。有了服务器,可以进行很多网络操作,如数据的上传、下载、软件更新等等功能)
tomcat服务器下载地址:http://download.csdn.net/detail/tideseng/9670507,无需安装,解压即可,具体使用方法请看简介
3.在AndroidStudio中导入RecyclerView的v7包
4.在AndroidStudio中导入Gson架包
5.在AndroidStudio中导入xutils架包,在app目录下的build.gradle里加入:useLibrary 'org.apache.http.legacy'
注意:
1.访问网络需要加Intent权限
2.访问服务器需要开启tomcat服务器,双击“startup.bat“,关闭则双击"shutdown.bat"
先看实现效果图:
实现代码:
activity的布局代码:
菜单栏item
网络链接地址类GlobalConstants.java代码:
public class GlobalConstants { // IP查询方法:在cmd命令行窗口输入--ipconfig public static final String SERVER_URL = "http://192.125.136.1:8080";//真机访问地址(IP为无线局域网的IPv4地址) // public static final String SERVER_URL = "http://169.252.975.164:8080";//模拟器访问地址(IP为以太网的IPv4地址) public static final String CITY_LIST_URL = SERVER_URL + "/JuHeCityList.json";// 城市名单接口 }
流转字符串工具类StreamUtil.java:
public class StreamUtil { public static String StramToString(InputStream is) { // 在读取的过程中,将读取的内容存储值缓存中,然后一次性的转换成字符串返回 ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 读流操作,读到没有为止(循环) byte[] buffer = new byte[1024]; // 记录读取内容的临时变量 int temp = -1; // 每次读取1024个字节,若能读到,返回赋给temp,只要不为-1,说明还有内容 try { while ((temp = is.read(buffer)) != -1) { bos.write(buffer, 0, temp); } //返回读取数据 return bos.toString(); } catch (IOException e) { e.printStackTrace(); }finally{ try { is.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } }
将Json数据转化为bean对象:
public class CityBean { public String resultcode; public String error_code; public String reason; // Json中遇到[]创建集合 public ArrayListresult; // Json中遇到{}创建对象 public class city{ public String id; public String province; public String city; public String district; // 要解析的字段需要生成set、get方法,并toString public String getId() { return id; } public void setId(String id) { this.id = id; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getDistrict() { return district; } public void setDistrict(String district) { this.district = district; } @Override public String toString() { return "city{" + "id='" + id + '\'' + ", province='" + province + '\'' + ", city='" + city + '\'' + ", district='" + district + '\'' + '}'; } } public String getResultcode() { return resultcode; } public void setResultcode(String resultcode) { this.resultcode = resultcode; } public String getError_code() { return error_code; } public void setError_code(String error_code) { this.error_code = error_code; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } public ArrayList getResult() { return result; } public void setResult(ArrayList result) { this.result = result; } @Override public String toString() { return "CityBean{" + "resultcode='" + resultcode + '\'' + ", error_code='" + error_code + '\'' + ", reason='" + reason + '\'' + ", result=" + result + '}'; } }
public class CityListAdapter extends RecyclerView.Adapter{ private final ArrayList mCitys; private final LayoutInflater mInflater; private final AddCityActivity mContent; private ArrayList mHeights; public CityListAdapter(ArrayList results, AddCityActivity content) { mCitys = results; mContent = content; mInflater = LayoutInflater.from(mContent); } // 创建ViewHolder,添加item的布局 @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = mInflater.inflate(R.layout.item_recyclerview, parent, false); MyViewHolder viewHolder = new MyViewHolder(view); return viewHolder; } // 绑定ViewHolder,设置数据 @Override public void onBindViewHolder(MyViewHolder holder, int position) { // 给条目控件设置数据 holder.id_tv.setText(mCitys.get(position).getDistrict()); } @Override public int getItemCount() { return mCitys.size(); } // 定义ViewHolder class MyViewHolder extends RecyclerView.ViewHolder { TextView id_tv; public MyViewHolder(View itemView) { super(itemView); id_tv = (TextView) itemView.findViewById(R.id.id_tv); } } }
瀑布流的适配器CityStaggeredAdapter.java:
public class CityStaggeredAdapter extends RecyclerView.Adapter{ private final ArrayList mCitys; private final LayoutInflater mInflater; private final AddCityActivity mContent; private ArrayList mHeights; public CityStaggeredAdapter(ArrayList results, AddCityActivity content) { mCitys = results; mContent = content; mInflater = LayoutInflater.from(mContent); // 得到随机高度,实现瀑布流效果 mHeights = new ArrayList<>(); for (int i = 0; i < mCitys.size(); i++) { mHeights.add((int) (100 + Math.random() * 300)); } } // 创建ViewHolder,添加item的布局 @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = mInflater.inflate(R.layout.item_recyclerview, parent, false); MyViewHolder viewHolder = new MyViewHolder(view); return viewHolder; } // 绑定ViewHolder,设置数据 @Override public void onBindViewHolder(MyViewHolder holder, int position) { // 动态设置高度 ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); layoutParams.height = mHeights.get(position); holder.itemView.setLayoutParams(layoutParams); // 给条目控件设置数据 holder.id_tv.setText(mCitys.get(position).getDistrict()); } @Override public int getItemCount() { return mCitys.size(); } // 定义ViewHolder class MyViewHolder extends RecyclerView.ViewHolder { TextView id_tv; public MyViewHolder(View itemView) { super(itemView); id_tv = (TextView) itemView.findViewById(R.id.id_tv); } } }
public class AddCityActivity extends AppCompatActivity{ private EditText et_add_city; private RecyclerView rv_city; private ArrayListmResults; private CityListAdapter mCityListAdapter; private String mJson; @Override protected void onCreate( Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } // 初始化控件 private void initView() { et_add_city = (EditText) findViewById(R.id.et_add_city); rv_city = (RecyclerView) findViewById(R.id.rv_city); } // 初始化数据 private void initData() { // ①通过通过HttpUrlConnection获取网络Json数据 // getServerDataByHttpUrlConnection(); // ①通过通过xUtils获取网络Json数据(不需开启子线程,也不需通过handle等返回主线程更新UI) getServerDataByxUtils(); } private void getServerDataByxUtils() { HttpUtils httpUtils = new HttpUtils(); httpUtils.send(HttpRequest.HttpMethod.GET, GlobalConstants.CITY_LIST_URL, new RequestCallBack () { @Override public void onSuccess(ResponseInfo responseInfo) { // 请求成功,返回结果 mJson = responseInfo.result;// 获取服务器返回结果 System.out.println("服务器获取的json数据:" + mJson); // 用于解析数据... processData(); } @Override public void onFailure(HttpException e, String s) { // 请求失败,返回异常日志error、错误信息msg e.printStackTrace(); Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show(); } }); } // // 开启子线程,①通过HttpUrlConnection获取网络Json数据 /*private void getServerDataByHttpUrlConnection() { new Thread(){ @Override public void run() { super.run(); try { // 根据url地址开启链接并设置参数 // 获取url地址 URL url = new URL(GlobalConstants.CITY_LIST_URL); // 根据url地址开启链接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 设置请求参数 connection.setConnectTimeout(2000); connection.setReadTimeout(2000); // 响应码成功后获取输入流并转为字符串 // 判断请求响应码 if (connection.getResponseCode() == 200){ // 获取输入流 InputStream is = connection.getInputStream(); // 流转字符串 mJson = StreamUtil.StramToString(is); System.out.println("获得的json数据为:" + mJson); // 开始解析数据... processData(); } } catch (Exception e) { e.printStackTrace(); } } }.start(); }*/ private void processData() { // ②通过Gson解析Json数据 Gson gson = new Gson(); CityBean cityJson = gson.fromJson(mJson, CityBean.class); System.out.println("Gson解析的数据为:" + cityJson); // 得到城市集合数据 mResults = cityJson.result; System.out.println("result为:" + mResults); System.out.println("第1个条目的city名为:" + mResults.get(0).getCity()); // 由于xUtils封装好了,所以直接更新UI即可 initAdapter(); /*// ③3.2发送handle消息 // Message msg = Message.obtain(); // msg.what = PROCESS_DATA; // mHandler.sendMessage(msg);*/ // // ③1.通过runOnUiThread来更新UI // runOnUiThread(new Runnable() { // @Override // public void run() { // initAdapter(); // } // }); // ③2.2通过post来更新UI // mHandler.post(new Runnable() { // @Override // public void run() { // initAdapter(); // } // }); } // ③2.1通过post来更新UI // private Handler mHandler = new Handler(); // ③3.1通过handleMessage来更新UI /*private static final int PROCESS_DATA = 0; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case PROCESS_DATA: // 获取数据成功后,解析数据 initAdapter(); } } };*/ // 创建适配器显示数据 private void initAdapter() { // ④用RecyclerView展示数据 mCityListAdapter = new CityListAdapter(mResults, this); rv_city.setAdapter(mCityListAdapter); // 设置RecyclerView布局管理 // ListView布局 LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false); rv_city.setLayoutManager(layoutManager); } // ⑤菜单栏切换ListView、GridView、瀑布流效果 @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()){ case R.id.action_listview: rv_city.setAdapter(new CityListAdapter(mResults, this)); rv_city.setLayoutManager(new LinearLayoutManager(getApplicationContext())); break; case R.id.action_gridview: rv_city.setAdapter(new CityListAdapter(mResults, this)); rv_city.setLayoutManager(new GridLayoutManager(getApplicationContext(), 3)); break; case R.id.action_staggered: rv_city.setAdapter(new CityStaggeredAdapter(mResults, this)); rv_city.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)); break; default: break; } return super.onOptionsItemSelected(item); } }