1、General

抽象类StateTracker

每个按钮实现一个StateTracker的子类(亮度按钮特殊处理不实现该类):

WifiStateTracker

BluetoothStateTracker

GpsStateTracker

SyncStateTracker

2、创建流程:

1、将PowerSave widget 拖出来后,系统调用回调onUpdate

// Update each requested appWidgetId

RemoteViews view = buildUpdate(context);

for (int i = 0; i <appWidgetIds.length; i++) {

appWidgetManager.updateAppWidget(appWidgetIds[i], view);

}

appWidgetManager.updateAppWidget(appWidgetIds[i],view)为调用系统函数不做解释。

BuildUpdate:

1、创建一个RemoteViews 指定layout

views =new RemoteViews(context.getPackageName(),R.layout.widget);

2、设置按键响应

views.setOnClickPendingIntent(R.id.btn_wifi,getLaunchPendingIntent(context,BUTTON_WIFI))

views.setOnClickPendingIntent(R.id.btn_wifi,getLaunchPendingIntent(context,BUTTON_BT))

………………..

3、获取各种Wifi BT等状态,更新图标

updateButtons

4、Done

updateButtons

sWifiState.setImageViewResources(context,views);

sBluetoothState.setImageViewResources(context,views);

……

setImageViewResources为抽象父类实现。

1、 获取按钮和按钮下面指示器的id

getButtonId()、getIndicatorId()此两者子类负责实现,提供给父类id信息

2、 获取指示器的位置(左中右),父类默认为中、wifi为重写该方法,返回左

3、 getTriState获取开、关、切换中三种状态 该方法调用子类的getActualState方法,负责返回所代表部件的状态。PS: getActualState返回的是五种状态之一:开、关、正在开、正在关、未知状态(异常)。getTriState将五种状态转换成三种状态,以供指示器显示。

4、 根据以上三步收集的信息 调用views.setImageViewResource绘出按钮以及指示器

创建流程至此结束。

2、widget如何响应按钮事件

由于widget里面是RemoteViews,所以没有OnClickListener,只能通过intent发送给Host来执行

先来看下创建是设置的getLaunchPendingIntent,

launchIntent.addCategory(Intent.CATEGORY_ALTERNATIVE);

launchIntent.setData(Uri.parse("custom:" + buttonId));

PendingIntent pi =PendingIntent.getBroadcast(context, 0 /* no requestCode */,

launchIntent, 0 /* no flags*/);

可以看出,intent携带了buttonId的数据来区别到底是哪个按钮事件,然后getBroadcast表明,按键事件将通过broadcast事件来通知widget。在onReceive中

else if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)){

Uri data = intent.getData();

int buttonId = Integer.parseInt(data.getSchemeSpecificPart());

if(buttonId == BUTTON_WIFI) {

sWifiState.toggleState(context);

}

else if (buttonId == BUTTON_BRIGHTNESS) {

toggleBrightness(context);

}else if (buttonId == BUTTON_SYNC) {

sSyncState.toggleState(context);

}

}

ToggleState

1、获取当前部件的状态。getTriState,根据当前状态确定是否需要进行状态切换

2、如果需要状态切换,调用子类的requestStateChange,子类负责切换所代表部件的状态。由于切换状态需要与硬件、网络交互。耗时长,所以内部使用AsyncTask进行异步切换

3、widget如何感知外部状态的变化

当用户在设置里面更改了Wifi、BT等状态,widget如何能及时知道,并修改按钮的图片

当外部状态变化时,widget的onReceive将收到消息,如果该部件不是通过broadcast来发送消息的,那么就注册一个Observer来监视该部件的变化(如亮度按钮)

根据intent识别是哪个部件发生变化

String action =intent.getAction();

if(WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {

sWifiState.onActualStateChange(context,intent);

} else if(BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {

sBluetoothState.onActualStateChange(context, intent);

}

………………..

updateWidget(context);

子类调用onActualStateChange,由于是外部发生变化,子类不需要其他操作,所以onActualStateChange实现没做什么事情。

updateWidget(context);内部调用buildUpdate来更新按钮状态


更多相关文章

  1. 【Android基础】Activity的启动模式(android:launchMode) .
  2. Android(安卓)初体验
  3. 自定义Android的Dialog
  4. Android网络连接网络
  5. Android(安卓)Accessibility : TalkBack的状态读取
  6. 屏幕元素的层次
  7. android百度地图
  8. android 仿照ihone开关
  9. Android(安卓)CheckBox实现SwitchButton

随机推荐

  1. Android——java.lang.UnsatisfiedLinkEr
  2. Android 中Activity 之间传递参数
  3. Android 调用camera2 人脸识别api
  4. Android TabHost 文字及图片的设置
  5. Android仿微信5实现滑动导航条
  6. Android:手机信息的发送
  7. Android 一个程序A启动程序B
  8. 如何获取Android IP地址
  9. Bugly对应用进行升级
  10. android点击屏幕隐藏小键盘