技术要点及实现方法:
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的布局代码:
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/yin_bg"
android:orientation="vertical">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingBottom="20dp"
android:paddingTop="20dp"
android:text="添加城市"/>
android:id="@+id/et_add_city"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@drawable/editview_shape"
android:drawableLeft="@drawable/sousuo"
android:ems="12"
android:hint="请输入城市名称"
android:padding="5dp"
android:singleLine="true"/>
android:id="@+id/rv_city"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"/>
圆角矩形框editview_shape.xml背景代码:
android:shape="rectangle">
android:color="#ffffff"/>
RecyclerView的条目代码item_recyclerview.xml:
android:layout_margin="3dp"
android:background="#44ff0000"
android:layout_width="match_parent"
android:layout_height="72dp">
android:id="@+id/id_tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="25sp"
android:textColor="#000"/>
菜单栏item
xmlns:app="http://schemas.android.com/apk/res-auto">
android:id="@+id/action_search"
android:orderInCategory="100"
android:title="Add"
android:icon="@drawable/menu_search"
app:showAsAction="ifRoom"/>
android:id="@+id/action_remind"
android:orderInCategory="100"
android:title="Delete"
android:icon="@drawable/menu_remind"
app:showAsAction="ifRoom"/>
android:id="@+id/action_listview"
android:orderInCategory="100"
android:title="ListView"
app:showAsAction="never"/>
android:id="@+id/action_gridview"
android:orderInCategory="100"
android:title="GridView"
app:showAsAction="never"/>
android:id="@+id/action_staggered"
android:orderInCategory="100"
android:title="StaggeredGridView"
app:showAsAction="never"/>
网络链接地址类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 ArrayList result;
// 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 +
'}';
}
}
适配器CityListAdapter.java:
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);
}
}
}
activity代码:
public class AddCityActivity extends AppCompatActivity{
private EditText et_add_city;
private RecyclerView rv_city;
private ArrayList mResults;
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);
}
}