okhttp请求远程数据并在ListView显示

    xiaoxiao2021-03-25  127

    1.我在本地搭建的服务端,基于springmvc,hibernate和注解,写了一个简单查询方法:

    @RequestMapping(value="/topicjson.do",method=RequestMethod.GET) @ResponseBody public void topicjson(HttpSession session,HttpServletRequest request,HttpServletResponse response){ List<TBaseTopic>topiclist=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

    <?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: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

    <?xml version="1.0" encoding="utf-8"?> <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<TBaseUser>)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<TBaseUser> data =getTBaseUser(); // 通过handler来发送消息,通知主线程去更新UI handler.sendMessage(handler.obtainMessage(22, data)); } catch (Exception e) { e.printStackTrace(); } } }).start(); } //加载远程数据 private List<TBaseUser>getTBaseUser(){ String url="http://192.168.56.1/springtest/topicaction/topicjson.do";//网络请求路径 List<TBaseUser>list=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<array.length();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<TBaseUser>)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<TBaseUser> data;//缓存数据 private int listviewItem;//条目id private File cache;//缓存文件 LayoutInflater layoutInflater; public ContactAdapter(Context context, List<TBaseUser> 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<String, Integer, Uri> { 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

    转载请注明原文地址: https://ju.6miu.com/read-25826.html

    最新回复(0)