【本文正在参与“有奖征文 | HarmonyOS征文大赛”活动】
活动链接:https://marketing.csdn.net/p/ad3879b53f4b8b31db27382b5fc65bbc
目录
本文主要阐述的内容有:
1、原子化卡片的创建
2、卡片的数据填充
3、数据更新
首先,先看下效果图:
HarmonyOS实时天气卡片
一、创建卡片服务
创建卡片之前先新建一个项目,这个就不在累赘的介绍了。点这里
右键entry新建选择service widget,如下图:
next,下图:
Finish完成,生成的项目目录如下红色表示在原有基础上新增的文件
这样我们的卡片服务就创建完成了。
二、卡片数据填充
找到MainAbiliity,里面新增了一写方法,onCreateForm为卡片创建的方法,onUpdateForm为卡片更新的方法,onDeleteForm为卡片删除的方法。
我们的config.json中新增了卡片的标签具体含义请查看:卡片服务
在onCreateFrorm中需要根据intent传递的参数获取对应的布局,比如1*2、2*2的布局,并为其设置数据。
流程如下图:
MainAbility代码如下:
public class MainAbility extends Ability {
public static final int DEFAULT_DIMENSION_2X2 = 2;
public static final int DEFAULT_DIMENSION_2X4 = 3;
private static final int INVALID_FORM_ID = -1;
private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, MainAbility.class.getName());
private String topWidgetSlice;
private long formId;
private ProviderFormInfo formInfo;
private DatabaseHelper helper = new DatabaseHelper(this);
private OrmContext connect;
private static final String EMPTY_STRING = "";
private OrmContext weatherConnect;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
connect = helper.getOrmContext("Database", "CardDatabase.db", CardDatabase.class);
weatherConnect=helper.getOrmContext("weather","WeatherDatabase.db", WeatherDataBase.class);
}
@Override
protected ProviderFormInfo onCreateForm(Intent intent) {
if (intent == null) {
return new ProviderFormInfo();
}
HiLog.info(TAG, "onCreateForm");
// 获取卡片id
formId = INVALID_FORM_ID;
if (intent.hasParameter(AbilitySlice.PARAM_FORM_IDENTITY_KEY)) {
formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);
} else {
return new ProviderFormInfo();
}
// 获取卡片名称
String formName = EMPTY_STRING;
if (intent.hasParameter(AbilitySlice.PARAM_FORM_NAME_KEY)) {
formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);
}
// 获取卡片规格
int dimension = DEFAULT_DIMENSION_2X2;
if (intent.hasParameter(AbilitySlice.PARAM_FORM_DIMENSION_KEY)) {
dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X2);
}
int layoutId = ResourceTable.Layout_form_image_with_information_widget_2_2;
HiLog.info(TAG, "dimension:" + dimension);
if (dimension == DEFAULT_DIMENSION_2X4) {
layoutId = ResourceTable.Layout_form_image_with_information_widget_2_4;
}
formInfo = new ProviderFormInfo(layoutId, this);
// 存储卡片信息
Card form = new Card(formId, formName, dimension);
if (weatherConnect==null){
weatherConnect=helper.getOrmContext("weather","WeatherDatabase.db", WeatherDataBase.class);
}
ComponentProvider componentProvider = ComponentProviderUtils.getComponentProvider(form, weatherConnect,getApplicationContext());
//componentProvider.setIntentAgent()
formInfo.mergeActions(componentProvider);
if (connect == null) {
connect =
helper.getOrmContext("Database", "CardDatabase.db", CardDatabase.class);
}
try {
DatabaseUtils.insertForm(form, connect);
} catch (Exception e) {
DatabaseUtils.deleteFormData(form.getFormId(), connect);
}
return formInfo;
}
@Override
protected void onDeleteForm(long formId) {
super.onDeleteForm(formId);
// 删除数据库中的卡片信息
DatabaseUtils.deleteFormData(formId, connect);
}
@Override
protected void onUpdateForm(long formId) {
super.onUpdateForm(formId);
}
}
因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息。且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID,因此若卡片提供方支持对卡片数据进行配置,则需要提供方对卡片的业务数据按照卡片ID进行持久化管理,以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据。
三、更新数据
在MainAbilitySlice中我选用了RadioContainer内含两个RadioButton实现单选,根据选择的城市获取对应城市的实时温度。获取到数据之后,根据数据库存储的卡片信息遍历更新所有卡片。
MainAbilitySlice代码如下:
public class MainAbilitySlice extends AbilitySlice {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00202, "MainAbilitySlice");
private RadioContainer mRadioContainer;
private OrmContext connect, weatherConnect;
private RadioButton mXiAn, mShangHai;
private Text mWeatherText;
private DatabaseHelper helper = new DatabaseHelper(this);
private NetWorkUtils netWorkUtils;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
mRadioContainer = (RadioContainer) findComponentById(ResourceTable.Id_radio_container);
mXiAn = (RadioButton) findComponentById(ResourceTable.Id_xi_an);
mShangHai = (RadioButton) findComponentById(ResourceTable.Id_shang_hai);
mWeatherText = (Text) findComponentById(ResourceTable.Id_weather_text);
connect = helper.getOrmContext("Database", "CardDatabase.db", CardDatabase.class);
weatherConnect = helper.getOrmContext("weather", "WeatherDatabase.db", WeatherDataBase.class);
netWorkUtils = NetWorkUtils.getInstance(getContext());
mRadioContainer.setMarkChangedListener(new RadioContainer.CheckedStateChangedListener() {
@Override
public void onCheckedChanged(RadioContainer radioContainer, int i) {
HiLog.error(LABEL, "onCheckedChanged->I:%{public}s", i);
switch (i) {
case 0:
PreferencesUtils.getInstance(getApplicationContext()).putInt("City", 0);
getWeather(0);
break;
case 1:
PreferencesUtils.getInstance(getApplicationContext()).putInt("City", 1);
getWeather(1);
break;
}
}
});
init();
}
private void upDataFrom() {
OrmPredicates ormPredicates = new OrmPredicates(Card.class);
List<Card> formList = connect.query(ormPredicates);
// 更新时分秒
if (formList.size() <= 0) {
return;
}
for (Card form : formList) {
// 遍历卡片列表更新卡片
ComponentProvider componentProvider = ComponentProviderUtils.getComponentProvider(form, weatherConnect, getApplicationContext());
try {
Long updateFormId = form.getFormId();
getAbility().updateForm(updateFormId, componentProvider);
} catch (FormException e) {
// 删除不存在的卡片
DatabaseUtils.deleteFormData(form.getFormId(), connect);
HiLog.error(LABEL, "onUpdateForm updateForm error");
}
}
}
public void init() {
int city = PreferencesUtils.getInstance(getApplicationContext()).getInt("City", 0);
if (city == 0) {
mXiAn.setChecked(true);
} else {
mShangHai.setChecked(true);
}
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
private void getWeather(int city) {
String cityName;
String url;
if (city == 0) {
url = Contents.ADDRESS_URL + "西安";
cityName = "西安";
} else {
cityName = "上海";
url = Contents.ADDRESS_URL + "上海";
}
HiLog.error(LABEL, "startTimer->url:%{public}s", url);
netWorkUtils.getWeather(url);
netWorkUtils.setNetWorkListener(new NetWorkListener() {
@Override
public void onSuccess(String result) {
Weather weather = new Weather(cityName, result);
DatabaseUtils.insertWeather(weather, weatherConnect);
upDataFrom();
}
@Override
public void onFail(String msg) {
}
});
}
}
也有很多是卡片是需要实时刷新或者隔几秒刷新一次,那么我们就是使用seviceAbility写定时任务,将获取数据部分放入的service中。