Update: I created a repository with less code to make it a bit easier to understand.
I'm trying to create a widget. I made it like described here: https://stackoverflow.com/a/6093753/2180161
It works partially, but I have a really strange bug. I made a screencast, so it's easier to understand what I mean: http://c.maysi.de/c6H9
As you can see there are some items which were added randomly. (RemoteViews
which were added to another RemoteViews
object)
The same happens when I resize the widget.
The things I printed out in the log are like expected. there is no wrong data. Also there are no new log entries when I scroll.
This is my code:
RemoteViewsFactory:
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MyWidgetViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private static ArrayList<Item> items = new ArrayList<>();
private static int itemnr = 0;
private static int subitemnr = 0;
private int appWidgetId;
private Context context;
public MyWidgetViewsFactory(Context context, Intent intent) {
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
//Some random data to display
for (int i = 0; i < 10; i++) {
Item item = new Item(String.valueOf(itemnr++));
for (int j = 0; j < 3; j++) {
String[] subitem = {String.valueOf(subitemnr++), String.valueOf(subitemnr++), String.valueOf(subitemnr++)};
item.addSubitem(subitem);
}
items.add(item);
}
}
@Override
public void onCreate() {
// no-op
}
@Override
public void onDestroy() {
// no-op
}
@Override
public int getCount() {
return items.size();
}
@Override
public RemoteViews getViewAt(int position) {
Log.d("MyWidgetViewsFactory", "getViewAt(" + position + "):" + items.get(position));
Item item = items.get(position);
RemoteViews itemView = new RemoteViews(context.getPackageName(), R.layout.widget_listview_item);
itemView.setTextViewText(R.id.textView_itemnr, item.getItemNr());
for (String[] s : item.getSubitems()) {
Log.d("MyWidgetViewsFactory", "subitem:" + s[0] + "|" + s[1] + "|" + s[2]);
RemoteViews subitem = new RemoteViews(context.getPackageName(), R.layout.widget_listview_subitem);
subitem.setTextViewText(R.id.textView_1, s[0]);
subitem.setTextViewText(R.id.textView_2, s[1]);
subitem.setTextViewText(R.id.textView_3, s[2]);
itemView.addView(R.id.linearLayout_item_body, subitem);
}
return itemView;
}
@Override
public RemoteViews getLoadingView() {
return (null);
}
@Override
public int getViewTypeCount() {
return (1);
}
@Override
public long getItemId(int position) {
return (position);
}
@Override
public boolean hasStableIds() {
return (true);
}
@Override
public void onDataSetChanged() {
// no-op
}
class Item {
private ArrayList<String[]> subitems = new ArrayList<>();
private String itemnr = "";
Item(String itemnr) {
this.itemnr = itemnr;
}
Item() {
}
public void addSubitem(String[] subitem) {
this.subitems.add(subitem);
}
public ArrayList<String[]> getSubitems() {
return subitems;
}
public String getItemNr() {
return itemnr;
}
public void setItemNr(String itemnr) {
this.itemnr = itemnr;
}
}
}
AppWidgetProvider
public class MyWidgetProvider extends AppWidgetProvider {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
Log.d("MyWidgetProvider", "appWidgetIds.lenght:" + appWidgetIds.length);
for (int appWidgetId : appWidgetIds) {
Intent svcIntent = new Intent(context, MyWidgetService.class);
svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget_root);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
widget.setRemoteAdapter(R.id.listView_widget, svcIntent);
else
widget.setRemoteAdapter(appWidgetId, R.id.listView_widget, svcIntent);
/*
Intent clickIntent = new Intent(context, MainActivity.class);
PendingIntent clickPI = PendingIntent.getActivity(context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
widget.setPendingIntentTemplate(R.id.listView_widget, clickPI);*/
appWidgetManager.updateAppWidget(appWidgetId, widget);
}
}
@Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
@Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
}
RemoteViewsService
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MyWidgetService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return (new MyWidgetViewsFactory(this.getApplicationContext(), intent));
}
}
all other resources can you find in the repo at GitHub.
Logcat output:
08-08 02:11:10.858 32427-32444/? D/MyWidgetViewsFactory﹕ getViewAt(0):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@3e7179c9
08-08 02:11:10.860 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:0|1|2
08-08 02:11:10.864 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:3|4|5
08-08 02:11:10.866 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:6|7|8
08-08 02:11:10.927 32427-32443/? D/MyWidgetViewsFactory﹕ getViewAt(0):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@3e7179c9
08-08 02:11:10.927 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:0|1|2
08-08 02:11:10.927 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:3|4|5
08-08 02:11:10.927 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:6|7|8
08-08 02:11:10.931 32427-32443/? D/MyWidgetViewsFactory﹕ getViewAt(1):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@23e248ce
08-08 02:11:10.931 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:9|10|11
08-08 02:11:10.931 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:12|13|14
08-08 02:11:10.931 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:15|16|17
08-08 02:11:10.933 32427-32443/? D/MyWidgetViewsFactory﹕ getViewAt(2):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@16dbf3ef
08-08 02:11:10.933 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:18|19|20
08-08 02:11:10.933 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:21|22|23
08-08 02:11:10.933 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:24|25|26
08-08 02:11:10.936 32427-32443/? D/MyWidgetViewsFactory﹕ getViewAt(3):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@19d3defc
08-08 02:11:10.936 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:27|28|29
08-08 02:11:10.936 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:30|31|32
08-08 02:11:10.936 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:33|34|35
08-08 02:11:10.938 32427-32443/? D/MyWidgetViewsFactory﹕ getViewAt(4):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@ee985
08-08 02:11:10.938 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:36|37|38
08-08 02:11:10.938 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:39|40|41
08-08 02:11:10.938 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:42|43|44
08-08 02:11:10.941 32427-32443/? D/MyWidgetViewsFactory﹕ getViewAt(8):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@335e23da
08-08 02:11:10.941 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:72|73|74
08-08 02:11:10.941 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:75|76|77
08-08 02:11:10.941 32427-32443/? D/MyWidgetViewsFactory﹕ subitem:78|79|80
08-08 02:11:10.943 32427-32447/? D/MyWidgetViewsFactory﹕ getViewAt(9):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@229de00b
08-08 02:11:10.943 32427-32447/? D/MyWidgetViewsFactory﹕ subitem:81|82|83
08-08 02:11:10.943 32427-32447/? D/MyWidgetViewsFactory﹕ subitem:84|85|86
08-08 02:11:10.943 32427-32447/? D/MyWidgetViewsFactory﹕ subitem:87|88|89
08-08 02:11:10.945 32427-32444/? D/MyWidgetViewsFactory﹕ getViewAt(5):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@2afdeee8
08-08 02:11:10.945 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:45|46|47
08-08 02:11:10.945 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:48|49|50
08-08 02:11:10.945 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:51|52|53
08-08 02:11:10.948 32427-32444/? D/MyWidgetViewsFactory﹕ getViewAt(7):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@1c599901
08-08 02:11:10.948 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:63|64|65
08-08 02:11:10.948 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:66|67|68
08-08 02:11:10.948 32427-32444/? D/MyWidgetViewsFactory﹕ subitem:69|70|71
08-08 02:11:10.951 32427-32447/? D/MyWidgetViewsFactory﹕ getViewAt(6):de.mayerhofersimon.listviewproblem.MyWidgetViewsFactory$Item@368aa3a6
08-08 02:11:10.951 32427-32447/? D/MyWidgetViewsFactory﹕ subitem:54|55|56
08-08 02:11:10.951 32427-32447/? D/MyWidgetViewsFactory﹕ subitem:57|58|59
08-08 02:11:10.951 32427-32447/? D/MyWidgetViewsFactory﹕ subitem:60|61|62
So the data gets passed correct. it just doesn't get correct displayed...
BTW: this is what it should look like: http://c.maysi.de/cB8K
Could it be, that the problem is because of nested remoteviews? because all the outer remoteviews are displayed correct...
I found the answer myself.
To fix the problem with the weird adding of views on scrolling and resizing you have to call removeAllViews
on the Layout where the subviews were added:
@Override
public RemoteViews getViewAt(int position) {
...
RemoteViews itemView = new RemoteViews(context.getPackageName(), R.layout.widget_listview_item);
itemView.removeAllViews(R.id.linearLayout_item_body);
...
return itemView;
}
And the problem that the views are not displayed is because of the color: After adding
subitem.setTextColor(R.id.textView_1, context.getResources().getColor(R.color.abc_primary_text_material_light));
subitem.setTextColor(R.id.textView_2, context.getResources().getColor(R.color.abc_primary_text_material_light));
subitem.setTextColor(R.id.textView_3, context.getResources().getColor(R.color.abc_primary_text_material_light));
all views are displayed: