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

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

时间:2015-03-05 22:11:24      阅读:339      评论:0      收藏:0      [点我收藏+]

标签:

6.加入Widget小部件

 

由于小部件的存在,我们可以直接在启动器上查看某些数据,下面通过一个简单布局Widget的实现学习如何与Widget的Provider类通信,和如何用外部传入的数据初始化Widget,

 

首先,按照编写小部件的标准步骤,定义布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <TextView
        android:id="@+id/date"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/temp"
        android:textSize="30sp"
        style="@style/MyTheme"
        android:gravity="center"/>
</LinearLayout>

 

然后是定义appwidget_info的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
    android:initialLayout="@layout/widget_layout"
    android:minWidth="250dp"
    android:minHeight="40dp"
    android:resizeMode="none"
    android:updatePeriodMillis="360000"
    xmlns:android="http://schemas.android.com/apk/res/android">
</appwidget-provider>

 

这样就可以定义AppWidgetProvider的子类了:

 1 import android.appwidget.AppWidgetManager;
 2 import android.appwidget.AppWidgetProvider;
 3 import android.content.Context;
 4 import android.content.Intent;
 5 import android.widget.RemoteViews;
 6 
 7 //管理所有Widget的类
 8 @SuppressWarnings("NullableProblems")
 9 public class WeatherWidgetProvider extends AppWidgetProvider {
10 
11     private static final String TAG="WeatherWidgetProvider";
12     private static WeatherItem mItem=new WeatherItem();//这里必须使用静态成员
13 
14     @Override
15     public void onReceive(Context context, Intent intent) {
16         switch (intent.getAction()){
17             case MainActivity.ACTION_SEND_DATA:
18                 if(intent.getExtras()!=null){
19                     mItem=(WeatherItem)intent.getBundleExtra(MainActivity.EXTRA).getSerializable(MainActivity.EXTRA_ITEM_DATA);
20                 }
21                 break;
22         }
23         super.onReceive(context, intent);
24     }
25 
26     @Override
27     public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
28         RemoteViews rv = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
29         rv.setTextViewText(R.id.date,mItem.getDate());
30         for(int appWidgetId : appWidgetIds){
31             appWidgetManager.updateAppWidget(appWidgetId,rv);
32         }
33         super.onUpdate(context, appWidgetManager, appWidgetIds);
34     }
35 }

在这里,由于一开始没有注意到整个类的对象问题,没有把mItem这个成员定义为静态,因此,每次在onReceive这个方法被调用的时候都无法获取应当已经被传给这个类的Weather类对象的数据。

 

在MainActivity中添加一些发送数据给Provider的语句:

 1 private void update(){
 2         //只有第一次加载数据还没有下载完成的时候才会有mAdapter为空的情况
 3         if(mAdapter == null){
 4             mAdapter = new ItemAdapter(mWeatherItems);
 5             listView.setAdapter(mAdapter);
 6         }
 7 
 8         if(!configure.exists()){
 9             Toast.makeText(getApplicationContext(),R.string.fetching,Toast.LENGTH_SHORT).show();
10             fetchData();
11         }else{
12             try{
13                 hasNew = !(DateTools.getDate().equals(FileTools.loadConf(getApplicationContext())));
14             }catch (IOException e){
15                 e.printStackTrace();
16             }
17             if(hasNew){
18                 Toast.makeText(getApplicationContext(),R.string.fetching,Toast.LENGTH_SHORT).show();
19                 fetchData();
20             }else{
21                 try{
22                     mWeatherItems=FileTools.loadData(getApplicationContext());
23                     mAdapter = new ItemAdapter(mWeatherItems);
24                     listView.setAdapter(mAdapter);
25                     mIntent.setAction(ACTION_SEND_DATA);
26                     mBundle.putSerializable(EXTRA_ITEM_DATA,mWeatherItems.get(0));
27                     mIntent.putExtra(EXTRA,mBundle);
28                     sendBroadcast(mIntent);
29                 }catch (IOException | JSONException e){
30                     e.printStackTrace();
31                 }
32             }
33         }
34     }

还有这里:

 1 private void fetchData(){
 2         RequestQueue mQueue= Volley.newRequestQueue(getApplicationContext());
 3         mQueue.add(new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
 4             @Override
 5             public void onResponse(JSONObject jsonObject) {
 6                 //服务器有响应的时候才会调用此方法
 7                 try {
 8                     mWeatherItems = ParseTools.getInstance(jsonObject.toString(),ParseTools.REQUEST_RAW);
 9                     //保存数据到文件
10                     FileTools.saveData(getApplicationContext(), mWeatherItems);
11                     Toast.makeText(getApplicationContext(),"更新完毕",Toast.LENGTH_SHORT).show();
12 
13                     mAdapter=new ItemAdapter(mWeatherItems);
14                     listView.setAdapter(mAdapter);
15 
16                     mIntent.setAction(ACTION_SEND_DATA);
17                     mBundle.putSerializable(EXTRA_ITEM_DATA,mWeatherItems.get(0));
18                     mIntent.putExtra(EXTRA,mBundle);
19                     sendBroadcast(mIntent);
20 
21                 } catch (JSONException | IOException e) {
22                     e.printStackTrace();
23                 }
24             }
25         }, new Response.ErrorListener() {
26             @Override
27             public void onErrorResponse(VolleyError volleyError) {
28                 Toast.makeText(getApplicationContext(), "获取失败", Toast.LENGTH_SHORT).show();
29             }
30         }));
31         mQueue.start();
32     }

 

当然,最后不能忘记在配置文件里写上receiver的节点定义:

<receiver android:name=".WeatherWidgetProvider" android:label="@string/weather">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
                <action android:name="action.appwidget.SEND_DATA"/>
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/widget_info"/>
        </receiver>

(由于AppWidgetProvider是一个BroadcastReceiver的子类,看上面那个onReceive方法就知道了,因此是可以自定义action-filter的,同时,当然也可以在其他类中通过sendBroadcast类被调用,并解析数据)

 

完成后的效果是:

 技术分享

技术分享

 

 

这里在测试的时候发现一个问题,当程序运行在上面的模拟器(5.0)中时,会因为后台程序没有运行(已经被销毁)而导致添加小部件的时候没有数据被显示,但是在真机(4.0.x)上测试的时候却没有这个问题。

然后刚才又发现,如果安装之后没有启动程序而直接添加小部件,那么当启动程序完成数据加载之后小部件也不会被更新,而在之后加入的小部件却可以正确初始化。

技术分享

 

这个问题暂时没有解决,下一阶段就是思考一下如何解决这个问题。

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

标签:

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

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