前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android:CoolWeather天气查看器

Android:CoolWeather天气查看器

作者头像
提莫队长
发布2019-03-01 09:57:31
1K0
发布2019-03-01 09:57:31
举报
文章被收录于专栏:刘晓杰刘晓杰

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

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();

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年02月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.单例模式
  • 2.网络编程
  • 3.解析XML和JSON数据
    • 第一:XML数据(Pull解析和SAX解析)
      • 第二:JSON数据(Json解析和Gson解析)
      • 4.SharedPreference的使用
      • 5.Service的使用
      • 6.BroadcastReceiver的使用
      • 7.多线程
        • 第一种:
          • 第二种:
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档