Android Java Widget - Стратегии обновления ListViews в виджетах - PullRequest
0 голосов
/ 18 февраля 2019

Следуя онлайн-примерам, я создал виджет, который показывает данные из XML-файла.Все работает, по крайней мере, кажется :), но

1) Я помещаю соединение с БД, интернет-соединение и анализ XML в "onDataSetChanged".Нет смысла повторять соединения для каждого активного виджета, поскольку данные одинаковы.Как я могу выполнить соединение только один раз, даже если пользователь активирует несколько виджетов?

2) Поскольку я сделал / скопировал, но я все еще должен понять :), есть ли какая-либо ошибка, кроме проблемы повторных соединений?Есть ли что-нибудь, что можно было бы сделать лучше?

3) Если бы я хотел добавить кнопку для обновления того, что я должен назвать?

4) Поскольку это выполняется каждые 30 минут, это труднодля меня, чтобы контролировать его поведение.Могу ли я быть уверен, что виджет продолжит работать должным образом со временем?

Спасибо, если кто-нибудь может помочь мне разобраться.

Здесь основные файлы

манифест

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="pm48.news.testwidget">

<uses-permission android:name="android.permission.INTERNET" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

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

    <receiver android:name=".NewWidgetProvider">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

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

    <service
        android:name=".NewsWidgetService"
        android:permission="android.permission.BIND_REMOTEVIEWS"
        />

</application>
</manifest>

scroll_widget_info.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialKeyguardLayout="@layout/scroll_widget"
    android:initialLayout="@layout/scroll_widget"
    android:minWidth="250dp"
    android:minHeight="110dp"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="vertical"
    android:updatePeriodMillis="1800000"
    android:widgetCategory="home_screen"></appwidget-provider>

NewsWidgetService

public class NewsWidgetService extends RemoteViewsService {
    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new NewsRemoteViewsFactory(this.getApplicationContext(), intent);
    }
}

class NewsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {

    private List<News> mNewsItems = new ArrayList<News>();
    private Context mContext;
    private int mAppWidgetId;

    public NewsRemoteViewsFactory(Context context, Intent intent) {
        mContext = context;
        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    }

    public void onCreate() {
    }

    public void onDestroy() {
        mNewsItems.clear();
    }

    public int getCount() {
        return mNewsItems.size();
    }

    public RemoteViews getViewAt(int position) {

        RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.scroll_widget_item);

        rv.setTextViewText(R.id.widget_item, mNewsItems.get(position).getTitle());

        Bundle extras = new Bundle();
        extras.putInt(NewsWidgetProvider.EXTRA_ITEM, position);
        Intent fillInIntent = new Intent();
        fillInIntent.putExtras(extras);

        rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);

        return rv;
    }

    public RemoteViews getLoadingView() {
        return null;
    }

    public int getViewTypeCount() {
        return 1;
   }

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

    public boolean hasStableIds() {
        return true;
    }


    public void onDataSetChanged() {

        NewsRoomDatabase db = NewsRoomDatabase.getDatabase(mContext.getApplicationContext());
        NewsDao mNewsDao = db.newsDao();

        try {
            URL url = new URL("http://examples.com/xml");
            URLConnection connection = url.openConnection();
            connection.setConnectTimeout(10000);
            connection.connect();
            InputStream in = connection.getInputStream();

            List<News> new_news = parseXML(in);
            mNewsDao.deleteAll();
            for (News n : new_news) {
                mNewsDao.insert(n);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mNewsItems = mNewsDao.getAllNews();
    }


    List<News> parseXML(InputStream in) throws IOException, XmlPullParserException {
    // *** return List<News> *** 
    }
}

NewsWigetProvider

public class NewsWidgetProvider extends AppWidgetProvider {

    public static final String TOAST_ACTION = "com.example.android.stackwidget.TOAST_ACTION";
    public static final String EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM";

    @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) {

        AppWidgetManager mgr = AppWidgetManager.getInstance(context);

        if (intent.getAction().equals(TOAST_ACTION)) {
            int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
            int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);
            Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show();
        }

        super.onReceive(context, intent);
    }


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        for (int i = 0; i < appWidgetIds.length; ++i) 
            Intent intent = new Intent(context, NewsWidgetService.class);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);

            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

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

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

            rv.setEmptyView(R.id.stack_view, R.id.empty_view);

            Intent toastIntent = new Intent(context, NewsWidgetProvider.class);
            toastIntent.setAction(NewsWidgetProvider.TOAST_ACTION);
            toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);

            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

            PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);


            // !!!!!! ?????
            appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.stack_view);

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

ОТ.Разработка программного обеспечения в течение 20 лет (Python, Javascript, VB и т. Д.), И я все ближе к Android.Возможно, это первоначальное разочарование от необходимости каждый раз понимать, как что-то делать, но я не вижу адекватной абстракции.Больше, чем программирование, вам нужно знать, какой объект использовать, каковы его методы и параметры, какова логика, которая имела в виду, кто создал объект ... Какой смысл в этом?

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