Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 最老程序員創業開發實訓13---Android---網絡請求與異步任務

最老程序員創業開發實訓13---Android---網絡請求與異步任務

編輯:關於Android編程

在完成了用戶注冊和登錄頁面的界面設計工作之後,我們就需要讓我們的程序向後台發起請求,請求後台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]



 

 

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved