Android:CoolWeather天气查看器

酷欧天气至少应该具备以下功能:

1. 可以罗列出全国所有的省、市、县。

2. 可以查看全国任意城市的天气信息。

3. 可以自由地切换城市,去查看其他城市的天气。

4. 提供手动更新以及后台自动更新天气的功能。

代码在这里:点击打开链接

但是由于网络地址的问题一直加载不出来,所以也没法通过安装查看。不过从这个软件还是可以学到很多东西。

1.单例模式

// 构造函数私有化
private CoolWeatherDB(Context context) {
helper = new CoolWeatherOpenHelper(context);
db = helper.getWritableDatabase();
}
// 提供了getInstance()方法来获取实例,这样就可以保证全局范围内只会有一个的实例
public synchronized static CoolWeatherDB getInstance(Context context) {
if (coolWeatherDB == null) {
coolWeatherDB = new CoolWeatherDB(context);
}
return coolWeatherDB;
}

2.网络编程

HttpURLConnection connection = null;
try {
URL url = new URL(address);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
} catch (Exception e) {

} finally {
if (connection != null) {
connection.disconnect();
}
}

3.解析XML和JSON数据

第一:XML数据(Pull解析和SAX解析)

/*
* 首先要获取到一个XmlPullParserFactory 的实例, 并借助这个实例得到XmlPullParser对象,
* 然后调用XmlPullParser 的setInput()方法将服务器返回的XML数据设置进去就可以开始解析了
* 解析的过程也是非常简单,通过getEventType()可以得到当前的解析事件, 然后在一个while 循环中不断地进行解析,
* 如果当前的解析事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没完成,
* 调用next()方法后可以获取下一个解析事件。 在while 循环中,我们通过getName()方法得到当前结点的名字,
* 如果发现结点名等于id、name 或version,就调用nextText()方法来获取结点内具体的内容,
* 每当解析完一个app结点后就将获取到的内容打印出来。/
*/
//XML
private void parseXMLWithPull(String xmlData) {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlData));
int eventType = xmlPullParser.getEventType();
String id = "";
String name = "";
String version = "";
while (eventType != XmlPullParser.END_DOCUMENT) {
String nodeName = xmlPullParser.getName();
switch (eventType) {
// 开始解析某个结点
case XmlPullParser.START_TAG: {
if ("id".equals(nodeName)) {
id = xmlPullParser.nextText();
} else if ("name".equals(nodeName)) {
name = xmlPullParser.nextText();
} else if ("version".equals(nodeName)) {
version = xmlPullParser.nextText();
}
break;
}
// 完成解析某个结点
case XmlPullParser.END_TAG: {
if ("app".equals(nodeName)) {
Log.d("MainActivity", "id is " + id);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "version is " + version);
}
break;
}
default:
break;
}
eventType = xmlPullParser.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}

//SAX
class ContentHandler extends DefaultHandler {
private String nodeName;
private StringBuilder id;
private StringBuilder name;
private StringBuilder version;

@Override//在开始XML 解析的时候调用
public void startDocument() throws SAXException {
id = new StringBuilder();
name = new StringBuilder();
version = new StringBuilder();
}
@Override//在开始解析某个结点的时候调用
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 记录当前结点名
nodeName = localName;
}
@Override//在获取结点中内容的时候调用
public void characters(char[] ch, int start, int length) throws SAXException {
// 根据当前的结点名判断将内容添加到哪一个StringBuilder对象中
if ("id".equals(nodeName)) {
id.append(ch, start, length);
} else if ("name".equals(nodeName)) {
name.append(ch, start, length);
} else if ("version".equals(nodeName)) {
version.append(ch, start, length);
}
}
@Override//在完成解析某个结点的时候调用
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("app".equals(localName)) {
Log.d("ContentHandler", "id is " + id.toString().trim());
Log.d("ContentHandler", "name is " + name.toString().trim());
Log.d("ContentHandler", "version is " + version.toString().trim());
// 最后要将StringBuilder清空掉
id.setLength(0);
name.setLength(0);
version.setLength(0);
}
}
@Override//在完成整个XML 解析的时候调用
public void endDocument() throws SAXException {
}
}
private void parseXMLWithSAX(String xmlData) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
ContentHandler handler = new ContentHandler();
// 将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
// 开始执行解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
} catch (Exception e) {
e.printStackTrace();
}
}

第二:JSON数据(Json解析和Gson解析)

//Json
private void parseJSONWithJSONObject(String jsonData) {
try {
JSONArray jsonArray = new JSONArray(jsonData);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String id = jsonObject.getString("id");
String name = jsonObject.getString("name");
String version = jsonObject.getString("version");
Log.d("MainActivity", "id is " + id);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "version is " + version);
}
} catch (Exception e) {
e.printStackTrace();
}
}

//Gson
private void parseJSONWithGSON(String jsonData) {
Gson gson = new Gson();
List<App> appList = gson.fromJson(jsonData,  new TypeToken<List<App>>() {}.getType() );
for (App app : appList) {
Log.d("MainActivity", "id is " + app.getId());
Log.d("MainActivity", "name is " + app.getName());
Log.d("MainActivity", "version is " + app.getVersion());
}
}

4.SharedPreference的使用

SharedPreferences sharedPreferences = getSharedPreferences("name", Activity.MODE_PRIVATE);
Editor editor = sharedPreferences.edit();
editor.putInt("are", 0);
editor.apply();

int flag = sharedPreferences.getInt("are", 0);

5.Service的使用

就是我们学习过的创建定时任务的技巧。为了保证软件不会消耗过多的流量,这里将时间间隔设置为8小时,8小时后就应该执行AutoUpdateReceiver 的onReceive()方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
updateWeather();
stopSelf();
}
}).start();
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
int anHour = 8 * 60 * 60 * 1000; // 这是8小时的毫秒数
long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
Intent i = new Intent(this, AutoUpdateReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
return super.onStartCommand(intent, flags, startId);
}
具体的介绍参见http://blog.csdn.net/lxj1137800599/article/details/50358765
和http://blog.csdn.net/lxj1137800599/article/details/50495046

6.BroadcastReceiver的使用

public class AutoUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
}
}

7.多线程

异步消息处理的整个流程:首先需要在主线程当中创建一个Handler对象,并重写handleMessage()方法。然后当子线程中需要进行UI 操作时,就创建一个Message对象,并通过Handler将这条消息发送出去。之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理消息,最后分发回Handler的handleMessage()方法中。由于Handler是在主线程中创建的,所以此时handleMessage()方法中的代码也会在主线程中运行,于是我们在这里就可以安心地进行UI操作了。

第一种:

private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0x001:
// 在这里可以进行UI操作
break;
default:
break;
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
handler.sendEmptyMessage(0x001);
}
}).start();

第二种:

使用AsyncTask(即使你对异步消息处理机制完全不了解,也可以十分简单地从子线程切换到主线程。)
第一个泛型参数指定为Void,表示在执行AsyncTask 的时候不需要传入参数给后台任务。
第二个泛型参数指定为Integer,表示使用整型数据来作为进度显示单位。
第三个泛型参数指定为Boolean,则表示使用布尔型数据来反馈执行结果。
public class DownloadTask extends AsyncTask<Void, Integer, Boolean> {
@Override
protected void onPreExecute() {
/*
* 这个方法会在后台任务开始执行之前调用,用于进行一些界面上的初始化操作,
* 比如显示一个进度条对话框等。/
*/
}
@Override
protected Boolean doInBackground(Void... arg0) {
/*
* 这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任
* 务。任务一旦完成就可以通过return 语句来将任务的执行结果返回,如果AsyncTask 的
* 第三个泛型参数指定的是Void,就可以不返回任务执行结果。
* 注意,在这个方法中是不可以进行UI 操作的,
* 如果需要更新UI元素,可以调用publishProgress(Progress...)
* publishProgress(Integer... values);/
*/
return true;
}
@Override
protected void onProgressUpdate(Integer... values) {
/*
* 当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就会很快被调用,
* 方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI 进行操作,
* 利用参数中的数值就可以对界面元素进行相应地更新。/
*/
}
@Override
protected void onPostExecute(Boolean result) {
/*
* 当后台任务执行完毕并通过return 语句进行返回时,这个方法就很快会被调用。
* 返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI 操作,
* 比如说提醒任务执行的结果,以及关闭掉进度条对话框等。/
*/
}
}
如果想要启动这个任务,只需编写以下代码即可:
new DownloadTask().execute();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值