什么是AppWidgetProvider和RemoteViewsService.RemoteViewsFactory之间共享数据的正确方法 [英] What is the correct way for sharing data among AppWidgetProvider and RemoteViewsService.RemoteViewsFactory

查看:400
本文介绍了什么是AppWidgetProvider和RemoteViewsService.RemoteViewsFactory之间共享数据的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我的 AppWidgetProvider 是有一个静态数据。它是用于信息传递左右 AppWidgetProvider &安培; RemoteViewsService.RemoteViewsFactory

Currently, my AppWidgetProvider is having a static data. It is used for information passing around AppWidgetProvider & RemoteViewsService.RemoteViewsFactory

public class MyAppWidgetProvider extends AppWidgetProvider {
    // Key will be widget id
    private static Map<Integer, Holder> holderMap = new java.util.concurrent.ConcurrentHashMap<Integer, Holder>();

    public static int getClickedColumn(int appWidgetId) {
        Holder holder = holderMap.get(appWidgetId);  
        if (holder == null) {
            return -1;
        }
        return holder.clickedColumn;
    }


public class AppWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
    @Override
    public void onDataSetChanged() {
        int clickedColumn = MyAppWidgetProvider.getClickedColumn(mAppWidgetId);

调用 AppWidgetProvider 的静态方法在大多数情况正常工作。

Calling AppWidgetProvider's static method works fine in most of the situation.

不过,有时候,如果我把小部件的主屏幕,让它在那里几个小时。当我回来的scoll 的ListView ,我可能会收到以下错误随机。

However, sometimes, if I place the widget to home screen, let it be there for few hours. When I come back and scoll the ListView, I might get the following error randomly.

java.lang.ExceptionInInitializerError
    at org.yccheok.project.gui.widget.AppWidgetRemoteViewsFactory.onDataSetChanged(AppWidgetRemoteViewsService.java:390)
    at android.widget.RemoteViewsService$RemoteViewsFactoryAdapter.onDataSetChanged(RemoteViewsService.java:142)
    at com.android.internal.widget.IRemoteViewsFactory$Stub.onTransact(IRemoteViewsFactory.java:49)
    at android.os.Binder.execTransact(Binder.java:367)
    at dalvik.system.NativeStart.run(Native Method)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
    at android.os.Handler.<init>(Handler.java:121)
    at org.yccheok.project.gui.widget.MyAppWidgetProvider.<clinit>(MyAppWidgetProvider.java:564)

&LT; clinit&GT; ,我怀疑 MyAppWidgetProvider 是由操作系统被破坏?这个原因 AppWidgetRemoteViewsFactory 要执行类的初始化,调用静态函数之前?

From <clinit>, I suspect MyAppWidgetProvider is destroyed by OS? This cause AppWidgetRemoteViewsFactory wants to perform class initialization, before calling the static function?

这是否意味着, MyAppWidgetProvider ,可以在任何时候通过OS破坏,我们不应该把股票能静态数据的呢?

Does this mean, MyAppWidgetProvider can be destroyed anytime by OS, and we shouldn't place share-able static data in it?

如果是这样,什么是中 AppWidgetProvider 共享数据的正确方法和 RemoteViewsService.RemoteViewsFactory ? (除了使用文件或共享preferences)

If so, what is the correct way for sharing data among AppWidgetProvider and RemoteViewsService.RemoteViewsFactory? (Besides using File, or SharedPreferences)

推荐答案

RemoteViewsFactory - > AppWidgetProvider

从RemoteViewsFactory到AppWidgetProvider通信可以做到使用广播,例如像这样的:

The communication from the RemoteViewsFactory to the AppWidgetProvider can be done using Broadcasts, e.g. like this:

Intent intent = new Intent(ACTION_PROGRESS_OFF);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);

在AppWidgetProvider接收像这样的事件:

The AppWidgetProvider receives the event like so:

@Override
public void onReceive(final Context context, final Intent intent) {

    // here goes the check if the app widget id is ours

    final String action = intent.getAction();
    if (ACTION_PROGRESS_OFF.equals(action)) {
        // turn off the refresh spinner

当然广播动作需要在清单中定义:

Of course the broadcast action needs to be defined in the manifest:

<receiver
    android:name="...">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        <action android:name="myPackage.ACTION_PROGRESS_OFF" />
    </intent-filter>
    <meta-data ... />
</receiver>


AppWidgetProvider - > RemoteViewsFactory

与RemoteViewsFactory交流(和你的情况可能是最好的一种)的一种方法是发送信息,你传递给RemoteViewsAdapter服务的意图:

One way to communicate with the RemoteViewsFactory (and in your case probably the best one) is to send the information in the intent of the service you're passing to the RemoteViewsAdapter:

Intent intentRVService = new Intent(context, RemoteViewsService.class);
intentRVService.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

// let's put in some extra information we want to pass to the RemoteViewsFactory
intentRVService.putExtra("HELLO", "WORLD");

// when intents are compared, the extras are ignored, so we need to
// embed the extras into the data so that the extras will not be ignored
intentRVService.setData(Uri.parse(intentRVService.toUri(Intent.URI_INTENT_SCHEME)));

rv.setRemoteAdapter(appWidgetId, R.id.my_list, intentRVService);
rv.setEmptyView(R.id.my_list, android.R.id.empty);

// create the pending intent template for individual list items
...
rv.setPendingIntentTemplate(R.id.my_list, pendingIntentTemplate);

appWidgetMgr.notifyAppWidgetViewDataChanged(appWidgetId, R.id.my_list);

该RemoteViewsService可以很容易地检索意图的信息并将其传递给RemoteViewsService.RemoteViewsFactory。

The RemoteViewsService can easily retrieve the information from the intent and pass it along to the RemoteViewsService.RemoteViewsFactory.

我不是100%肯定,当你的小部件决定如何对数据进行排序,但如果用户选择一个列进行排序,那么你必须去通过与notifyAppWidgetViewDataChanged更新周期,然后你会通过我会承担列沿着。如果以后需要的话这些信息你就必须以某种方式存储的信息(共享preferences)。

I'm not 100% sure when and how your widget decides to sort the data but I'd assume if the user picks a column to sort then you have to go through the update cycle with notifyAppWidgetViewDataChanged and then you would pass that column along. If you need that information later on then you'd have to store the information somehow (SharedPreferences).

这篇关于什么是AppWidgetProvider和RemoteViewsService.RemoteViewsFactory之间共享数据的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆