How to load items in android homescreen listview widget?

Torasu picture Torasu · Jan 27, 2014 · Viewed 11.5k times · Source

I am currently developing an Android project which makes use of a Homescreen Widget to display data to the user. The view that I used in the Widget is a ListView. Below are my codes:

WidgetService Class

public class WidgetService extends RemoteViewsService
{

    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent)
    {   
        return (new WidgetRemoteViewsFactory(this.getApplicationContext(), intent));
    }

}

WidgetProvider Class

public class WidgetProvider extends AppWidgetProvider
{   
    @Override
    public void onDeleted(Context context, int[] appWidgetIds)
    {
        super.onDeleted(context, appWidgetIds);
    }

    @Override
    public void onDisabled(Context context) 
    {
        super.onDisabled(context);
    }

    @Override
    public void onEnabled(Context context) 
    {
        super.onEnabled(context);
    }

    @Override
    public void onReceive(Context context, Intent intent)
    {
        super.onReceive(context, intent);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) 
    {
        for(int i=0;i<appWidgetIds.length;i++)
        {
            RemoteViews rv = new RemoteViews(context.getPackageName(),
                    R.layout.widget);

            Intent intent = new Intent(context, WidgetService.class);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    appWidgetIds[i]);
            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

            rv.setRemoteAdapter(R.id.widgetListView, intent);

            appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
        }
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
}

WidgetRemoteViewsFactory Class

public class WidgetRemoteViewsFactory implements RemoteViewsFactory
{
private Context context = null;
private int appWidgetId;

private List<String> widgetList = new ArrayList<String>();
private DBHelper dbhelper;

public WidgetRemoteViewsFactory(Context context, Intent intent)
{
    this.context = context;
    appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
    Log.d("AppWidgetId", String.valueOf(appWidgetId));
    dbhelper = new DBHelper(this.context);
}

private void updateWidgetListView()
{
    String[] widgetFruitsArray = dbhelper.retrieveFruitsList();
    List<String> convertedToList = new ArrayList<String>(Arrays.asList(widgetFruitsArray));
    this.widgetList = convertedToList;
}

@Override
public int getCount()
{
    return widgetList.size();
}

@Override
public long getItemId(int position)
{
    return position;
}

@Override
public RemoteViews getLoadingView()
{
    // TODO Auto-generated method stub
    return null;
}

@Override
public RemoteViews getViewAt(int position)
{
    Log.d("WidgetCreatingView", "WidgetCreatingView");
    RemoteViews remoteView = new RemoteViews(context.getPackageName(),
            R.layout.listview_row_item);

    Log.d("Loading", widgetList.get(position));
    remoteView.setTextViewText(R.id.listTV, widgetList.get(position));

    return remoteView;
}

@Override
public int getViewTypeCount()
{
    // TODO Auto-generated method stub
    return 0;
}

@Override
public boolean hasStableIds()
{
    // TODO Auto-generated method stub
    return false;
}

@Override
public void onCreate()
{
    // TODO Auto-generated method stub
    updateWidgetListView();
}

@Override
public void onDataSetChanged()
{
    // TODO Auto-generated method stub
    updateWidgetListView();
}

@Override
public void onDestroy()
{
    // TODO Auto-generated method stub
    widgetList.clear();
    dbhelper.close();
}
}

Android Manifest File

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.listviewwithdb"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="14"
    android:targetSdkVersion="19" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/MyTheme.Light" >

    <activity
        android:name="com.example.listviewwithdb.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <receiver android:name="com.example.listviewwithdb.WidgetProvider" >
        <intent-filter >
            <action 
                android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/widgetinfo" />
    </receiver>

    <service
        android:name="com.example.listviewwithdb.WidgetService"
        android:exported="false"
        android:permission="android.permission.BIND_REMOTEVIEWS" />

</application>

</manifest>

The problem is that I can add the widget into the homescreen, but it displays the list of item in the listview with a "Loading.." message in it, I tried logging the values at getViewAt() as shown above and it displays the content that I want successfully. Is there anything that I'm missing in my codes that is causing the issue? Thanks for the help in advance

Answer

Torasu picture Torasu · Jan 28, 2014

I have found out the issue. It turns out that I need to return the number of views, in which my case is 1, that I have in getViewTypeCount() in my WidgetRemoteViewsFactory class.