1.我在本地搭建的服务端,基于springmvc,hibernate和注解,写了一个简单查询方法:
@RequestMapping(value="/topicjson.do",method=RequestMethod.GET)
@ResponseBody
public void topicjson(HttpSession session,HttpServletRequest request,HttpServletResponse response){
Listtopiclist=this.topicservice.getAllTopic();
for (TBaseTopic tBaseTopic : topiclist) {
tBaseTopic.setPublishdatestr(DateUtil.formatDate(tBaseTopic.getPublishdate(), "yyyy-MM-dd HH:mm"));
}
JSONArray array=JSONArray.fromObject(topiclist);
response.setContentType("text/json;charset=utf-8");//设置编码
PrintWriter out=null;
try {
out = response.getWriter();
} catch (Exception e) {
}
out.print(array.toString());
}
将查询出来的数据集合转成jsonArray,然后out.print(array.toString());将结果打印出来,要注意的是需要设置下数据格式和编码,不然中文会出现乱码问题。
先通过浏览器访问这个方法:http://192.168.56.1/springtest/topicaction/topicjson.do
ip是我们手机端访问我们本地服务器的ip,cmd,ipconfig,以太网IPv4
然后可以看到页面上的json格式的数据:
[{"comment":0,"heart":3,"id":"1","image":"","nickname":"管理员","publishdate":{"date":8,"day":4,"hours":7,"minutes":0,"month":11,"nanos":0,"seconds":0,"time":1481151600000,"timezoneOffset":-480,"year":116},"publishdatestr":"2016-12-08 07:00","topic":"如果再给你一次回去的机会,你想回到什么时候?","userid":"1001"},{"comment":0,"heart":22,"id":"2","image":"","nickname":"管理员","publishdate":{"date":28,"day":2,"hours":0,"minutes":0,"month":1,"nanos":0,"seconds":0,"time":1488211200000,"timezoneOffset":-480,"year":117},"publishdatestr":"2017-02-28 00:00","topic":"薛之谦的歌总能莫名其妙的戳中泪点","userid":"1001"},{"comment":0,"heart":221,"id":"3","image":"","nickname":"管理员","publishdate":{"date":28,"day":2,"hours":0,"minutes":0,"month":1,"nanos":0,"seconds":0,"time":1488211200000,"timezoneOffset":-480,"year":117},"publishdatestr":"2017-02-28 00:00","topic":"致陪伴我们每天的网易云音乐","userid":"1001"},{"comment":0,"heart":1,"id":"4","image":"","nickname":"管理员","publishdate":{"date":28,"day":2,"hours":0,"minutes":0,"month":1,"nanos":0,"seconds":0,"time":1488211200000,"timezoneOffset":-480,"year":117},"publishdatestr":"2017-02-28 00:00","topic":"说说你童年时候给你印象深刻的一件事","userid":"1001"},{"comment":7,"heart":0,"id":"5","image":"","nickname":"管理员","publishdate":{"date":1,"day":3,"hours":0,"minutes":0,"month":2,"nanos":0,"seconds":0,"time":1488297600000,"timezoneOffset":-480,"year":117},"publishdatestr":"2017-03-01 00:00","topic":"高中时候的你有没有曾为理想奋斗过","userid":"1001"},{"comment":6,"heart":6,"id":"6","image":"","nickname":"管理员","publishdate":{"date":1,"day":3,"hours":0,"minutes":0,"month":2,"nanos":0,"seconds":0,"time":1488297600000,"timezoneOffset":-480,"year":117},"publishdatestr":"2017-03-01 00:00","topic":"杭漂的日子里都有谁陪你度过","userid":"1001"},{"comment":0,"heart":7,"id":"7","image":"","nickname":"管理员","publishdate":{"date":1,"day":3,"hours":0,"minutes":0,"month":2,"nanos":0,"seconds":0,"time":1488297600000,"timezoneOffset":-480,"year":117},"publishdatestr":"2017-03-01 00:00","topic":"七八十年代那时候年轻人的娱乐方式","userid":"1001"},{"comment":0,"heart":4,"id":"8","image":"","nickname":"管理员","publishdate":{"date":1,"day":3,"hours":0,"minutes":0,"month":2,"nanos":0,"seconds":0,"time":1488297600000,"timezoneOffset":-480,"year":117},"publishdatestr":"2017-03-01 00:00","topic":"七八十年代那时候年轻人的娱乐方式","userid":"1001"},{"comment":0,"heart":2,"id":"9","image":"","nickname":"管理员","publishdate":{"date":1,"day":3,"hours":0,"minutes":0,"month":2,"nanos":0,"seconds":0,"time":1488297600000,"timezoneOffset":-480,"year":117},"publishdatestr":"2017-03-01 00:00","topic":"七八十年代那时候年轻人的娱乐方式","userid":"1001"}]
2.下面就是手机端ListView加载数据这块的开发了,总结一下:
UI线程中不能去加载数据
okhttp请求数据
ListView数据填充
3.新建一个实体类,TBaseUser.java
package com.imooc.forum.entity;
/**
* Created by lsk on 2017/3/5.
*/
public class TBaseUser {
private String id;
private String topic;
public TBaseUser(){}
public TBaseUser(String id,String topic){
this.id=id;
this.topic=topic;
}
public String getId(){
return id;
}
public void setId(String id){
this.id=id;
}
public String getTopic(){
return topic;
}
public void setTopic(String topic){
this.topic=topic;
}
}
4.新建一个请求数据的工具类,MyHttpUtil.java
package com.imooc.forum.httputil;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import java.io.IOException;
/**
* Created by lsk on 2017/3/9.
*/
public class MyHttpUtil {
String str="";
public String httpGet(String url){
OkHttpClient okHttpClient=new OkHttpClient();
Request.Builder builder=new Request.Builder();
Request request=builder.get().url(url).build();
Call call=okHttpClient.newCall(request);
//同步GET请求
try {
Response response=call.execute();
if(!response.isSuccessful()) {
Headers responseHeaders = response.headers();
for (int i = 0; i < responseHeaders.size(); i++) {
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
}
}
str= response.body().string();
}catch (Exception e){
e.printStackTrace();
}
//异步GET请求
/*call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Response response) throws IOException {
str=response.body().toString();
}
});*/
return str;
}
}
需要在项目中添加okhttp的依赖,打开build.gradle,在dependencies中添加一行:
compile 'com.squareup.okhttp:okhttp:2.6.0'
然后你会看到上面会出现一行提示,Sync Now,点击它会自动给你添加jar包,然后Open Module Setting,dependencies,你会看到我们需要的jar已经添加上了。
通过Request.Builder构造一个request,然后将request当做一个参数传到okHttpClient.newCall()方法中,返回一个call,call执行,返回response,从response的body()获取数据,这里要注意的是用string()方法获得字符串,而不是toString()
4.然后看布局文件,activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mylistview"
>
ListView>
RelativeLayout>
我们还要自己定义一个布局文件,用于ListView的每一项的填充布局,mylistitem.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/mylistitem"
android:paddingBottom="3dp"
android:paddingLeft="10dp"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="@+id/ItemTitle"
android:textSize="30dip">
TextView>
<TextView
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="@+id/ItemText">
TextView>
LinearLayout>
这里只是简单的定义两个TextView显示测试数据
5.基础工作做好后,就要看MainActivity我们的主页面了
package com.imooc.forum;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.imooc.forum.entity.TBaseUser;
import com.imooc.forum.httputil.MyHttpUtil;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.RunnableFuture;
public class MainActivity extends AppCompatActivity {
ListView listView;
File cache;//缓存文件
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
listView.setAdapter(new ContactAdapter(MainActivity.this,(List)msg.obj,R.layout.mylistitem,cache));
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.mylistview);
cache=new File(Environment.getExternalStorageDirectory(), "cache"); // 实例化缓存文件
if (!cache.exists())cache.mkdirs(); // 如果文件不存在,创建
new Thread(new Runnable() {
@Override
public void run() {
try {
List data =getTBaseUser();
// 通过handler来发送消息,通知主线程去更新UI
handler.sendMessage(handler.obtainMessage(22, data));
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
//加载远程数据
private ListgetTBaseUser(){
String url="http://192.168.56.1/springtest/topicaction/topicjson.do";//网络请求路径
Listlist=new ArrayList<>();
MyHttpUtil httpUtil=new MyHttpUtil();
String str=httpUtil.httpGet(url);//获取请求的数据
Log.d(str,"msg");
try {
JSONArray array=new JSONArray(str);
for(int i=0;i
JSONObject object=(JSONObject) array.get(i);
TBaseUser user=new TBaseUser();
user.setId(object.get("id").toString());
user.setTopic(object.get("topic").toString());
list.add(user);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
@Override
protected void onDestroy() {
// 删除缓存
for (File file : cache.listFiles()) {
file.delete();
}
cache.delete();
super.onDestroy();
}
}
getTBaseUser是解析请求数据的方法,将请求的数据转成jsonArray,遍历array获取每一个jsonObject,从object中根据id,topic获取要用的数据,封装到实体类中
new一个新的线程去请求数据,并通过handler发送消息通知UI线程更新数据
handler.sendMessage(handler.obtainMessage(22, data));
在handler中:
listView.setAdapter(new ContactAdapter(MainActivity.this,(List)msg.obj,R.layout.mylistitem,cache));
6.下面就要写我们的填充器ContactAdapter
package com.imooc.forum;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.imooc.forum.entity.TBaseUser;
import org.w3c.dom.Text;
import java.io.File;
import java.util.List;
/**
* Created by lsk on 2017/3/10.
*/
public class ContactAdapter extends BaseAdapter {
private List data;//缓存数据
private int listviewItem;//条目id
private File cache;//缓存文件
LayoutInflater layoutInflater;
public ContactAdapter(Context context, List data, int listviewItem, File cache) {
this.data = data;
this.listviewItem = listviewItem;
this.cache = cache;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);//获取布局填充服务
}
/**
* 得到数据的总数
* @return
*/
@Override
public int getCount() {
return data.size();
}
/**
* 根据数据索引得到集合所对应的数据
* @param position
* @return
*/
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = null;
TextView textView1=null;
if (convertView == null) {
convertView = layoutInflater.inflate(listviewItem, null); // 获取条目的view对象
textView = (TextView) convertView.findViewById(R.id.ItemText);
textView1=(TextView)convertView.findViewById(R.id.ItemTitle);
convertView.setTag(new DataWrapper(textView,textView1));
} else {
DataWrapper dataWrapper = (DataWrapper) convertView.getTag();
textView = dataWrapper.textView;
textView1=dataWrapper.textView1;
}
TBaseUser user = data.get(position);
textView.setText(user.getId());
textView1.setText(user.getTopic());
//asyncImageLoad(imageView, contact.image);
return convertView;
}
/*
private void asyncImageLoad(ImageView imageView, String path) {
AsyncImageTask asyncImageTask = new AsyncImageTask(imageView);
asyncImageTask.execute(path);
}
private final class AsyncImageTask extends AsyncTask {
private ImageView imageView;
public AsyncImageTask(ImageView imageView) {
this.imageView = imageView;
}
protected Uri doInBackground(String... params) {// 子线程中执行的
try {
return ContactService.getImage(params[0], cache);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Uri result) {// 运行在主线程
if (result != null && imageView != null)
imageView.setImageURI(result);
}
}
*/
private final class DataWrapper {
public TextView textView;
public TextView textView1;
public DataWrapper(TextView textView, TextView textView1) {
this.textView = textView;
this.textView1=textView1;
}
}
}
ContactAdapter继承BaseAdapter,重写父类方法,在getView()方法中,给布局文件绑定数据
7.要在AndroidManifest.xml添加访问网络权限:
<uses-permission android:name="android.permission.INTERNET"/>
8.测试时候有可能出现的问题需要注意:
response.body().toString();会报错:
org.json.JSONException: Value com.squareup.okhttp.internal.http.RealResponseBody@536ca2e4 of type java.lang.String cannot be converted to jsonArray
应该用string()方法
当返回的字符串为“”时转jsonArray会报错,所以要做为空处理
org.json.JSONException: End of input at character 0 of
然后启动Genymotion,运行项目,效果如下:
界面是很丑的,不过我们的主要目的是通过okhttp加载远程数据并填充到ListView上,效果已经实现了,还有一些要做的,本地缓存,图片加载处理,界面mylistitem.xml布局的优化
特别感谢下面博主,学习到了很多。
博客地址:
http://blog.csdn.net/true_maitian/article/details/53234458