Android天氣預報應用設計(二)

來源:互聯網
上載者:User
 Android天氣預報應用設計(二)三.詳細設計

本文在天氣預報應用基礎功能上參考了http://www.anddev.org/android_weather_forecast_-_google_weather_api_-_description-t337.html一文,該文提供了整體設計思路及完整的原始碼,此處只針對額外的功能及不同的設計方法進行闡述。此外,在進行源碼分析時,只挑選示意性、結構性的代碼進行分析,而程式完整的原始碼可在http://download.csdn.net/detail/frankxuanhui/3593051進行下載。

(1)查詢天氣資訊的多執行緒

由於查詢天氣資訊涉及到網路資源的訪問,在網路連接狀況不佳的情況下可能非常耗時,而在訪問網路的同時,應用主介面是處於阻塞狀態的,也即在這段時間內使用者無法與應用進行互動,導致“假死”狀態,這顯然是非常不好的使用者體驗。針對這類問題,我們可以建立另一個線程,並在新線程中進行天氣預報查詢操作:

queryButton.setOnClickListener(new OnClickListener(){    public void onClick(View arg0){        new Thread(new Runnable(){            public void run(){                queryWeather();        }).start();    }}

這裡對queryButton按鍵進行監聽,當按下該按鍵時,將啟動一個新線程,並在新線程中調用訪問天氣資訊的方法queryWeather()。

在這裡必須注意一個問題,Android採用的是單線程UI,即UI介面的重新整理只能在主線程中進行。也就是說,當我們在queryWeather()方法中查詢到天氣資訊後,直觀的想法是在該線程中直接進行介面的重新整理,但遺憾的是這種做法在Android中是無效的。我們不能在新建立的線程中對主線程的UI進行重新整理,解決方案是利用Handler類:

private class RefreshUIHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {             case 1:                                    refreshUI();                               case 2:                                    updateUI();                               default:break;}}}

上述方法通過繼承Handler類建立了自訂的重新整理介面的RefreshUIHandler,並實現了介面方法handleMessage方法。在該方法中通過分析收到的資訊,進行UI更新操作。我們需要在主線程中建立RefreshUIHandler的執行個體:

RefreshUIHandler mainHandler = new RefreshUIHandler();

然後在新線程中需要更新介面的地方作如下調用:

Message msg = mainHandler.obtainMessage(1);mainHandler.sendMessage(msg);

上述代碼建立了一個Message對象,並將其發送至mainHandler進行處理,注意到obtainMessage方法中的參數對應了Handler類中handleMessage方法的參數msg.what。通過這樣的方法就可以實現在新線程中進行UI介面重新整理,從而實現了天氣預報查詢的多執行緒。(Android中還可以利用更輕量級的AsyncTask實現該功能,本文對此未作研究,希望能和做過類似功能的朋友交流)

(2)自訂快顯功能表功能

在Android真機上按MENU鍵可彈出應用菜單(模擬器對應的是PC鍵盤的F12鍵),該功能是通過方法onCreateOptionsMenu實現的。建立菜單有兩種方法:直接通過Menu.add方法添加,或利用MenuInflater解析menu的xml文檔,本文採用了第二種方法:

public boolean onCreateOptionsMenu(Menu menu) {MenuInflater inflater = getMenuInflater();inflater.inflate(R.menu.operation_menu, menu);// 通過MenuInflater來建立定義在R.menu.operation_menu.xml中的菜單return true;}

當然,首先要在工程的res目錄下建立名為menu的檔案夾,並建立operation_menu.xml文檔:

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@+id/send_message" android:icon="@drawable/send_message"android:title="@string/menu_send_message"></item><item android:id="@+id/change_skin" android:icon="@drawable/change_skin"android:title="@string/menu_change_skin"></item><item android:id="@+id/description" android:icon="@drawable/app_description"android:title="@string/menu_description"></item><item android:id="@+id/exit" android:icon="@drawable/exit"android:title="@string/menu_exit"></item></menu>

最後在onMenuItemSelected方法中實現相應的事件處理函數即可:

public boolean onMenuItemSelected(int featureId, MenuItem item) {switch (item.getItemId()) {case R.id.send_message:                            function1();return true;case R.id.change_skin:                            function2();                            return true;case R.id.exit:                            function3();                            return true;case R.id.description:                            function4();                            return true;default:return false;}}

(3)傳送簡訊功能

當我們查詢到天氣預報資訊後,有時希望能夠直接將內容形成一條簡訊發送給親朋好友,這樣的功能在Android中是很容易實現的。該功能分兩個步驟:(1)擷取系統內的連絡人資訊(2)傳送簡訊至指定連絡人。首先是擷取系統內的連絡人資訊:

private Map<String, String> getSystemContacts() {Map<String, String> contactsMap = new HashMap<String, String>();Cursor cur = getContentResolver().query(Contacts.People.CONTENT_URI,null, null, null, null);while (cur.moveToNext()) {int indexName = cur.getColumnIndex(Contacts.PeopleColumns.NAME);// 獲得連絡人姓名列索引int indexPhone = cur.getColumnIndex(Contacts.PhonesColumns.NUMBER);// 獲得連絡人電話號碼列索引String name = cur.getString(indexName);String phone = cur.getString(indexPhone);contactsMap.put(name, phone);}cur.close();return contactsMap;}

該方法主要利用了ContentResolver的query方法,對於query方法的詳細介紹讀者可參考API文檔,該方法類似與SQL操作,返回的Cursor類對象是一個指向結果集的游標,通過對該游標進行操作即可擷取系統內所有連絡人的資訊。擷取到連絡人清單後,即可設計一個介面將其顯示在螢幕上供使用者選擇,接下去要做的就是傳送簡訊功能:

public void onItemClick(AdapterView<?> arg0, View arg1,int arg2, long arg3) {        String phone = phoneList.get(arg2);        String name = nameList.get(arg2);        SmsManager smsManager = SmsManager.getDefault();// 擷取系統的簡訊管理器            List<String> dividedMessageList = smsManager.divideMessage(message);//將天氣預報簡訊內容分割成多條簡訊(若簡訊內容大於70字)                for (String message : dividedMessageList) {                 smsManager.sendTextMessage(phone, null, message, null, null);// 傳送簡訊            }}

上述方法是為連絡人清單ListView自訂的響應事件方法,當使用者在介面中選定某個連絡人時,該方法即會響應。首先擷取簡訊管理類SmsManager的對象,並通過它將簡訊內容message進行切割(若簡訊長度大於70字),最後將其發送至指定連絡人。

(4)更換皮膚功能

該功能的思路非常簡單,提供一個RadioGroup供使用者進行選擇,並根據使用者的選擇將主介面的背景改為相應的圖片資源。但要注意的是這種背景的更改在程式退出後便消失,下次再進入應用時背景皮膚仍然顯示的是預設圖片,而不是使用者之前選擇的圖片,那麼要實現使用者佈建參數儲存的功能,就要利用SharePreferences類:

SharedPreferences selectedSkin = getSharedPreferences("skinSelection",Context.MODE_WORLD_READABLE);final SharedPreferences.Editor editor = selectedSkin.edit();skinGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {    public void onCheckedChanged(RadioGroup group, int checkedId) {         if (checkedId == skinBlue.getId()) {                   scrollView.setBackgroundResource(R.drawable.background_blue);            editor.putInt("SELECTED_SKIN",R.drawable.background_blue);        } else if (checkedId == skinGreen.getId()) {                   scrollView.setBackgroundResource(R.drawable.background_green);                   editor.putInt("SELECTED_SKIN",R.drawable.background_green);        }       ...      editor.commit();}

上述代碼的第一句話將會在手機或模擬器的data/data/<package_name>/shared_prefs目錄下產生一個名為skinSelection的XML文檔,用於儲存配置參數。隨後擷取一個Editor對象,並利用該對象的putXXX方法向XML文檔中添加資訊。這樣,在應用主Activity中,就可以通過讀取該文檔來進行介面背景的設定:

scrollView = (ScrollView) findViewById(R.id.scroll_view);SharedPreferences selectedSkin = getSharedPreferences("skinSelection",Context.MODE_PRIVATE);scrollView.setBackgroundResource(selectedSkin.getInt("SELECTED_SKIN",R.drawable.background_blue));

(5)自訂“返回”按鍵的功能

Android系統為我們預定義了各個按鍵的響應事件方法,例如“返回”按鍵就可以返回到上一個介面或者退出應用程式,那如果我們需要自訂按鍵的響應事件方法,則需要重寫onKeyDown方法:

public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {                            function();}/* 當按下MENU鍵時,開啟菜單 */if (keyCode == KeyEvent.KEYCODE_MENU) {super.openOptionsMenu();}return true;}

上述方法首先判斷按鍵代碼,若檢測到返回鍵被按下,則執行相應的處理動作。需要注意的是,由於重寫了onKeyDown方法,因此系統預定義的MENU鍵將會失效,必須對MENU鍵的響應事件也進行重寫,如上述代碼中的super.openOptionsMenu(),若缺少了這行代碼,則在應用中按MENU鍵將無效。

(6)啟動應用後自動開啟軟鍵盤的問題
由於Android在啟動一個應用後,焦點自動落在從上到下、從左往右的第一個可編輯介面組件上,因此若該組件是一個EditText,則啟動應用時將自動開啟軟鍵盤,影響了使用者體驗,最簡單的解決方案是開啟布局檔案,在第一個產生焦點的組件定義之前,再定義一個大小為0的LinearLayout,並將其設定為可捕捉焦點:

<LinearLayout android:focusable="true"android:focusableInTouchMode="true" android:layout_width="0px"android:layout_height="0px" />

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.