多知天氣
前言
項目:https://github.com/w77996/Weather
多知天氣,代碼寫的不咋的,主要是給大家學習一下。有些東西也是借鑒別人的主要借鑒的是別人的UI,因為我寫UI太難看了TAT,我自己都看不下去。
項目主要是12月23日開始建立,春節(jié)半個多月回家了,就沒有寫了。三月初完成了整個項目。耗時近兩個月。平時在公司也就做點測試的任務,開發(fā)的任務還得等到畢業(yè)后才有TAT不知道畢業(yè)后會不會被留下,所以也是練練手。基于Rxjava+Retrofif+Ok之后也寫了一個是http+Mvp的閱讀類APP,鏈接在這里:HiReader,項目還沒有完全寫完,一直在更新,主要是自己學習一些主流的東西。
感謝開源
看別人的代碼慢慢學習,你會看到自己的成長的~
現(xiàn)在的我看這個畢業(yè)設計項目會覺得沒有當初想的那么難了,可以用更高的效率,更好的方式去實現(xiàn)這個項目。
借鑒過的項目
還有郭神的第二行代碼,不解釋
開源框架
- Butterknife注解式框架 http://jakewharton.github.io/butterknife/
- Glide圖片加載框架 https://github.com/bumptech/glide
- Okhttp網(wǎng)絡請求框架 http://square.github.io/okhttp/
- LitePal數(shù)據(jù)庫操作框架 https://github.com/LitePalFramework/LitePal
- Logger 開發(fā)日志框架 https://github.com/orhanobut/logger
- Gson json數(shù)據(jù)解析框架 https://github.com/google/gson
- SlidingMenu側拉菜單框架 https://github.com/jfeinstein10/SlidingMenu
- SwipeMenuListView側滑刪除框架 https://github.com/baoyongzhang/SwipeMenuListView/
- 易源數(shù)據(jù)提供的天氣數(shù)據(jù) https://www.showapi.com/
- 極光推送服務 https://www.jiguang.cn/accounts/platform
- 有米廣告平臺 https://www.youmi.net/
- 高德地圖 http://lbs.amap.com/
功能
- 第一次打開APP引導頁,緩沖加載
- 天氣信息的顯示
- 廣告,推送
- 桌面小工具
- 新聞資訊的查看
- 藍牙串口傳輸溫度
那時候還不大會使用Gson,簡直就是Android開發(fā)的敗筆呀~傻乎乎的自己去解析近千的json信息,也是醉了。
準備
易源數(shù)據(jù)中的天氣Json如果請求的是15天的Json數(shù)據(jù)那有近千行,所以取自己有用的。
- 開發(fā)環(huán)境:Android studio
- 數(shù)據(jù)獲取:易源數(shù)據(jù)SDK
幫助工具
Json數(shù)據(jù)分析
這么多Json,細思極恐啊~
不過我們一步步來分析,key的作用可以看易源的文檔。
- cityInfo 城市信息
- time 時間
- now 現(xiàn)在的天氣
- f1~f6 近一星期的天氣預報信息
- alarmList 預警信息
- hourDataList 半小時更新一次的天氣信息
- aqi 空氣質(zhì)量
天氣封裝
在目錄下新建com.weather.entity
其實覺得Gson挺好用的……
那我為何不用Gson呢。。。因為那時候還不會用@Serializedname,易源數(shù)據(jù)的json竟然還有用數(shù)字開頭的key ┭┮﹏┭┮
然后經(jīng)過了一番的倒騰,終于一個個把數(shù)據(jù)給對上了= =,當做自己解析json數(shù)據(jù)的練手吧
網(wǎng)絡請求
主要是用okhttp,用到的是郭神的幾行代碼
public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(address).build();
client.newCall(request).enqueue(callback);
}
直接傳入地址就請求到數(shù)據(jù)了,
不過這邊有個坑!!
有個坑!!!
有個坑!!!
重要的事情所三遍
在請求后不能直接使用response.body().string(),要緩存一下才能使用,不然為空。
//使用okhttp的封裝進行請求
HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
//這里有坑
String responseText = response.body().string();
數(shù)據(jù)庫
本人數(shù)據(jù)庫超級爛,不過不算渣渣,還是能寫點東西,數(shù)據(jù)庫我設計的十分簡單,只有兩個重要的屬性,就是城市名和json數(shù)據(jù),為的是在無網(wǎng)絡狀態(tài)下從數(shù)據(jù)庫直接獲取到json數(shù)據(jù),解析后顯示到界面上。
框架的話本來打算用GreenDao的,不過后面改成LitePal了。
public class WeatherDB extends DataSupport {
public int id;
public String mCityName;
public String mJsonData;
...
廣告,推送
廣告用的是有米廣告,直接對著SDK把代碼加進去就好了,想用騰訊的廣告,但是打電話給我問我有沒營業(yè)執(zhí)照。。。。暈,沒有所以沒有審核通過。
推送使用的是極光推送,也是直接使用SDK,本來使用的是BOMB的,但是Bomb SDK中的okhttp和我自己的依賴起沖突了,而且還有一些機子無法推送成功,所以最后改成了極光推送,這都是血淋淋的坑啊,一步步踩過來簡直吐血。
//廣告條初始化
View bannerView = BannerManager.getInstance(WeatherActivity.this)
.getBannerView(WeatherActivity.this, new BannerViewListener() {
@Override
public void onRequestSuccess() {}
@Override
public void onSwitchBanner() {}
@Override
public void onRequestFailed() {}
});
// 獲取要嵌入廣告條的布局
LinearLayout bannerLayout = (LinearLayout) findViewById(R.id.ll_banner);
// 將廣告條加入到布局中
bannerLayout.addView(bannerView);
嵌入廣告就是這么簡單暴力,但是建議用積分墻,我這個是廣告條。。。。。
因為。。。
他們廣告條好像沒啥廣告。。。可能在實際中顯示不出來,不過在初始化時使用測試廣告的話那就可以看到了。
城市選擇
這里推薦別人寫的一個依賴,直接傳送門 CityPicker
用的是高德地圖定位

桌面小工具
這方面我需要學習的東西還有很多的,開啟服務在后臺更新,想想后期如果能加入Rxjava,看看能不能優(yōu)化一些操作,不過在使用Glide加載圖片到AppWidget時需要獲取到ImageView控件,所以有折騰了一下。

//通過APPWIdgetTarget獲取到Image控件
mAppWidgetTarget =new AppWidgetTarget(getApplicationContext(),mRemoteViews,R.id.appwiget_picture,mAppwidgetId);
Glide.with(getApplicationContext()).load(weatherBean.getmNowWeatherBean().getmWeather_Pic()).asBitmap().into(mAppWidgetTarget);
藍牙和單片機通信模塊
因為本人學過嵌入式開發(fā),在機緣巧合的時候接觸了Android,所以現(xiàn)在做Android開發(fā),單片機上使用的是DS18B20溫度傳感器,藍牙是HC-05,通過串口進行溫度傳輸,不要覺得很難,其實很簡單,嗯,說笑的,基礎好就很簡單啦,代碼并不多,曾經(jīng)試過一次返回數(shù)據(jù)一直都是亂碼,找了一個星期的問題都沒找到,最后發(fā)現(xiàn)是波特率的問題,太感動了,傳送門
界面
進入APP加載界面,淡入淡出效果,弱引用持有Activity對象,文字動畫效果

//activity切換的淡入淡出效果
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
//弱引用的使用
private static class SwitchHandler extends Handler {
private WeakReference<SplashActivity> mWeakReference;
SwitchHandler(SplashActivity activity) {
mWeakReference = new WeakReference<SplashActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
SplashActivity activity = mWeakReference.get();
if (activity != null) {
WeatherActivity.launch(activity);
activity.finish();
}
}
}
主界面

這邊其實沒有按照Material design的要求透明化狀態(tài)欄,主界面填充整個手機屏幕,通過計算手機屏幕總高度,減去狀態(tài)欄的高度和ActionBar的高度,得出了主界面視圖的高度,就做到了在任何分辨率下都只顯示這樣的界面的效果(原諒我這種拗口的表達,你懂就好哈哈哈哈~~)
/**
* 獲取手機屏幕高度
*
* @param context
* @return
*/
public static int getDisplayHeight(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
// 獲取屏幕信息
wm.getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
/**
* 獲取手機屏幕寬度
*
* @param context
* @return
*/
public static int getDisplayWidth(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
// 獲取屏幕信息
wm.getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
/**
* 反射方法獲取狀態(tài)欄高度
*
* @param context
* @return
*/
public static int getStatusBarHeight(Context context) {
int statusBarHeight = 20;
try {
Class<?> _class = Class.forName("com.android.internal.R$dimen");
Object object = _class.newInstance();
Field field = _class.getField("status_bar_height");
int restult = Integer.parseInt(field.get(object).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(
restult);
} catch (Exception e) {
e.printStackTrace();
}
// Toast.makeText(getActivity(), "StatusBarHeight = " + statusBarHeight,
// Toast.LENGTH_SHORT).show();
return statusBarHeight;
}
/**
* 獲取?attr/actionBarSize高度
*
* @param context
* @return
*/
public static int getActionBarSize(Context context) {
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.actionBarSize, typedValue, true);
int actionBarHeight = TypedValue.complexToDimensionPixelSize(typedValue.data, context.getResources().getDisplayMetrics());
return actionBarHeight;
}
// mNowWeatherHeight高度=屏幕高度-標題欄高度-狀態(tài)欄高度
mNowWeatherHeight = SystemUtils.getDisplayHeight(mContext) - SystemUtils.getActionBarSize(mContext) - SystemUtils.getStatusBarHeight(mContext);
每半小時更新的數(shù)據(jù)list和未來天氣預報
這邊是RecyclerView,在繪制每個Item的時候也是計算了屏幕的寬度,每個item占屏幕的1/5,所以在所有分辨率下都只呈現(xiàn)五個Item

空氣指數(shù)和生活指數(shù)
UI 很多都是從Android Studio中的Vetor assert里面找的,大家也可以去找找適合自己的UI,還有阿里的iconfont阿里巴巴矢量圖標庫

城市編輯界面
背景Activity半透明,填充屏幕,listview側滑刪除
進入Activity后從數(shù)據(jù)庫中獲取到數(shù)據(jù),然后顯示到listview中,進行操作后再主界面的onActivityResult中重新獲取數(shù)據(jù)庫中的內(nèi)容,更新UI.

//側滑刪除
SwipeMenuCreator creator = new SwipeMenuCreator() {
@Override
public void create(SwipeMenu menu) {
SwipeMenuItem openItem = new SwipeMenuItem(
getApplicationContext());
SwipeMenuItem deleteItem = new SwipeMenuItem(
getApplicationContext());
deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,
0x3F, 0x25)));
deleteItem.setWidth(dp2px(60));
deleteItem.setIcon(R.drawable.ic_delete);
menu.addMenuItem(deleteItem);
}
};
mCityEditListview.setMenuCreator(creator);
mCityEditListview.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
switch (index) {
case 0:
// open
Toast.makeText(getApplicationContext(), position + " menu click", Toast.LENGTH_SHORT).show();
if(mCityList.size()>1){
CityRmoveThread cityRmoveThread = new CityRmoveThread(mCityList.get(position).getmCityName());
cityRmoveThread.start();
mCityList.remove(position);
mCityEditListAdapter.notifyDataSetChanged();
}else{
Toast.makeText(getApplicationContext(), position + " 親,刪除了你看啥?", Toast.LENGTH_SHORT).show();
}
break;
}
// false : 會關閉菜單; true :不會關閉菜單
return false;
}
});
新聞,笑話,美圖
這個模塊寫的說實話我自己都看不下去了,那時候為了趕進度,,哎,意思一下。用的是sharepreference進行很簡單的存儲。嗯,就是這樣的
總結
僅供參考,不得用于商業(yè)項目,如果覺得對你有幫助,給個Star吧親~
在寫項目的時候?qū)懥撕枚嗉毠?jié),都忘了很多了,還是很用心去處理一些問題的~
還有引導頁設計的不是很好,是直接扣網(wǎng)絡上的圖片,到第三個界面的時候點擊一下就可以進去了~
謝謝觀看