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

时间:2024-03-04 14:17:14

上一篇的文章中,我给出了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~