去年,做了一個簡單的案頭天氣外掛程式:Android之高仿墨跡天氣案頭組件(AppWidgetProvider) 簡單得不能再簡單了,而且到現在估計都用不了啦,其實一直都想好好修改一下,由於一直比較懶,再加上工作比較忙,轉眼就快一年了。最近抽出幾天時間,重新完善了一下,很簡單,但是個人覺得對於天氣一類的應用來說,完全夠了。不需要那麼多花哨的功能,能簡單得告訴我們天氣資訊就可以了,好了,廢話不多說,我們來看看效果:
百度應用apk下載:http://as.baidu.com/a/item?docid=4064176&pre=web_am_se
本文源碼地址v1.0.0:http://download.csdn.net/detail/weidi1989/5768855
新版本V1.2.0已上傳:http://download.csdn.net/detail/weidi1989/5951563
changelog:
①.加入SplashActivity,減少進入應用時黑屏時間,更好的使用者體驗。
②.重寫BladeView,修複選擇城市後,popwindow還未關閉會導致程式異常關閉的bug。
③.修複因空氣品質api更改導致擷取失敗的bug。
④.其他一些小細節最佳化。
1.簡單的一個案頭外掛程式,上面是我的,下面是墨跡天氣的,當然,圖片資源都是來自墨跡天氣。字型有些偏差,顏色改成白色就好了。
2.主介面,圖片資源來自網易新聞,因為感覺它的圖片很小清新,有沒有這種感覺啊?哈哈,標題列跟墨跡天氣的功能差不多,左邊這個是城市管理,右邊兩個按鈕一個自動定位,一個是重新整理天氣。下面主介面右上方顯示的是空氣品質pm2.5值,中間是當天天氣情況,下面是未來三天內的天氣情況。
3.全國各地城市,總共有2500多個。
4.自動匹配搜尋,只是全拼、城市首字母、中文三種搜尋方式。
好吧!今天是周六,我就不貼全代碼了,估計也沒什麼人看,就說說主要思路吧!
①.主介面天氣資訊,是通過解析3個地址才擷取到的。
簡要天氣:http://www.weather.com.cn/data/sk/101280601.html
詳細天氣:http://m.weather.com.cn/data/101280601.html
空氣品質:http://www.pm25.in/api/querys/pm2_5.json?city=shenzhen&token=5j1znBVAsnSf5xQyNQyq&stations=no
注意空氣品質這裡的token是公開金鑰,每個小時可以請求500次,請別頻繁請求,給別的開發工程師留點機會吧~謝謝。
②.案頭外掛程式,我這裡就不多說了,基本的使用,在之前的那個博文裡面講得還算比較詳細,我這裡只是最佳化了一下,最佳化了維護外掛程式更新的那個服務,使其不至於輕易得被系統給回收掉。看來還是得貼代碼了,我在AndroidManifest.xml檔案中做了如下處理:
<receiver android:name="com.way.weather.WeatherWidget" android:label="@string/app_name" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="android.intent.action.USER_PRESENT" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/weather_widget_4x2" /> </receiver>
多了一個android.intent.action.USER_PRESENT事件的監聽,其實他是監聽系統喚醒的廣播,當系統在睡眠的時候,我們的服務最容易被回收,所以,監聽這個廣播,當系統喚醒時,重新啟動一下這個服務。會使得這個服務變得比較頑強一點。我測試了3天左右,都沒出現服務幹掉的情況。
③.重點說一下城市列表的匹配搜尋吧,首先,2500多個城市,要想快速匹配,臨時讀取資料庫是不可能達到快速的,所以,我們在應用啟動時,就可以把這2000多個城市從資料庫中讀入記憶體中。然後,根據首字的拼音首字母排序整理好,以便我們設定ListView的Adapter。我們看一下搜尋城市的SearchCityAdapter:它實現了Filterable這個介面,覆蓋了getFilter這個函數,這個函數是最重要的部分了,匿名內部類Filter將動態傳入的字串進行匹配處理(performFiltering函數處理),然後動態更新adapter,從而實現動態匹配搜尋。
public class SearchCityAdapter extends BaseAdapter implements Filterable {private List<City> mAllCities;private List<City> mResultCities;private LayoutInflater mInflater;private Context mContext;public SearchCityAdapter(Context context, List<City> allCities) {mContext = context;mAllCities = allCities;mResultCities = new ArrayList<City>();mInflater = LayoutInflater.from(mContext);}@Overridepublic int getCount() {return mResultCities.size();}@Overridepublic City getItem(int position) {return mResultCities.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = mInflater.inflate(R.layout.search_city_item, null);}TextView provinceTv = (TextView) convertView.findViewById(R.id.search_province);provinceTv.setText(mResultCities.get(position).getProvince());TextView cityTv = (TextView) convertView.findViewById(R.id.column_title);cityTv.setText(mResultCities.get(position).getCity());return convertView;}//下面這部分代碼是至關重要的@Overridepublic Filter getFilter() {Filter filter = new Filter() {protected void publishResults(CharSequence constraint,FilterResults results) {mResultCities = (ArrayList<City>) results.values;if (results.count > 0) {notifyDataSetChanged();} else {notifyDataSetInvalidated();}}protected FilterResults performFiltering(CharSequence s) {String str = s.toString().toUpperCase();// mFilterStr = str;FilterResults results = new FilterResults();ArrayList<City> cityList = new ArrayList<City>();if (mAllCities != null && mAllCities.size() != 0) {for (City cb : mAllCities) {// 匹配全屏、首字母、和城市名中文if (cb.getAllFristPY().indexOf(str) > -1|| cb.getAllPY().indexOf(str) > -1|| cb.getCity().indexOf(str) > -1) {cityList.add(cb);}}}results.values = cityList;results.count = cityList.size();return results;}};return filter;}}
接下來讓我們看一下,資料是如何傳遞給SearchCityAdapter進行處理的,我就貼出監聽EditText動態變化的那個函數,mSearchCityAdapter.getFilter().filter(s);這樣一句話就可以了。其實也不是很難嘛!
@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {mSearchCityAdapter = new SearchCityAdapter(SelectCtiyActivity.this,mCities);mSearchListView.setAdapter(mSearchCityAdapter);mSearchListView.setTextFilterEnabled(true);if (mCities.size() < 1 || TextUtils.isEmpty(s)) {mCityContainer.setVisibility(View.VISIBLE);mSearchContainer.setVisibility(View.INVISIBLE);mClearSearchBtn.setVisibility(View.GONE);} else {mClearSearchBtn.setVisibility(View.VISIBLE);mCityContainer.setVisibility(View.INVISIBLE);mSearchContainer.setVisibility(View.VISIBLE);mSearchCityAdapter.getFilter().filter(s);}}
好了,就介紹到這裡了,想瞭解更多的朋友可以下載源碼看看,恭喜你已經看到文章最後了,我也洗洗睡覺去了,明天好好玩一下!