码迷,mamicode.com
首页 > 其他好文 > 详细

自己实现简单的天气预报应用(4)

时间:2015-03-05 00:06:34      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:

4.数据的本地存储

 

从网络上获取的我称之为原始数据,解析之后保存的称为item数据,下面修改解析工具类来分别按照请求码来进行解析:

 1 import org.json.JSONArray;
 2 import org.json.JSONException;
 3 import org.json.JSONObject;
 4 import org.json.JSONTokener;
 5 
 6 import java.util.ArrayList;
 7 
 8 public class ParseTools {
 9 
10     public static final int REQUEST_RAW=0;
11     public static final int REQUEST_ITEMS=1;
12 
13     private static ArrayList<WeatherItem> mWeatherItems=new ArrayList<>();
14 
15     public static ArrayList<WeatherItem> getInstance(String jsonData,int requestCode) throws  JSONException{
16         switch (requestCode){
17             case REQUEST_RAW:
18                 return parseRaw(jsonData);
19             case REQUEST_ITEMS:
20                 return parseItems(jsonData);
21             default:
22                 return null;
23         }
24     }
25 
26     //解析原始数据
27     private static ArrayList<WeatherItem> parseRaw(String jsonData) throws JSONException{
28         JSONObject object = (JSONObject) new JSONTokener(jsonData).nextValue();
29         JSONArray allData = object.getJSONArray("result");
30         for(int i=0;i<allData.length();++i){
31             WeatherItem witem=new WeatherItem();
32             JSONObject item=allData.getJSONObject(i);
33             witem.setDate(item.getString("days"));
34             witem.setWeek(item.getString("week"));
35             witem.setTemp_low(Integer.parseInt(item.getString("temp_low")));
36             witem.setTemp_high(Integer.parseInt(item.getString("temp_high")));
37             witem.setHumi_low(Integer.parseInt(item.getString("humi_low")));
38             witem.setHumi_high(Integer.parseInt(item.getString("humi_high")));
39             witem.setWeather(item.getString("weather"));
40             witem.setWinp(item.getString("winp"));
41             witem.setWind(item.getString("wind"));
42             mWeatherItems.add(witem);
43         }
44         return mWeatherItems;
45     }
46 
47     //从文件获取的数据来解析
48     private static ArrayList<WeatherItem> parseItems(String jsonData) throws JSONException{
49         ArrayList<WeatherItem> items=new ArrayList<>();
50         JSONArray array=(JSONArray) new JSONTokener(jsonData).nextValue();
51         for(int i=0;i<array.length();++i){
52             WeatherItem item=new WeatherItem(array.getJSONObject(i));
53             items.add(item);
54         }
55         return items;
56     }
57 }

 

将数据存储到文件中:新建一个文件操作的工具类

 1 import android.content.Context;
 2 
 3 import org.json.JSONArray;
 4 import org.json.JSONException;
 5 
 6 import java.io.BufferedReader;
 7 import java.io.IOException;
 8 import java.io.InputStream;
 9 import java.io.InputStreamReader;
10 import java.io.OutputStream;
11 import java.util.ArrayList;
12 
13 public class FileTools {
14 
15     private static final String jsonFile="data.json";
16     private static final String conf="date.conf";
17 
18     public static void saveData(Context context,ArrayList<WeatherItem> weatherItems) throws JSONException,IOException {
19 
20         JSONArray array=new JSONArray();
21         for(WeatherItem item : weatherItems){
22             array.put(item.toJson());
23         }
24 
25         try{
26             OutputStream out= context.openFileOutput(conf,Context.MODE_PRIVATE);
27             out.write(DateTools.getDate().getBytes());
28             out.close();
29         }catch (IOException e){
30             e.printStackTrace();
31         }
32 
33         try {
34             OutputStream out=context.openFileOutput(jsonFile,Context.MODE_PRIVATE);
35             out.write(array.toString().getBytes());
36             out.close();
37         }catch (IOException e){
38             e.printStackTrace();
39         }
40     }
41 
42     public static ArrayList<WeatherItem> loadData(Context context) throws IOException,JSONException{
43         ArrayList<WeatherItem> items=new ArrayList<>();
44 
45         BufferedReader reader=null;
46         try{
47             InputStream is=context.openFileInput(jsonFile);
48             reader=new BufferedReader(new InputStreamReader(is));
49             StringBuilder builder=new StringBuilder();
50             String line=null;
51             while((line=reader.readLine())!=null){
52                 builder.append(line);
53             }
54 
55             items = ParseTools.getInstance(builder.toString(),ParseTools.REQUEST_ITEMS);
56         }catch (IOException | JSONException e){
57             e.printStackTrace();
58         }
59 
60         return items;
61     }
62 }

 

又通过fetch到的数据可知,每天的预报数据中当天天气在第一个,他的Date可以唯一标记每天下载的数据:下面Date工具类构造和获取的数据相同的格式的Date字符串:

1 import android.text.format.DateFormat;
2 
3 import java.util.Date;
4 
5 public class DateTools {
6     public static String getDate(){
7         return DateFormat.format("yyyy-MM-dd",new Date()).toString();
8     }
9 }

 

 如果每次我们fetch都重新获取数据,就会显得很麻烦而且浪费流量(特别是非wifi下,虽然数据很少,但是多了也是浪费),因此上面FileTools类中使用一个配置文件保存当前在存储中的最新气象数据的获取时间,

注意,这样我们就可以通过在fetch的时候比较当前时间和保存的时间来决定是否下载数据。

 

主要逻辑如下,两个方法,一个判断是否从网上更新,另一个判断就是从网上更新数据并保存:

 1 private void update(){
 2         if(!configure.exists()){    //配置文件不存在的时候需要直接加载数据,一般是第一次启动程序的时候才没有此文件
 3             Toast.makeText(getApplicationContext(),"更新ing...",Toast.LENGTH_SHORT).show();
 4             fetchData();
 5         }else {
 6             try{
 7                 hasNew = ! DateTools.getDate().equals(FileTools.loadConf(getApplicationContext()));//判断从配置文件中读取的数据是否与当前时间相同
 8             }catch (IOException e){
 9                 e.printStackTrace();
10             }
11             if(hasNew){
12                 Toast.makeText(getApplicationContext(),"更新ing...",Toast.LENGTH_SHORT).show();
13                 fetchData();
14             }
15         }
16     }
17 
18     private void fetchData(){
19         RequestQueue mQueue= Volley.newRequestQueue(getApplicationContext());
20         mQueue.add(new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
21             @Override
22             public void onResponse(JSONObject jsonObject) {
23                 try {
24                     mWeatherItems = ParseTools.getInstance(jsonObject.toString(),ParseTools.REQUEST_RAW);
25                     //保存数据到文件
26                     FileTools.saveData(getApplicationContext(), mWeatherItems);
27                     Toast.makeText(getApplicationContext(),"更新完毕",Toast.LENGTH_SHORT).show();
28                 } catch (JSONException | IOException e) {
29                     e.printStackTrace();
30                 }
31             }
32         }, new Response.ErrorListener() {
33             @Override
34             public void onErrorResponse(VolleyError volleyError) {
35                 Toast.makeText(getApplicationContext(), "获取失败", Toast.LENGTH_SHORT).show();
36             }
37         }));
38         mQueue.start();
39     }

 

这样我们就可以在OnCreate方法中进行自动更新了,然后在Menu上加入手动更新的menuitem:

 1 //标记是否有最新的数据可用
 2     private static boolean hasNew;
 3     private static File configure;
 4     private ArrayList<WeatherItem> mWeatherItems=new ArrayList<>();
 5 
 6     @Override
 7     protected void onCreate(Bundle savedInstanceState) {
 8         super.onCreate(savedInstanceState);
 9         setContentView(R.layout.activity_main);
10 
11         configure=new File(getApplicationContext().getFilesDir().toString()+"/"+FileTools.conf);
12         update();
13 
14         ListView listView=(ListView)findViewById(R.id.listView);
15         listView.setEmptyView(getLayoutInflater().inflate(R.layout.empty_view,null));
16         try{
17             listView.setAdapter(new ItemAdapter(FileTools.loadData(getApplicationContext())));
18         }catch (IOException | JSONException e){
19             e.printStackTrace();
20         }
21     }

 

这里的Adapter是继承自BaseAdapter的一个基本Adapter:

 1 private class ItemAdapter extends BaseAdapter{
 2 
 3         ArrayList<WeatherItem> mItems=new ArrayList<>();
 4         private ItemAdapter(ArrayList<WeatherItem> items) {
 5             mItems=items;
 6         }
 7 
 8         @Override
 9         public View getView(int position, View convertView, ViewGroup parent) {
10             if(convertView==null){
11                 convertView=getLayoutInflater().inflate(R.layout.list_item,parent,false);
12             }
13             WeatherItem item=getItem(position);
14             ((TextView)convertView.findViewById(R.id.date)).setText(item.getDate());
15             ((TextView)convertView.findViewById(R.id.weather)).setText(item.getWeather());
16             return convertView;
17         }
18 
19         @Override
20         public long getItemId(int position) {
21             return position;
22         }
23 
24         @Override
25         public WeatherItem getItem(int position) {
26             return mItems.get(position);
27         }
28 
29         @Override
30         public int getCount() {
31             return mItems.size();
32         }
33     }

 

没有用ViewHolder,明天把UI优化下再补上。

 

OK,以上就是所有比较繁琐的操作,等到明天我检查一下相关可能出bug的地方并优化一下然后再解决Widget界面的问题。

自己实现简单的天气预报应用(4)

标签:

原文地址:http://www.cnblogs.com/lhyz/p/4314363.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!