Servlet回传的数据显示在界面上

上一篇的文章中,我给出了android和servlet之间数据的传递。实现了:android端数据打包--》发送给servlet端解析--》返回给android端

但还有一个很重要的内容,我以为很简单可以实现。结果纠结了两天才实现。即上述步骤的最后一步,就是【返回的数据显示到android上】

这个过程其实挺简单的,修改上一篇博文中2.1中的代码如下就可以了

public String sendJson(){
        StringBuilder result = new StringBuilder();
        String urlStr = "http://192.168.1.24:8080/servletTest/test";
        HttpPost post = new HttpPost(urlStr);

        try{
            JSONObject json = new JSONObject();
            json.put("book_id", id);
            System.out.println("=============="+json.toString());

            StringEntity se = new StringEntity(json.toString());
            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
            post.setEntity(se);

            HttpClient httpClient = getHttpClient();
            HttpResponse httpResponse = httpClient.execute(post);
            /////////////////////////////
            int httpCode = httpResponse.getStatusLine().getStatusCode();
            if(httpCode==HttpURLConnection.HTTP_OK && httpResponse != null){
                HttpEntity entity = httpResponse.getEntity();
                InputStream inputStream = entity.getContent();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                BufferedReader reader = new BufferedReader(inputStreamReader);
                String s;
                while((s=reader.readLine()) != null){
                    result.append(s);
                }
                reader.close();

                JSONObject object =  new JSONObject(result.toString());
                String str = object.getString("book_list");
                //detail1.setBookText(str);
                return str;
            }
            ////////////////////////////
        }catch(Exception exception){
            exception.printStackTrace();
        }
        return null;
    }

红色区域内的内容是新添加的,将返回的httpResponse中的内容提取出来,并返回一个str字符串。

到目前为止,都没有什么问题。但是当我们试图将返回的str字符串用于更新UI内容的时候,android报错,说UI内容的修改只能在创建UI的线程中才能修改,也就是说只能在主线程中修改;而不能在子线程中修改。

这个时候就出现了一个矛盾体。访问服务器的操作必须要在子线程中,因为它是一个耗时操作,会降低UI线程的性能;而UI的更新操作必须在UI线程中,子线程不允许修改UI。这个时候,我们需要的就是——线程间的通讯。

是的,当子线程获取了servlet返回的数据后,将数据通过线程间通讯的方式发送给主线程。主线程收到这个消息后,再更新UI。就是这样一个过程。

这个时候就不再涉及到servlet端的代码了,因为servlet已经把数据都返回回来。所以下面我只给出android端的代码。

/****  android code  ****/

package com.example.douban250;

@SuppressLint("HandlerLeak") public class BookDetailsActivity extends ActionBarActivity{
    private BookDetail detail1;
    private ImageButton backButton;
    private String responseMsg = "";
    int id;
    private Handler mMainHandler, mChildHandler;

    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.book_detail_main);

        detail1 = (BookDetail)this.findViewById(R.id.book_detail);

        Intent intent = getIntent();
        id = intent.getIntExtra("id", -1);
        mMainHandler = new Handler(){
            public void handleMessage(Message msg){
                //接收子线程的消息
                detail1.setBookText((String)msg.obj);
                System.out.println("==========main thread get the message:"+msg.obj);
                System.out.println("Finally, the message is :"+msg.obj);

            }
        };
        QueryThread thread = new QueryThread();
        thread.start();

        while(mChildHandler == null){

        }
        if(mChildHandler != null){
            //发送消息给子线程
            Message childMsg = mChildHandler.obtainMessage();
            childMsg.obj = mMainHandler.getLooper().getThread().getName();
            System.out.println("==========send message to mChild: "+childMsg.obj);
            mChildHandler.sendMessage(childMsg);
        }

    }

    public void onDestroy(){
        super.onDestroy();
        mChildHandler.getLooper().quit();
    }

    public String getBookDetails(){

        //与servlet交互的实现代码
        StringBuilder result = new StringBuilder();
        String urlStr = "http://192.168.1.21:8080/servletTest/test";
        HttpPost post = new HttpPost(urlStr);

        try{
            //发送request
            JSONObject json = new JSONObject();
            json.put("book_id", id);
            System.out.println("=============="+json.toString());

            StringEntity se = new StringEntity(json.toString());
            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
            post.setEntity(se);

            HttpClient httpClient = getHttpClient();
            HttpResponse httpResponse = httpClient.execute(post);
            //接收到response并处理
            int httpCode = httpResponse.getStatusLine().getStatusCode();
            if(httpCode==HttpURLConnection.HTTP_OK && httpResponse != null){
                HttpEntity entity = httpResponse.getEntity();
                InputStream inputStream = entity.getContent();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                BufferedReader reader = new BufferedReader(inputStreamReader);
                String s;
                while((s=reader.readLine()) != null){
                    result.append(s);
                }
                reader.close();

                JSONObject object =  new JSONObject(result.toString());
                String str = object.getString("book_list");
                //detail1.setBookText(str);
                //得到最终返回的结果
                return str;
            }

        }catch(Exception exception){
            exception.printStackTrace();
        }
        return null;
    }

    public HttpClient getHttpClient(){
        BasicHttpParams httpParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(httpParams, 5*1000);
        HttpConnectionParams.setSoTimeout(httpParams, 10*1000);
        HttpClient client = new DefaultHttpClient(httpParams);
        return client;
    }

    class QueryThread extends Thread{
        public void run(){

            //初始化消息循环队列,需要在Handler创建之前
            Looper.prepare();
            mChildHandler = new Handler(){
                public void handleMessage(Message msg){
                    //访问网络等工作
                    String book_titleString = getBookDetails();
                    System.out.println("================book_title from servlet is "+book_titleString);
                    Message toMain = mMainHandler.obtainMessage();
                    toMain.obj = book_titleString;
                    //向主线程当前线程的Looper对发送message
                    System.out.println("================send message to main thread: "+book_titleString);
                    mMainHandler.sendMessage(toMain);
                }
            };
            //启动子线程消息循环队列
            Looper.loop();
            System.out.println("================json is done!");
        }
    }
}

过程就是这样的,onCreate方法中的以下这段代码,我也不是太懂是什么意思。但是我理解的就是讲mChildHandler注册到消息队列中去。这样的话mMainHandler就知道有这么一个消息了。

if(mChildHandler != null){
            //发送消息给子线程
            Message childMsg = mChildHandler.obtainMessage();
            childMsg.obj = mMainHandler.getLooper().getThread().getName();
            System.out.println("==========send message to mChild: "+childMsg.obj);
            mChildHandler.sendMessage(childMsg);
        }

然后QueryThread中的下面这段代码就是,就是将网络访问中的返回值——book_titleString当做消息的内容,传递给mMainHandler。

mChildHandler = new Handler(){
                public void handleMessage(Message msg){
                    //访问网络等工作
                    String book_titleString = getBookDetails();
                    System.out.println("================book_title from servlet is "+book_titleString);
                    Message toMain = mMainHandler.obtainMessage();
                    toMain.obj = book_titleString;
                    //向主线程当前线程的Looper对发送message
                    System.out.println("================send message to main thread: "+book_titleString);
                    mMainHandler.sendMessage(toMain);
                }
            };

最后mMainHandler作为主线程,接收到这个消息,并将其中的信息提取出来,更新UI。下面标红的代码就是我封装的一个修改UI的代码。跟textView.setText((String)msg.obj)是一个意思。

mMainHandler = new Handler(){
            public void handleMessage(Message msg){
                //接收子线程的消息
                detail1.setBookText((String)msg.obj);
                System.out.println("==========main thread get the message:"+msg.obj);
                System.out.println("Finally, the message is :"+msg.obj);

            }
        };

Bon Appetite~

时间: 2024-10-14 20:43:38

Servlet回传的数据显示在界面上的相关文章

C++ 从数据库读取数据,将数据显示在界面上的TreeCtrl上

oracle数据库读取数据如下所示: 代码如下: //构造节点 struct AREA { long id; long parent_area_id; string area_name; std::vector<AREA> children; } //从AREA表中根据id读一个结构体Area的数据 void Id2FindAreaTree(Session ses, AREA& Area, int id) { Statement select(ses); select <<

无界面上(linux)生成测试报告(3)

无界面上(linux)生成测试报告 1.待jmx文件运行完成后,键入命令进入到jtl文件下: #cd testresult#bin目录下使用此命令,进入到jtl文件下 #jmeter -g pushGeomquota.jtl -e -o report#生成测试报告 #zip -q -r report.zip report/ #压缩文件夹中的内容 #sz report.zip#然后导出至windows本地即可 2.解压report.zip文件,浏览器打开html文件即可,如下图所示 原文地址:ht

无界面上(linux)运行jmeter(2)

无界面上(linux)运行jmeter 1.先在bin目录下面创建一个文件夹testplan用来存放脚本(.jmx文件),然后在创建一个文件夹testresult用来存放脚本执行后的结果(.jtl文件),结果文件是可以在jmeter可视化界面打开的,它保存了脚本执行过程中的各种结果非常全面,结果树.聚合报告.表格查看结果等都可以将它打开看到相应数据 命令如下: #mkdir testplan#在bin目录下面创建testplan文件夹 #cd ../#回到bin目录 #mkdir testres

Android+PHP+MYSQL把数据库中的数据显示在Android界面上

俗话说,好记性不如烂笔头.今天终于体会其中的道理了.昨天写好的代码不知道为何找不到了.所以今天我一定得抽出一点时间把我的代码保存起来,以防我的代码再没有了. 还是先上图片. 这个界面是用ListView实现的,数据是数据库里面的数据,服务器为thinkPHP.我就不废话那么多,直接把我的代码拷贝上了. 总的思想就是,利用账号查询数据库中的信息,然后对返回的信息进行解析.这里我把账号保存到了本地. Data.java package cn.edu.aynu.rjxy.entity; public

AngularJS取得后台Jason数据显示在页面上

代码下载:https://files.cnblogs.com/files/xiandedanteng/angularjsAjax.rar 前台代码: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.get

10_Android中通过HttpUrlConnection访问网络,Handler和多线程使用,读取网络html代码并显示在界面上,ScrollView组件的使用

?? 编写如下项目: 2 编写Android清单文件 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima28.htmldemo" android:versionCode="1" andr

iOS7_关于UISwitch_01_如何添加一个UISwitch到界面上

1.首先我们先创建一个 SingleView application. 2.我们可以用Inface Builder 来实现,也可以通过手码来实现.我们这次先通过手码来实现: 首先,我们在 xxxViewController.m文件中,为self添加一个UISwitch类型的成员变量,我们叫TA mainSwitch: 第一种方式,我们可以: @interface moboViewController (){ UISwitch *_mainSwitch; //成员变量 } 第二步,我们通过 all

Unity5中Inspector界面上的AssetBundle值设定问题

注: 编辑器扩展方面  Unity5  AssetBundle Unity5对AssetBundle做了很大的调整,与旧版很大不同,例如,如果一个资源已经打包,如果该资源没有任何更新,那么该资源将不会被打包.打包的同时会生成该文件同名的"*.manifest"文件,该文件中记录了打包后的bundle文件的相关信息. 此外,在Inspector面板中还多出了AssetBundle的名称和文件扩展名的的选项,如图: 最近有个需求需要通过以编辑器扩展方式实现同时设置多个资源文件的AssetB

判断View是否显示在界面上

我们都知道ViewController有viewWillAppear和viewDidAppear等关于页面生命周期的方法,用来对视图做一些管理,比如页面出现时怎么样,页面消失时怎么样.. 但是对于View,有没有类似的方法可以判断是否view出现了,view消失或者被遮挡了呢? 先介绍一下场景吧,朋友的一个项目,有个界面是直接做了个View,然后add到某个ViewController上去了(层级比较深,不方便在ViewController里操作这个view).后来需求变动,需要这个View中做