Android - Widget with Scrollable Listview Manual Refresh

11,975

You can update the ListView by using notifyAppWidgetViewDataChanged() method of AppWidgetManager. You will have to get the instance of AppWidgetManager, get the AppWidgetIds and the call appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, viewId);

Pseudo Code,

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int appWidgetIds[] = appWidgetManager.getAppWidgetIds(
                           new ComponentName(context, WidgetProvider.class));
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.listview);

When you call notifyAppWidgetViewDataChanged() then the onDataSetChanged() method of RemoteViewsFactory will be called which is serving as a Adapter for your ListView. You can do web-service stuff and other operations in onDataSetChanged(), get the response and add it to your data-set which maybe ArrayList or any such Collection.

For further readings/reference you can check Keeping Collection Data Fresh part from the docs. Also you can check a demo example from my github.

Share:
11,975
Vishal Khakhkhar
Author by

Vishal Khakhkhar

Updated on June 05, 2022

Comments

  • Vishal Khakhkhar
    Vishal Khakhkhar about 2 years

    I googled and found the code to manipulate listview data using RemoteViewsService and RemoteViewsService.RemoteViewsFactory. as below

    Intent svcIntent = new Intent(context, WidgetService.class);
    svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appWidgetIds[i]);
    svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
    RemoteViews widget = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
    widget.setRemoteAdapter(appWidgetIds[i], R.id.lstAppointments,svcIntent);
    

    WidgetService.java contains

    public class WidgetService extends RemoteViewsService {
    
        @Override
        public RemoteViewsFactory onGetViewFactory(Intent intent) {
            return (new WidgetViewsFactory(this.getApplicationContext(), intent));
        }
    
        public IBinder onBind(Intent intent) {
            // TODO Auto-generated method stub
            return super.onBind(intent);
        }
    }
    

    and wrote all the codes for fetching data from webservice in onCreate of WidgetViewsFactory implements RemoteViewsService.RemoteViewsFactory

    For updating records manually or automatically every 5seconds, I found Update via Service methods as below mentioned

    public class WordWidget extends AppWidgetProvider {
    
        static int value = 1;
        Handler handler = new Handler();
        MyRunnable myRunnable;
    
        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                int[] appWidgetIds) {
            // To prevent any ANR timeouts, we perform the update in a service
            myRunnable = new MyRunnable(context);
            handler.postDelayed(myRunnable, 1000);
        }
    
        class MyRunnable implements Runnable {
    
            Context context;
    
            public MyRunnable(Context context) {
                this.context = context;
            }
    
            public void run() {
                context.startService(new Intent(context, UpdateService.class));
                handler.postDelayed(myRunnable, 1000);
            }
        }
    
        public static class UpdateService extends Service {
            @Override
            public void onStart(Intent intent, int startId) {
                // Build the widget update for today
                RemoteViews updateViews = buildUpdate(this);
    
                // Push update for this widget to the home screen
                ComponentName thisWidget = new ComponentName(this, WordWidget.class);
                AppWidgetManager manager = AppWidgetManager.getInstance(this);
                manager.updateAppWidget(thisWidget, updateViews);
            }
    
            public RemoteViews buildUpdate(Context context) {
                RemoteViews updateViews;
    
                // Build an update that holds the updated widget contents
                updateViews = new RemoteViews(context.getPackageName(),
                        R.layout.widget_word);
    
                Log.e("value", String.valueOf(value));
                updateViews.setTextViewText(R.id.word_title, "Title");
                updateViews.setTextViewText(R.id.word_type, String.valueOf(value));
                updateViews.setTextViewText(R.id.definition, String.valueOf(value));
    
                value += 1;
    
                // When user clicks on widget it opens www.google.com
                Intent defineIntent = new Intent(Intent.ACTION_VIEW,
                        Uri.parse("https://www.google.co.in/"));
                PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                        defineIntent, 0);
                updateViews.setOnClickPendingIntent(R.id.widget, pendingIntent);
    
                return updateViews;
            }
    
            @Override
            public IBinder onBind(Intent intent) {
                // We don't need to bind to this service
                return null;
            }
        }
    }
    

    How to update the listview automatically.. I know how to update textview as mentioned above.

  • Javi Vazquez
    Javi Vazquez about 7 years
    After looking at many threads in this site and none worked for me (probably because I am using a "Collection Widget"), this one worked as a charm! Thank you very much!
  • Juan Mendez
    Juan Mendez about 7 years
    i was using sendBroadcast() which in turn was recreating each layout, and wasn't updating the listviews. Method notifyAppWidgetViewDataChanged only takes care of refreshing making it less expensive.