前面的两篇文章里面讲了移动客户端和服务器端的数据交互与显示
但是我们知道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~