notifyappwidgetviewdatachanged 无法处理我的小部件上的列表视图
notifyappwidgetviewdatachanged not working on a listview on my widget
我尝试了很多解决方案,但几周后我仍无法解决这个问题:为什么 "notifyappwidgetviewdatachanged" 不起作用?如何更新放置在我的小部件上的列表视图?我哪里错了?
这是我的类。
小部件提供商:
public class Widget_Provider extends AppWidgetProvider
{
public static final String ACTION_MOSTRAORARI = "fACTION_TOAST";
public static final String EXTRA_STRING = "EXTRA_STRING";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds)
{
RemoteViews views = updateWidgetListView(context, appWidgetId);
final Intent onItemClick = new Intent(context, Widget_Provider.class);
onItemClick.setAction(ACTION_MOSTRAORARI);
onItemClick.setData(Uri.parse(onItemClick.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(context, 0, onItemClick, PendingIntent.FLAG_UPDATE_CURRENT);
views.setPendingIntentTemplate(R.id.myStopList, onClickPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public RemoteViews updateWidgetListView(Context context, int appWidgetId)
{
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent svcIntent = new Intent(context, Widget_Service.class);
svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
remoteViews.setRemoteAdapter(R.id.myStopList, svcIntent);
return remoteViews;
}
@Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(ACTION_MOSTRAORARI)) {
if (MainUtils.isNewtworkAvailable(context))
{
String item = intent.getExtras().getString(EXTRA_STRING);
Intent intentOrari = new Intent(context, Diag_MostraOrari.class);
intentOrari.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intentOrari);
}
}
super.onReceive(context, intent);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {}
@Override
public void onEnabled(Context context) {}
@Override
public void onDisabled(Context context) {}
}
小部件服务:
public class Widget_Service extends RemoteViewsService
{
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent)
{
Map<String, ArrayList<String>> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
/* ---
* Here i fetch data from a local db and store it on "map"
*/ ---
return (new Widget_ListProvider(this.getApplicationContext(), intent, map));
}
}
列表提供者:
public class Widget_ListProvider implements RemoteViewsFactory
{
private Map<String, ArrayList<String>> map = new HashMap<>();
private ArrayList<ListItem_Widget> listItemList = new ArrayList<>();
private Context context = null;
private int appWidgetId;
public Widget_ListProvider(Context context, Intent intent, Map<String, ArrayList<String>> map)
{
this.map = map;
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
populateListItem();
}
//This function populate the arraylist "listItemList" by the data stored on "map"
private void populateListItem() { [...] }
@Override
public int getCount() {
return listItemList.size();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public RemoteViews getViewAt(int position)
{
final RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.listitem_widget);
ListItem_Widget listItem = listItemList.get(position);
remoteView.setTextViewText(R.id.heading, listItem.heading);
remoteView.setTextViewText(R.id.content, listItem.content);
final Intent fillInIntent = new Intent();
fillInIntent.setAction(Widget.ACTION_MOSTRAORARI);
final Bundle bundle = new Bundle();
bundle.putString(Widget.EXTRA_STRING, listItem.heading);
fillInIntent.putExtras(bundle);
remoteView.setOnClickFillInIntent(R.id.listrow, fillInIntent);
return remoteView;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public void onCreate() {}
@Override
public void onDataSetChanged() {}
@Override
public void onDestroy() {}
}
我的列表视图自定义项的 xml 仅包含两个文本视图:"heading" 和 "content"。
我哪里错了?为什么当我从另一个 activity 呼叫 "notifyappwidgetviewdatachanged" 时没有任何反应?
[编辑]
这是我需要更新小部件的 activity。
public class Diag_Line extends AppCompatActivity
{
//[...]
@Override
protected void onCreate(Bundle savedInstanceState)
{
//[...]
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
ComponentName thisAppWidget = new ComponentName(getApplicationContext().getPackageName(), Widget.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myStopList);
//"myStopList" is the id of my listview inside the widget xml.
//[...]
}
}
好吧,问题很明显:在您的 RemoteViewsFactory 中,您有一个空方法 onDataSetChanged()
。但是当你触发 notifyAppWidgetViewDataChanged()
时,你会在 onDataSetChanged()
中收到回调。为了更好地理解检查这张照片。
如果 Diag_Line 是一个配置 Activity 就做这样的事情:
appWidgetManager.updateAppWidget(appWidgetIds, views); // views is a RemoteViews that you need to build
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myStopList);
同时查看官方文档here
更新
给你一些提示。如果您正在使用小部件,请在后台进行所有获取数据和填充 RemoteViews(IntentService 是一种不错的方法)。所以只需在这里制作 IntentService 并为小部件制作逻辑。如果您通过广播触发更新,请不要忘记将他设置为前景(仅适用于 Android O)。您也可以查看 library 是否适合您。
为了让notifyAppWidgetViewDataChanged()正常工作
我们需要在 RemoteViewSourceFactory 的 onDataSetChanged() 方法中获取数据
像这样:
override fun onDataSetChanged() {
listOfArticles = newsDatabaseRepo.getSynchronouslySavedNews() as ArrayList<Articles>
}
如 here
中所建议
并且有一种方法可以在发生更改时刷新小部件:
private fun refreshWidget() {
val appWidgetManager =
AppWidgetManager.getInstance(applicationContext)
val thisAppWidget = ComponentName(
applicationContext.packageName,
MyAppWidgetProvider::class.java.name
)
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.stack_view)
}
调用上述方法后,一旦我退出我的应用程序,我就能注意到我的小部件的变化
所以为了检查onDataSetChanged是否在notifyAppWidgetViewDataChanged()之后被调用
我保留了一个调试点并调用了 onDataSetChanged() 并按照此处 here
中的建议更新了列表
我尝试了很多解决方案,但几周后我仍无法解决这个问题:为什么 "notifyappwidgetviewdatachanged" 不起作用?如何更新放置在我的小部件上的列表视图?我哪里错了?
这是我的类。
小部件提供商:
public class Widget_Provider extends AppWidgetProvider
{
public static final String ACTION_MOSTRAORARI = "fACTION_TOAST";
public static final String EXTRA_STRING = "EXTRA_STRING";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds)
{
RemoteViews views = updateWidgetListView(context, appWidgetId);
final Intent onItemClick = new Intent(context, Widget_Provider.class);
onItemClick.setAction(ACTION_MOSTRAORARI);
onItemClick.setData(Uri.parse(onItemClick.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(context, 0, onItemClick, PendingIntent.FLAG_UPDATE_CURRENT);
views.setPendingIntentTemplate(R.id.myStopList, onClickPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public RemoteViews updateWidgetListView(Context context, int appWidgetId)
{
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent svcIntent = new Intent(context, Widget_Service.class);
svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
remoteViews.setRemoteAdapter(R.id.myStopList, svcIntent);
return remoteViews;
}
@Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(ACTION_MOSTRAORARI)) {
if (MainUtils.isNewtworkAvailable(context))
{
String item = intent.getExtras().getString(EXTRA_STRING);
Intent intentOrari = new Intent(context, Diag_MostraOrari.class);
intentOrari.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intentOrari);
}
}
super.onReceive(context, intent);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {}
@Override
public void onEnabled(Context context) {}
@Override
public void onDisabled(Context context) {}
}
小部件服务:
public class Widget_Service extends RemoteViewsService
{
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent)
{
Map<String, ArrayList<String>> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
/* ---
* Here i fetch data from a local db and store it on "map"
*/ ---
return (new Widget_ListProvider(this.getApplicationContext(), intent, map));
}
}
列表提供者:
public class Widget_ListProvider implements RemoteViewsFactory
{
private Map<String, ArrayList<String>> map = new HashMap<>();
private ArrayList<ListItem_Widget> listItemList = new ArrayList<>();
private Context context = null;
private int appWidgetId;
public Widget_ListProvider(Context context, Intent intent, Map<String, ArrayList<String>> map)
{
this.map = map;
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
populateListItem();
}
//This function populate the arraylist "listItemList" by the data stored on "map"
private void populateListItem() { [...] }
@Override
public int getCount() {
return listItemList.size();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public RemoteViews getViewAt(int position)
{
final RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.listitem_widget);
ListItem_Widget listItem = listItemList.get(position);
remoteView.setTextViewText(R.id.heading, listItem.heading);
remoteView.setTextViewText(R.id.content, listItem.content);
final Intent fillInIntent = new Intent();
fillInIntent.setAction(Widget.ACTION_MOSTRAORARI);
final Bundle bundle = new Bundle();
bundle.putString(Widget.EXTRA_STRING, listItem.heading);
fillInIntent.putExtras(bundle);
remoteView.setOnClickFillInIntent(R.id.listrow, fillInIntent);
return remoteView;
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public void onCreate() {}
@Override
public void onDataSetChanged() {}
@Override
public void onDestroy() {}
}
我的列表视图自定义项的 xml 仅包含两个文本视图:"heading" 和 "content"。
我哪里错了?为什么当我从另一个 activity 呼叫 "notifyappwidgetviewdatachanged" 时没有任何反应?
[编辑]
这是我需要更新小部件的 activity。
public class Diag_Line extends AppCompatActivity
{
//[...]
@Override
protected void onCreate(Bundle savedInstanceState)
{
//[...]
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
ComponentName thisAppWidget = new ComponentName(getApplicationContext().getPackageName(), Widget.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myStopList);
//"myStopList" is the id of my listview inside the widget xml.
//[...]
}
}
好吧,问题很明显:在您的 RemoteViewsFactory 中,您有一个空方法 onDataSetChanged()
。但是当你触发 notifyAppWidgetViewDataChanged()
时,你会在 onDataSetChanged()
中收到回调。为了更好地理解检查这张照片。
如果 Diag_Line 是一个配置 Activity 就做这样的事情:
appWidgetManager.updateAppWidget(appWidgetIds, views); // views is a RemoteViews that you need to build
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.myStopList);
同时查看官方文档here
更新 给你一些提示。如果您正在使用小部件,请在后台进行所有获取数据和填充 RemoteViews(IntentService 是一种不错的方法)。所以只需在这里制作 IntentService 并为小部件制作逻辑。如果您通过广播触发更新,请不要忘记将他设置为前景(仅适用于 Android O)。您也可以查看 library 是否适合您。
为了让notifyAppWidgetViewDataChanged()正常工作
我们需要在 RemoteViewSourceFactory 的 onDataSetChanged() 方法中获取数据 像这样:
override fun onDataSetChanged() {
listOfArticles = newsDatabaseRepo.getSynchronouslySavedNews() as ArrayList<Articles>
}
如 here
中所建议并且有一种方法可以在发生更改时刷新小部件:
private fun refreshWidget() {
val appWidgetManager =
AppWidgetManager.getInstance(applicationContext)
val thisAppWidget = ComponentName(
applicationContext.packageName,
MyAppWidgetProvider::class.java.name
)
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.stack_view)
}
调用上述方法后,一旦我退出我的应用程序,我就能注意到我的小部件的变化
所以为了检查onDataSetChanged是否在notifyAppWidgetViewDataChanged()之后被调用 我保留了一个调试点并调用了 onDataSetChanged() 并按照此处 here
中的建议更新了列表