編輯:關於Android編程
本系列文章提供簡單Android應用開發實例方法,文章步驟如下所示:
1 獲取應用所需的數據源
數據源一般來源於互聯網、個人搜集或者其他方式
2 應用UI設計
每個應用軟件都需要有一個簡單的UI設計草圖,便於開發者更好的實現編碼
3 應用實現
實現完整的Android應用
特此說明:本系列文章的數據源均采用互聯網方式獲取,僅作為示例演示
提供各個高校歷屆的分數線錄取查詢功能,作為高考學子填寫志願的參考應用。最終效果圖:

1 從Assets中獲取到學校信息,學校存儲格式為:
1#10001#北京大學
1#10002#中國人民大學
1#10003#清華大學
1#10004#北京交通大學
其中1代表省份ID,10001代表學校ID,最後的為學校名稱
我們新建FileUtils類,提供獲取Assets下文件的方法:
public static List以上方法將文件中的數據按行加載到列表中,由於在保存數據源時保存為ASCII格式,所以此處采用gbk加載。loadFileContentForList(String filePath, Context ctx) throws IOException { InputStream is = ctx.getAssets().open(filePath); BufferedReader br = new BufferedReader(new InputStreamReader(is, gbk)); ArrayList results = new ArrayList (); String readLine = null; while((readLine = br.readLine()) != null) { results.add(readLine); } return results; }
2 從網絡中獲取高校查詢結果
采用Android自帶的HttpClient進行實現,我們首先封裝一個簡單的HttpUtils處理類,提供httpGet請求方法:
/**
* 獲取指定URL請求的結果信息,以字符串方式返回請求內容
* @param url 請求地址
* @param param 請求所需參數
* @return
*/
public static String httpGet(String url, HashMap param) {
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
HttpClient mHttpClient = new DefaultHttpClient(httpParams);
String mUrl = url;
if(param != null && param.size() > 0) {
StringBuilder sb = new StringBuilder();
sb.append(url);
sb.append(?);
for(Entry m : param.entrySet()) {
sb.append(m.getKey());
sb.append(=);
sb.append(m.getValue());
sb.append(&);
}
mUrl = sb.substring(0, sb.length()-1);
}
HttpGet httpRequest = new HttpGet(mUrl);
try {
HttpResponse httpResponse = mHttpClient.execute(httpRequest);
if (httpResponse.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
String str = EntityUtils.toString(httpResponse.getEntity());
return str;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpRequest.abort();
}
return null;
}
3 為了便於控件渲染數據,我們將所有數據均轉為SimpleAdapter可識別的格式ArrayList
通過MUtils類提供各個數據的轉化:
loadSchool方法用於提供所有學校信息數據轉化,其中Map的key表示省份ID,value為學校列表
@SuppressLint(UseSparseArrays) public static HashMaploadResult方法用於將網絡獲取的查詢結果信息進行轉化,主要將返回的JSON格式進行處理>> loadSchool(Context ctx) { HashMap >> result = new HashMap >>(); try { List contents = FileUtils.loadFileContentForList(m/data, ctx); for(int i = 0, len = contents.size(); i < len; i++) { String[] item = contents.get(i).split(#); HashMap data = new HashMap (); data.put(id, item[1]); data.put(name, item[2]); ArrayList > itemList = result.get(Integer.parseInt(item[0])); if(itemList == null) { itemList = new ArrayList >(); result.put(Integer.parseInt(item[0]), itemList); } itemList.add(data); } } catch (IOException e) { e.printStackTrace(); } return result; }
public static ArrayList其中BASE_URL = http://kaoshi.edu.sina.com.cn/iframe/i_collegescore.php, batchMap從原有數據網站中獲取並初始化數據> loadResult(final String schoolId, final int type, final int prov2) throws Exception{ //從網絡獲取查詢結果,返回格式為JSON String netStr = HttpUtils.httpGet(BASE_URL, new HashMap (){{ put(_action, collegescore); put(num, 0); put(provid, prov2); put(wl, type); put(collegeid, schoolId); }}); if(netStr == null) { //異常直接返回null return null; } JSONArray resultArray = new JSONArray(netStr); ArrayList > result = new ArrayList >(); for(int i = 0, len = resultArray.length(); i < len; i++) { //依次處理每一條數據信息 JSONObject jobj = resultArray.getJSONObject(i); HashMap d = new HashMap (); int tempInt; d.put(year, jobj.getString(syear)); tempInt = jobj.optInt(plan, -1); d.put(plan, (tempInt <= 0 ? -- : + tempInt)); tempInt = jobj.optInt(score_min, -1); d.put(score_min, tempInt <= 0 ? -- : + tempInt); tempInt = jobj.optInt(score_avg, -1); d.put(score_avg, (tempInt <= 0 ? -- : + tempInt)); tempInt = jobj.optInt(score_td, -1); d.put(score_td, (tempInt <= 0 ? -- : + tempInt)); tempInt = jobj.optInt(score_max, -1); d.put(score_max, (tempInt <= 0 ? -- : + tempInt)); d.put(batch, batchMap.get(jobj.getString(batch))); d.put(batch_diff, jobj.getString(batch_diff)); result.add(d); } return result; } public static final HashMap batchMap = new HashMap (){{ put(00, 不詳); put(01, 本科提前批); put(11, 本科一批); put(12, 本科二批); put(13, 本科三批); put(123, 本科二、三批); put(21, 專科); }};
Activity中所有變量定義如下所示:
//依次為省份選擇ID,用戶所在地ID,學校序號,文理科類型
int prov1, prov2, school, type;
ArrayList> resultData; //查詢錄取結果
HashMap>> datas; //保存省份下的學校信息
//依次為省份選擇彈窗、學校選擇彈窗和文理科選擇彈窗
PopupWindow provWindow, schoolWindow, typeWindow;
TextView prov1Sel, schoolSel, typeSel, prov2Sel, tipView, resultTitleView;
ListView provList, schoolList, resultList;
LinearLayout resultLayout;
Button queryButton;
//依次為省份信息和文理科信息(從strings.xml中獲取)
String[] provs, types;
/**
* 顯示省份彈窗。type=0表示學校省份彈窗,=1表示用戶所在地省份彈窗
* @param type
*/
public void showProvWindow(final int type) {
if (provWindow == null) {
View v = LayoutInflater.from(this).inflate(R.layout.pop_list, null);
provList = (ListView) v.findViewById(R.id.pop_list);
provList.setAdapter(new ArrayAdapter(this,
R.layout.pop_list_item, R.id.pop_list_item_name, provs));
provWindow = new PopupWindow(v, Utils.screenWidth,
Utils.screenHeight / 2, true);
}
provList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView av, View arg1, int position,
long arg3) {
//ID為選擇序號+1
if (type == 0) {
prov1 = position + 1;
prov1Sel.setText(provs[position]);
} else {
prov2 = position + 1;
prov2Sel.setText(provs[position]);
}
if (provWindow != null) {
provWindow.dismiss();
}
}
});
if (type == 0 && prov1 > 0) {
provList.setSelection(prov1 - 1);
} else if (type == 1 && prov2 > 0) {
provList.setSelection(prov2 - 1);
} else {
provList.setSelection(0);
}
provWindow.showAsDropDown(type == 0 ? prov1Sel : prov2Sel, 0, 0);
provWindow.update();
}
文理科類型彈窗實現如下所示:
public void showTypeWindow() {
if (typeWindow == null) {
View v = LayoutInflater.from(this).inflate(R.layout.pop_list, null);
ListView tList = (ListView) v.findViewById(R.id.pop_list);
tList.setAdapter(new ArrayAdapter(this, R.layout.pop_list_item,
R.id.pop_list_item_name, types));
typeWindow = new PopupWindow(v, Utils.screenWidth / 2,
Utils.screenHeight / 2, true);
tList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView av, View arg1,
int position, long arg3) {
type = position;
typeSel.setText(types[position]);
if (typeWindow != null) {
typeWindow.dismiss();
}
}
});
}
typeWindow.showAsDropDown(typeSel, 0, 0);
typeWindow.update();
}
學校下拉彈窗實現如下所示:
public void showSchoolWindow() {
if (prov1 <= 0) {
Toast.makeText(this, 請先選擇省份!, Toast.LENGTH_SHORT).show();
return;
}
if (schoolWindow == null) {
View v = LayoutInflater.from(this).inflate(R.layout.pop_list, null);
schoolList = (ListView) v.findViewById(R.id.pop_list);
schoolList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView av, View arg1,
int position, long arg3) {
school = position;
schoolSel.setText((String) datas.get(prov1).get(school)
.get(name));
if (schoolWindow != null) {
schoolWindow.dismiss();
}
}
});
schoolWindow = new PopupWindow(v, Utils.screenWidth,
Utils.screenHeight / 2, true);
}
//每次點擊都需要更新數據,防止省份改變
schoolList.setAdapter(new SimpleAdapter(this, datas.get(prov1),
R.layout.pop_list_item, new String[] { name },
new int[] { R.id.pop_list_item_name }));
schoolList.setSelection(school);
schoolWindow.showAsDropDown(schoolSel, 0, 0);
schoolWindow.update();
}
因為Http請求不能在主線程實現,我們通過新開線程,通過Handler實現UI刷新,請求查詢並渲染結果如下所示:
@Override
public void run() {
try {
resultData = MUtils.loadResult((String) datas.get(prov1).get(school)
.get(id), type + 1, prov2);
} catch (Exception e) {
resultData = null;
}
handler.sendEmptyMessage(0);
}
public void search() {
if (!Utils.canAccessNetwork(this)) {
tipView.setText(無法連接到網絡!);
changeView(false);
return;
}
if (prov1 <= 0) {
tipView.setText(請選擇學校!);
changeView(false);
return;
}
if (prov2 <= 0) {
tipView.setText(請選擇您的所在地!);
changeView(false);
return;
}
tipView.setText(正在努力為您加載中...);
changeView(false);
new Thread(this).start();
}
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (resultData == null) {
tipView.setText(獲取結果失敗,請稍後再試!);
changeView(false);
} else {
StringBuilder sb = new StringBuilder();
sb.append(
); sb.append(); sb.append(datas.get(prov1).get(school).get(name)); sb.append(); sb.append(在); sb.append(); sb.append(provs[prov2 - 1]); sb.append(); sb.append(的); sb.append(types[type]); sb.append(錄取線); sb.append(); resultTitleView.setText(Html.fromHtml(sb.toString())); resultList .setAdapter(new SimpleAdapter(MainActivity.this, resultData, R.layout.result_item, new String[] { year, score_max, score_avg, score_td, plan, batch, batch_diff }, new int[] { R.id.result_item_year, R.id.result_item_max, R.id.result_item_avg, R.id.result_item_real, R.id.result_item_persons, R.id.result_item_pici, R.id.result_item_xiancha })); changeView(true); } }; }; public void changeView(boolean flag) { if (flag) { resultLayout.setVisibility(View.VISIBLE); tipView.setVisibility(View.GONE); } else { resultLayout.setVisibility(View.GONE); tipView.setVisibility(View.VISIBLE); } }
package com.gklq.zl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import com.my.lib.Utils;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener, Runnable {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Utils.screenHeight <= 0) {
Utils.initSize(this);
}
if (datas == null) {
datas = MUtils.loadSchool(this);
}
setContentView(R.layout.activity_main);
prov1Sel = (TextView) findViewById(R.id.prov1_sel);
prov1Sel.setOnClickListener(this);
schoolSel = (TextView) findViewById(R.id.school_sel);
schoolSel.setOnClickListener(this);
typeSel = (TextView) findViewById(R.id.type_sel);
typeSel.setOnClickListener(this);
prov2Sel = (TextView) findViewById(R.id.prov2_sel);
prov2Sel.setOnClickListener(this);
queryButton = (Button) findViewById(R.id.query_btn);
queryButton.setOnClickListener(this);
tipView = (TextView) findViewById(R.id.text_tip);
resultLayout = (LinearLayout) findViewById(R.id.layout_result);
resultTitleView = (TextView) findViewById(R.id.text_result);
resultList = (ListView) findViewById(R.id.list_result);
provs = getResources().getStringArray(R.array.province);
types = getResources().getStringArray(R.array.type);
}
public void onClick(android.view.View v) {
switch (v.getId()) {
case R.id.prov1_sel:
showProvWindow(0);
break;
case R.id.prov2_sel:
showProvWindow(1);
break;
case R.id.type_sel:
showTypeWindow();
break;
case R.id.school_sel:
showSchoolWindow();
break;
case R.id.query_btn:
search();
break;
default:
break;
}
}
@Override
public void run() {
try {
resultData = MUtils.loadResult((String) datas.get(prov1).get(school)
.get(id), type + 1, prov2);
} catch (Exception e) {
resultData = null;
}
handler.sendEmptyMessage(0);
}
public void search() {
if (!Utils.canAccessNetwork(this)) {
tipView.setText(無法連接到網絡!);
changeView(false);
return;
}
if (prov1 <= 0) {
tipView.setText(請選擇學校!);
changeView(false);
return;
}
if (prov2 <= 0) {
tipView.setText(請選擇您的所在地!);
changeView(false);
return;
}
tipView.setText(正在努力為您加載中...);
changeView(false);
new Thread(this).start();
}
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (resultData == null) {
tipView.setText(獲取結果失敗,請稍後再試!);
changeView(false);
} else {
StringBuilder sb = new StringBuilder();
sb.append(
Android搶紅包助手開發全攻略
背景:新年之際,微信微博支付寶紅包是到處飛,但是,自己的手速總是比別人慢一點最後導致紅包沒搶到,紅包助手就應運而生。需求:收到紅包的時候進行提醒,然後跳轉到紅包的界面方便
Android學習筆記45之gson解析json
JSON即JavaScript Object Natation, 是一種輕量級的數據交換格式,采用完全獨立於語言的文本格式,為Web應用開發提供了一種理想的數據交換格式。
淺談Android官方MVP架構解讀
綜述對於MVP (Model View Presenter)架構是從著名的MVC(Model View Controller)架構演變而來的。而對於Android應用的開
詳解Android更改APP語言模式的實現過程
一、效果圖二、描述更改Android項目中的語言,這個作用於只用於此APP,不會作用於整個系統三、解決方案(一)布局文件<LinearLayout xmlns:an