在完成了用户注册和登录页面的界面设计工作之后,我们就需要让我们的程序向后台发起请求,请求后台PHP程序实际进行用户注册操作。在新版本的Android系统中,所有的网络请求必须以异步的方式来进行,我们既可以通过线程方式也可以通过Android系统为我们提供的异步任务方式来完成,我们在这里选择采用异步任务的方式来进行网络操作。
根据异步任务的原理,当应用调用异步任务时,异步任务会在后台完成相应的网络操作,在完成之后,在onPostExecute方法中通知界面,更新操作状态。有两种方法可以完成这项任务,一种是将Activity对象放到异步任务类中,当需要更新界面时,直接调用该Activity对象的方法即可,另一种方式是传入Activity对象的Handler对象,当异步任务完成网络操作时,向Handler对象发送消息,由Handler对象来更新界面。从上面的分析可以看出,第一种方法使Activity和异步任务之间产生了紧耦合,是软件开发中不太提倡的,因此我们采用第二种方式,即采用Handler对象,异步任务通过发送消息通知Activity更新界面状态。
我们首先在JysRegisterLoginActivity类中,定义与异步任务交互的Handler:
static protected class JysRegisterLoginHandler extends WkyRegisterLoginHandler { public JysRegisterLoginHandler(JysRegisterLoginActivity activity) { this.activity = activity; } public void handleMessage(Message msg) { super.handleMessage(msg); // 自己额外的处理 switch (msg.what) { case WkyConstants.MSG_REGISTER_USER: activity.processRegisterUserResult(msg); break; } } private JysRegisterLoginActivity activity = null; }
需要注意的是,我们将JysRegisterLoginHandler声明为静态的内部类,因为如果只声明为内部类,有出现内存泄露的可能性。
在Activity的onCreate函数中,初始化这个Hanlder对象。
handler = new JysRegisterLoginHandler(this);
我们在用户点击注册按钮时,调用异步任务发起网络请求,请求PHP程序完成用户注册功能。
/** * 点击注册/登录按钮 * 【闫涛 2015.09.16】初始版本 */ protected void setRegisterOrLoginImgvOnClickListener() { registerOrLoginImgv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e("wky", "register or login to the system..."); if (wkyRegisterLoginModel.getState() == WkyRegisterLoginModel.STATE_REGISTER) { registerUser(); } else if (wkyRegisterLoginModel.getState() == WkyRegisterLoginModel.STATE_LOGIN) { Log.e("wky", "login the user"); } } }); } protected void registerUser() { Log.e("wky", "Regisger the user"); if (null == registerTask) { registerTask = new WkyRegisterAsyncTask(this, handler); String urlStr = WkyConstants.CMD_REGISTER_USER; Log.e("wky", "url=" + urlStr + "!"); String body = prepareRegisterReqBody(); registerTask.execute(urlStr, body); } }
异步任务需要两个参数,一个是请求URL,另一个是Json格式的请求数据。
在这里顺便提一下编程规范的问题,大家看请求的URL是定义在WkyConstants里的一个常量,而不是直接写字符串,这样便于日后的代码维护。我们在代码中要尽量避免在代码中直接写数字和字符串,因为我们在维护时可能会忘记数字的含义,字符串容易在不同的地方写得不一致,造成比较难于调试的BUG。
下面是具体的异步任务类:
/** * 异步任务开始前的回调函数 * 【闫涛 2015.09.24】初始版本 */ @Override protected void onPreExecute() { Log.e("wky", "WkyRegisterAsyncTask.onPreExecute 1"); } /** * 具体异步任务执行函数 * 【闫涛 2015.09.24】初始版本 */ @Override protected String doInBackground(String... params) { String urlStr = params[0]; String body = params[1]; return WkyHttpClient.doPost(urlStr, body); } /** * 更新异步任务状态信息(在显示进度条时会用到) * 【闫涛 2015.09.24】初始版本 */ @Override protected void onProgressUpdate(Integer... progress) { } /** * 异步任务结束时要调用的方法,通知页面进行更新 * 【闫涛 2015.09.24】初始版本 */ @Override protected void onPostExecute(String result) { Log.e("wky", "new:" + result); Message msg = handler.obtainMessage(); msg.what = WkyConstants.MSG_REGISTER_USER; Bundle params = new Bundle(); params.putString(WkyConstants.MSG_DATA_NAME, result); msg.setData(params); handler.dispatchMessage(msg); }
从上面的代码中可以看出,在doInBackground中调用网络POST请求方法,发送POST请求。这里重点是在onPostExecute方法中,生成一个Message对象,将POST响应字符串,添加到Message对象中,然后向Handler对象发送消息。在前面Handler类的代码中,接收到这个消息,就会调用相相应的方法来处理响应结果了。代码如下所示:
public void processRegisterUserResult(Message msg) { String jsonStr = msg.getData().getString(WkyConstants.MSG_DATA_NAME); JSONObject json = null; String status = null; long userId = 0; try { json = new JSONObject(jsonStr); status = json.getString("status"); userId = json.getLong("userId"); Log.e("wky", "^_^ registerUser:" + status + "; u=" + userId + "!"); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
在这里我们什么也没做,只是把响应结果变为json对象,从中取出status和userId等项目,在实际的代码中,我们需要记录下用户的信息,然后转到应用首页中去。
下面是具体发起网络请求的类:
/** * 普通POST请求,窗体形式,没有文件上传操作 * @param urlStr * @param data 以JSON格式存在 * @return 响应字符串 * 【闫涛 2015.09.23】初始版本 */ public static String doPost(String urlStr, String data) { HttpURLConnection conn = null; OutputStreamWriter outStream = null; StringBuilder result = new StringBuilder(); try { URL url = new URL(urlStr); conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setDoInput(true); conn.setRequestProperty("charset", "utf-8"); conn.setRequestMethod(POST); conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); conn.setConnectTimeout(TIMEOUT); conn.setReadTimeout(TIMEOUT); conn.connect(); outStream = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); if (data != null) { outStream.write(data); } outStream.flush(); outStream.close(); // } if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { result.append(readAsString(conn.getInputStream(), "UTF-8")); }else{ Log.e("wky","ResponseCode:" + conn.getResponseCode()); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result.toString(); }
由于我们的网络请求处理比较简单,因此直接采用了Java的方法来进行网络请求。
华丽的分隔线
******************************************************************************************************************************************************************************
希望大家多支持,有大家的支持,我才能走得更远,谢谢!
银行账号:622202 0200 1078 56128 闫涛
我的支付宝:[email protected]