Android-виджет отображает только один элемент из БД - PullRequest
0 голосов
/ 12 февраля 2012

Чувак,

мой виджет Android отображает только одну запись из моей базы данных.Я уверен, что из базы данных извлечено более одного элемента.

Метод onUpdate WidgetProvider:

public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {
    super.onUpdate(context, appWidgetManager, appWidgetIds);

    if (items == null) {
        items = new ItemsData(new DbHelper(context));
    }

    final int N = appWidgetIds.length;

    Item[] iii = items.getItemsArray();
    Log.d(TAG, "got " + iii.length + " items from db");

    ComponentName thisWidget = new ComponentName(context, WidgetProvider.class);

    for (int i = 0; i < N; i++) {
        int appWidgetId = appWidgetIds[i];

        Log.d(TAG, "updating widget " + appWidgetId);

        RemoteViews rv = new RemoteViews(context.getPackageName(),
                R.layout.widgetlayout);

        for (Item item : iii) {

            Log.d(TAG, "updating item " + item.id + ", " + item.title);

            RemoteViews views = new RemoteViews(context.getPackageName(),
                    R.layout.row);
            views.setTextViewText(R.id.textViewShortName, item.title);
            views.setTextViewText(R.id.textViewDesc, item.description);
            views.setTextViewText(R.id.textViewDue, new StringBuilder()
                    .append(item.dueDate).toString());
            rv.addView(R.id.llWidget, views);
        }

        appWidgetManager.updateAppWidget(thisWidget, rv);

    }

}

И мой макет просто:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/llWidget"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:background="#ff99ff">

    <include
        android:id="@+id/row"
        layout="@layout/row" />

</LinearLayout>

с'row' - это три элемента TextView, упорядоченные в соответствии с моими потребностями.

Что происходит так: когда я добавляю элементы в обновления базы данных и виджетов, можно увидеть только последний элемент.Он расположен сверху.

Я искал руководство по виджетам для Android, переполнение стека, некоторые другие веб-сайты, учебное пособие из книги, но хотя некоторые представили подобные примеры, я не могу заставить его работать... Руководство по виджетам Google Android показывает, как использовать коллекции, но это только для 3.0+.В учебнике по Android описан виджет с элементами, добавленными в виде строк, поэтому я последовал за ним, но не смог добиться прогресса ... Люди спрашивали о получении данных из БД из виджета (например, Android: получить данные виджета из базы данных) и, насколько мне известно, не сталкивался с такой проблемой.И их решения у меня не работают.

Прямо сейчас я даже не знаю, как искать ошибку ... Странно то, что в LogCat я вижу эти строки "обновления элемента X".

Есть идеи?

ОБНОВЛЕНИЕ 1. Обновлен метод (соответствующая часть) после информации Сергея Беннера:

    Item[] iii = items.getItemsArray();
    for (int i = 0; i < N; i++) {
        int appWidgetId = appWidgetIds[i];
        RemoteViews rv = new RemoteViews(context.getPackageName(),
                R.layout.widgetlayout);
        for (Item item : iii) {
            RemoteViews views = new RemoteViews(context.getPackageName(),
                    R.layout.row);
            views.setTextViewText(R.id.textViewShortName, item.title);
            views.setTextViewText(R.id.textViewDesc, item.description);
            views.setTextViewText(R.id.textViewDue, new StringBuilder()
                    .append(item.dueDate).toString());
            rv.addView(R.id.llWidget, views);
        }

        appWidgetManager.updateAppWidget(appWidgetId, rv);
    }

ОБНОВЛЕНИЕ 2.

Файл AndroidManifest:

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

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:debuggable="true"
        android:name=".ToDoExApp" >

        <activity
            android:label="@string/app_name"
            android:name=".ListItemsActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

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


        <activity android:label="@string/titleAdd" android:name=".AddItemActivity" />

        <activity android:label="@string/titleRemindments" android:name=".RemindmentListActivity" />

        <activity android:label="@string/titleAddRemindment" android:name=".AddRemindmentActivity" />

        <activity android:label="@string/titleSetDate" android:name=".ChooseDateActivity" />

        <receiver android:name=".WidgetProvider" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                    android:resource="@xml/widgetprovider" />
        </receiver>

    </application>

</manifest>

widgetprovider.xml:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dp"
    android:minHeight="160dp"
    android:updatePeriodMillis="3000"

    android:initialLayout="@layout/widgetlayout" >

</appwidget-provider>

row.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textViewShortName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/textViewDesc"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_weight="0.80"
            android:textAppearance="?android:attr/textAppearanceSmall" />

        <TextView
            android:id="@+id/textViewDue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:textAppearance="?android:attr/textAppearanceSmall" />
    </LinearLayout>

</LinearLayout>

и обновленный метод onUpdate в начале этого поста.В WidgetProvider больше ничего нет: пустой конструктор, onEnabled только с super.onEnabled. Также: я поместил весь макет виджета и строку xmls.

ОБНОВЛЕНИЕ 3. СейчасКаждый раз, когда элемент изменяется, я запускаю этот метод:

private void updateWidget(Item item) {
    Log.d(TAG, "updateWidget(). Sending broadcast to widget.");

    Intent intent = new Intent(WidgetProvider.UPDATE);
    intent.putExtra(WidgetProvider.UPDATE_ITEM, item.id);
    sendBroadcast(intent);
}

onReceived моего виджета теперь выглядит так:

public void onReceive(Context context, Intent intent) {

    if (intent.getAction().equals(UPDATE)) {
        Log.d(TAG, "onReceived detected new update");
        AppWidgetManager appWidgetManager = AppWidgetManager
                .getInstance(context); // 13
        this.onUpdate(context, appWidgetManager, appWidgetManager
                .getAppWidgetIds(new ComponentName(context,
                        WidgetProvider.class)),
                intent.getExtras().getLong(WidgetProvider.UPDATE_ITEM));
    } else {
        super.onReceive(context, intent);
    }
}

А специальная, модифицированная версия onUpdate выглядит так:

public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds, long itemId) {
    super.onUpdate(context, appWidgetManager, appWidgetIds);

    if (items == null) {
        items = ((ToDoExApp) ((ContextWrapper) context).getBaseContext()).itemsData;
    }

    Item item = items.getItem2(itemId);
    if (item == null) {
        Log.d(TAG, "Item with id = " + itemId + " not found.");
        return;
    }

    final int N = appWidgetIds.length;
    for (int i = 0; i < N; i++) {
        int appWidgetId = appWidgetIds[i];

        Log.d(TAG, "updating widget " + appWidgetId);

        RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.row);
        views.setTextViewText(R.id.textViewShortName, item.title);
        views.setTextViewText(R.id.textViewDesc, item.description);
        views.setTextViewText(R.id.textViewDue,
                new StringBuilder().append(item.dueDate).toString());
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

}

Теперь, когда я изменяю, добавляю элемент в базу данных, информация об этом передается на виджет.Затем он получен и обработан.Однако только этот элемент отображается в виджете.Приложение Yamba (из Learning Android) имеет нечто очень похожее - каждый раз, когда обнаруживается обновление, оно добавляется в виджет.Единственное серьезное отличие, которое я вижу, заключается в том, что Yamba использует распознаватель контента, а я использую базу данных ...

1 Ответ

0 голосов
/ 12 февраля 2012

Я использовал следующее, чтобы добавить элементы в свой виджет в качестве образца:

    for(Server srv:mylist){
      newView = new RemoteViews(context.getPackageName(), R.layout.widget_row);
      newView.setTextViewText(R.id.servername,srv.getServerName());
      newView.setTextViewText(R.id.serverstatus,srv.getServerStatus());
      remoteViews.addView(R.id.widget,newView);
    }

это в основном добавляет "строку" newView к редактированию remoteViews

:

Запуск виджета на 2.2.Конечно, виджет может быть растянут в зависимости от вашего запуска.

РЕДАКТИРОВАТЬ:

попробуйте и используйте следующее в onUpdate ()


    ComponentName thisWidget = new ComponentName(context, MyWidget.class);
    Item[] iii = items.getItemsArray();
    RemoteViews rv = new RemoteViews(context.getPackageName(),
            R.layout.widgetlayout);
    for (Item item : iii) {
        RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.row);
        views.setTextViewText(R.id.textViewShortName, item.title);
        views.setTextViewText(R.id.textViewDesc, item.description);
        views.setTextViewText(R.id.textViewDue, new StringBuilder()
                .append(item.dueDate).toString());
        rv.addView(R.id.llWidget, views);
    }

    appWidgetManager.updateAppWidget(thisWidget, rv);

Я все ещене понимаю, какой смысл в этом

        for (int i = 0; i < N; i++) {
             int appWidgetId = appWidgetIds[i];

РАБОЧЕМ ПРИМЕРЕ: вы все еще можете реализовать сервис


public class StatusWidget extends AppWidgetProvider {
     LayoutInflater  inflater;
    int[] appWidgetIds;
    AppWidgetManager appWidgetManager;
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                         int[] appWidgetIds) {
        this.appWidgetIds=appWidgetIds;
        this.appWidgetManager=appWidgetManager;
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1, 30000); //30 seconds timeout
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
            final int appWidgetId = intent.getExtras().getInt(
                                AppWidgetManager.EXTRA_APPWIDGET_ID,
                                AppWidgetManager.INVALID_APPWIDGET_ID);

            if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
                this.onDeleted(context, new int[]{appWidgetId});
            }
        } else {
            super.onReceive(context, intent);
        }
    }

    private class MyTime extends TimerTask {
        RemoteViews remoteViews;
        AppWidgetManager appWidgetManager;
        ComponentName thisWidget;
        Context context;
        public MyTime(Context context, AppWidgetManager appWidgetManager) {
            this.context = context;
            this.appWidgetManager = appWidgetManager;
            remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_message);
            thisWidget = new ComponentName(context, StatusWidget.class);
        }

        @Override
        public void run() {
            remoteViews.removeAllViews(R.id.widget);
             Date date = new Date();
            DateFormat format = SimpleDateFormat.getTimeInstance(
            SimpleDateFormat.LONG, Locale.getDefault());        
            InputStream is = null;
            ImageAdapter myServers =null;
               List<Server> mylist =null;
            try {
                is = new ByteArrayInputStream(Utils.fetch("http://mystatusserver/status", null).toByteArray());
            } catch (Exception cte) {
            }

            try {
                String l = Utils.readInputStream(is);
             List<Server> list= Utils.parseServers(l);
             mylist=   Utils.loadMyServerList(context, list);
            } catch (Exception e) {
                e.printStackTrace();
            }
             RemoteViews newView =null;
            for(Server srv:mylist){
              newView = new RemoteViews(context.getPackageName(), R.layout.widget_row);
              newView.setTextViewText(R.id.servername,srv.getServerName());
              newView.setTextViewText(R.id.serverstatus,srv.getServerStatus());
              remoteViews.addView(R.id.widget,newView);
            }
            newView = new RemoteViews(context.getPackageName(), R.layout.datetime);
            newView.setTextViewText(R.id.time,"Last Updated At: "+format.format(date));
            remoteViews.addView(R.id.widget,newView);
           appWidgetManager.updateAppWidget(thisWidget, remoteViews);

        }
    }

}

надеюсь, что это поможет abit

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...