将访问服务器的工作交由Service承担

前面的两篇文章里面讲了移动客户端和服务器端的数据交互与显示

但是我们知道Activity是主要负责界面的,那么在activity中不应该承担太多的访问服务器的任务。也就是说,上一篇的文章所讲述的内容,虽然可行。但对于系统的架构来说,还是将责任明确划分。Activity负责界面的显示,而Service负责访问服务器。

本文将展示android端(Activity和Service)的代码,服务器端(servlet)的代码。其数据传递的过程如下:

这一切的大前提是Activity与Service绑定。如果绑定好了以后,数据的传输过程:

1. Activity将数据通过intent传递给Service。这个数据一般是一个查询条件,如(id)

2. Service提取相应的数据值,封装到json中发送request给服务器Servlet

3. Servlet通过查询条件查询结果,并将结果返回给Service

4. Service得到response后提取数据,得到的数据通过一个本地方法(call)或回调方法(callback)将结果传递给Activity

5. Activity通过调用调用Service的方法更新UI

以上就是上图所示的数据传输过程。

代码分为3段,Activity段负责【intent】和【callback】,Service段负责【Json+request+response】,Servlet段负责【query】

/****** Activity.java ******/package com.example.helloworld;

import com.example.service.MsgService;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class ServeActivity extends Activity {
    private MsgService msgService;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_main);

        textView = (TextView)findViewById(R.id.frag_text);

        //绑定Service
        Intent intent = new Intent(ServeActivity.this, MsgService.class);
        bindService(intent, conn, Context.BIND_AUTO_CREATE);

    }

    ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //返回一个MsgService对象
            msgService = ((MsgService.MsgBinder)service).getService();
            //向Service通过intent传递数据
            Intent intent = new Intent();
            intent.putExtra("book_name", 1);
            //启动Service
            msgService.onStart(intent, 0);//设置回调函数。那么在Service中,直接调用onProgress方法就可以直接执行本段代码
            msgService.setOnProgressListener(new OnProgressListener() {

                @Override
                public void onProgress(String progress) {
                    // TODO Auto-generated method stub
                    //修改UI
                    textView.setText(progress);
                }
            });
        }
    };

    @Override
    protected void onDestroy() {
        unbindService(conn);
        super.onDestroy();
    }
}

这个地方唯一需要注意的就是两段标红的函数。Activity中定义了一个回调函数onProgress,在下面的Service中,只要OnProgressListener的对象调用onProgress这个函数,就相当于是修改了Activity中的UI。这种方法很好用。不过需要先创建一个interface:

package com.example.helloworld;

public interface OnProgressListener {
    void onProgress(String progress);
}

回调函数和本篇的大部分实现方法,来自博客 Android Service与Activity之间通信的几种方式  和 一个经典例子让你彻彻底底理解java回调机制

/******  Service.java   ********/package com.example.service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;

import com.example.helloworld.OnProgressListener;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

public class MsgService extends Service {

    private int index = 2;
    private String result;
    private Handler mMainHandler, mChildHandler;
    int id;
    private OnProgressListener onProgressListener;

    public void onStart(Intent intent, int startId){
        System.out.println("================="+intent.getIntExtra("book_name", -1));
        //获取Activity传过来的数据
        id = intent.getIntExtra("book_name", -1);

        //初始化mMainHandler
        mMainHandler = new Handler(){
            public void handleMessage(Message msg){
                //detail1.setBookText((String)msg.obj);
                result = (String)msg.obj;
                if(onProgressListener != null){
                    System.out.println("==========callback function: set the textView text");
                    //调用Activity中的onProgress方法,修改UI
                    onProgressListener.onProgress((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){
            //将mChildHandler加入到消息队列中
            Message childMsg = mChildHandler.obtainMessage();
            childMsg.obj = mMainHandler.getLooper().getThread().getName();
            System.out.println("==========send message to mChild: "+childMsg.obj);
            mChildHandler.sendMessage(childMsg);
        }
    }

    //设置回调函数的接口。Activity通过这个方法获取对象
    public void setOnProgressListener(OnProgressListener onProgressListener){
        this.onProgressListener = onProgressListener;
    }

    public void onDestroy(){
        super.onDestroy();
        mChildHandler.getLooper().quit();
    }
    public String getBookDetails(int id){

        StringBuilder result = new StringBuilder();
        String urlStr = "http://192.168.1.21: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((Header) 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;
    }

    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(id);
                    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!");
        }
    }

    public class MsgBinder extends Binder{
        public MsgService getService(){

            return MsgService.this;
        }
    }

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return new MsgBinder();
    }
}
/******* Servlet.java ********/

package com.example.service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;

import com.example.helloworld.OnProgressListener;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

public class MsgService extends Service {

    private int index = 2;
    private String result;
    private Handler mMainHandler, mChildHandler;
    int id;
    private OnProgressListener onProgressListener;

    public void onStart(Intent intent, int startId){
        System.out.println("================="+intent.getIntExtra("book_name", -1));
        //获取Activity传过来的数据
        id = intent.getIntExtra("book_name", -1);

        //初始化mMainHandler
        mMainHandler = new Handler(){
            public void handleMessage(Message msg){
                //detail1.setBookText((String)msg.obj);
                result = (String)msg.obj;
                if(onProgressListener != null){
                    System.out.println("==========callback function: set the textView text");
                    //调用Activity中的onProgress方法,修改UI
                    onProgressListener.onProgress((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){
            //将mChildHandler加入到消息队列中
            Message childMsg = mChildHandler.obtainMessage();
            childMsg.obj = mMainHandler.getLooper().getThread().getName();
            System.out.println("==========send message to mChild: "+childMsg.obj);
            mChildHandler.sendMessage(childMsg);
        }
    }

    //设置回调函数的接口。Activity通过这个方法获取对象
    public void setOnProgressListener(OnProgressListener onProgressListener){
        this.onProgressListener = onProgressListener;
    }

    public void onDestroy(){
        super.onDestroy();
        mChildHandler.getLooper().quit();
    }
    public String getBookDetails(int id){

        StringBuilder result = new StringBuilder();
        String urlStr = "http://192.168.1.21: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((Header) 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;
    }

    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(id);
                    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!");
        }
    }

    public class MsgBinder extends Binder{
        public MsgService getService(){

            return MsgService.this;
        }
    }

    public int getIndex(){
        System.out.println("greg");
        return index;
    }

    public void startDonwload(){
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                index++;
                System.out.println("fd");
            }
        }).start();
    }

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return new MsgBinder();
    }
}

Bon Appetite~

时间: 2024-10-05 05:07:24

将访问服务器的工作交由Service承担的相关文章

[转载]浏览器的工作原理:新式网络浏览器幕后揭秘

原文地址 序言 这是一篇全面介绍 WebKit 和 Gecko 内部操作的入门文章,是以色列开发人员塔利·加希尔大量研究的成果.在过去的几年中,她查阅了所有公开发布的关于浏览器内部机制的数据(请参见资源),并花了很多时间来研读网络浏览器的源代码.她写道: 在 IE 占据 90% 市场份额的年代,我们除了把浏览器当成一个"黑箱",什么也做不了.但是现在,开放源代码的浏览器拥有了过半的市场份额,因此,是时候来揭开神秘的面纱,一探网络浏览器的内幕了.呃,里面只有数以百万行计的 C++ 代码.

Service一

一.Service: (一).Service 简介: 1.何谓"Service"? "Service" 意思即"服务"的意思, 像 Windows 上面的服务一样,服务是在后台上运行,承担着静悄悄的不为人所注意的工作.Service运行在后台,它是不可见的.无界面的程序. Service可以在很多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity,这个时候程序要在后台继续播放:比如检测SD卡上文件的变化:再或者在后台记录用户的地

你们都满足下面的工作考核吗

1.运行力与发展力.不存在违反公司制度以及信息安全事件,自觉參与公司以及部门的培训.服从主管工作安排. 2.工作态度,分为四个点 (1)自律性:主动积极遵循部门管理字段,遵守工作规范与流程. (2)责任心:工作须要积极主动,扎实,尽职尽责.实事求是,可以主动承担很多其它的工作.敢于承担责任,工作仔细,严谨.格守职责. (3)团队协作:主动配合主管.同事及相关部门工作,与团队成员分享信息和经验.促进团队成员合作,接受和支持团队决策.可以和团队成员保持充分的交流和沟通.并在相关问题上给予其它同事帮助

Android Api Component---翻译Service

一个service是一个在后台执行长时间的操作并且不需要提供一个用户接口的应用程序组件.另一个应用程序能够开启service并且继续运行在后台甚至如果用户切换到另一个应用程序.此外,一个组件可以绑定到service与它交互而且甚至可以执行进程间通信(IPC).例如一个service也许操作网络事务,播放音乐,执行文件I/O或者跟一个内容提供交互,所有那些都是在后台执行的. 一个service本质上可以接受两种组成: Started 当应用程序通过调用startService()的时候,一个ser

MySQL后台线程的清理工作

后台清理工作:脏页刷盘.undo回收 1.page cleaner thread:刷新脏页 2.purge thread:清空undo页.清理"deleted"page 一.innodb_page_cleaners page cleaner线程从buffer pool中刷脏页的线程数量. 1.5.7新特性 1.5.6版本以前,脏页的清理工作交由master线程的: 2.Page cleaner thread是5.6.2引入的一个新线程(单线程),从master线程中卸下buffer p

浏览器渲染引擎工作原理

浏览器内核包括渲染引擎和JS引擎,由于js引擎越来越独立,内核就倾向于只指渲染引擎 渲染引擎是一种对HTML文档进行解析并将其显示在页面上的工具.它负责取得网页的内容(HTML.XML.图象等等).整理信息(例如加入CSS等),以及计算网页的显示方式然后会输出至显示器或打印机 渲染引擎工作流程 HTML解析器解析DOMM树(解析为DOM树上个节点,同时解析CSS样式) 渲染树结构(具有一定的视觉效果,并按照一定顺序排列在屏幕上) 布局渲染树(为每个节点分配固定坐标) 绘制DOM树(渲染引擎会遍历

浏览器的工作原理(转)

简介 网络浏览器很可能是使用最广的软件.在这篇入门文章中,我将会介绍它们的幕后工作原理.我们会了解到,从您在地址栏输入google.com直到您在浏览器屏幕上看到 Google 首页的整个过程中都发生了些什么. 目录 简介 我们要讨论的浏览器 浏览器的主要功能 浏览器的高层结构 呈现引擎 呈现引擎 主流程 主流程示例 解析和 DOM 树构建 解析 - 综述 语法 解析器和词法分析器的组合 翻译 解析示例 词汇和语法的正式定义 解析器类型 自动生成解析器 HTML 解析器 HTML 语法定义 非与

android开发之service详解

service作为android的四大组件之一,其重要性可想而知,在开发中,我们经常把一些不需要与用户进行交互的工作放在service中来完成,service运行在后台,这样有些人可能会产生错觉,以为service是运行在新线程中,其实不然,service也运行在主线程中,因此不能在service中进行耗时操作,否则会报ANR异常,但是我们可以在service中新开线程来进行耗时操作,比如下载等等. 先来说说service的两种绑定方式,一种是通过Context.startService()来启

徐家骏:我在华为工作十年的感悟 (转)

徐是华为数据中心的头,技术超级牛人,一级部门总监,华为副总裁,年收入过千万,数据中心是用火山岩建的深入地下的一个大型建筑.防辐射,可防卫星的电子,雷达等手段的侦察.里面有象卫星发射中心那种超大屏幕,机房里满是三米的大型服务器和大型计算机.连接整个华为全球的每一台终端,整个华为每天三十多万封邮件,海外和全球的同步研发,内部的信息管理,内部流程,华为的国内国际IP电话都是通过出去. 上周,我正式提交了离职报告,准备给自己的职业生涯一个很大的转折,这是我长时间的思考最后所做的决定.但真的提出离职后,回