代码之家  ›  专栏  ›  技术社区  ›  Adrian Le Roy Devezin

不显示数据列表的小部件

  •  1
  • Adrian Le Roy Devezin  · 技术社区  · 6 年前

    我有一个小部件,它应该显示一个信息列表。然而,在研究了大量教程和文档之后,我无法理解为什么它没有显示列表。它将始终显示空视图。从未调用过widgetservice.java类。

    我的代码可以在Github上找到 here :

    RecipeWidgetProvider.java

    public class RecipeWidgetProvider extends AppWidgetProvider {
    
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
    
    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) {
        SharedPreferences preferences = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
        long recipeId = preferences.getLong(WidgetConfigurationActivity.PREF_PREFIX_KEY+appWidgetId, 0);
        Intent serviceIntent = new Intent(context, WidgetService.class);
        serviceIntent.putExtra(WidgetService.EXTRA_RECIPE_ID, recipeId);
        serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
        Intent intent = new Intent(context, RecipeListActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    
    
        RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget_recipes);
        widget.setRemoteAdapter(appWidgetId, R.id.widget_configuration_list_view, serviceIntent);
        widget.setEmptyView(R.id.widget_recipe_list_view, R.id.empty_view);
        widget.setOnClickPendingIntent(R.id.widget_container, pendingIntent);
    
        //appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_recipe_list_view);
        appWidgetManager.updateAppWidget(appWidgetId, widget);
    }
    }
    

    小部件服务.java

    public class WidgetService extends RemoteViewsService {
        public static String EXTRA_RECIPE_ID = "recipeId";
    
        @Override
        public RemoteViewsFactory onGetViewFactory(Intent intent) {
            int recipeId = intent.getIntExtra(EXTRA_RECIPE_ID, -1);
            return new WidgetViewFactory(getApplicationContext(), recipeId);
        }
    }
    

    小部件视图工厂.java

    public class WidgetViewFactory implements RemoteViewsService.RemoteViewsFactory {
        private Context context;
        private long recipeId;
        private ArrayList<IngredientEntity> ingredients = new ArrayList<>();
    
        public WidgetViewFactory(Context context, long recipeId) {
            this.context = context;
            this.recipeId = recipeId;
            RecipeLocalSource source = RecipeLocalSource.getInstance(context);
            RecipeEntity recipe = source.getRecipe(recipeId);
            if (recipe != null) {
                ingredients.addAll(recipe.getIngredients());
            }
        }
    
        @Override
        public void onCreate() {
            Log.e("","");
        }
    
        @Override
        public void onDataSetChanged() {
            RecipeLocalSource source = RecipeLocalSource.getInstance(context);
            RecipeEntity recipe = source.getRecipe(recipeId);
            if (recipe != null) {
                ingredients.addAll(recipe.getIngredients());
            }
        }
    
        @Override
        public void onDestroy() {
            Log.e("","");
        }
    
        @Override
        public int getCount() {
            Log.d("","");
            return ingredients.size();
        }
    
        @Override
        public RemoteViews getViewAt(int position) {
            final IngredientEntity ingredient = ingredients.get(position);
            RemoteViews row = new RemoteViews(context.getPackageName(),
                    R.layout.item_widget_ingredient);
    
            row.setTextViewText(R.id.item_widget_ingredient_name, ingredient.getIngredient());
            row.setTextViewText(R.id.item_widget_ingredient_quantity_measure, String.format("%s %s", ingredient.getQuantity(), ingredient.getMeasure()));
            return row;
        }
    
        @Override
        public RemoteViews getLoadingView() {
            return null;
        }
    
        @Override
        public int getViewTypeCount() {
            return 1;
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public boolean hasStableIds() {
            return true;
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Elletlar FireTr3e    6 年前

    这个方法的问题是:

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId) {
        SharedPreferences preferences = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
        long recipeId = preferences.getLong(WidgetConfigurationActivity.PREF_PREFIX_KEY+appWidgetId, 0);
        Intent serviceIntent = new Intent(context, WidgetService.class);
        serviceIntent.putExtra(WidgetService.EXTRA_RECIPE_ID, recipeId);
        serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
        Intent intent = new Intent(context, RecipeListActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    
    
        RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget_recipes);
        widget.setRemoteAdapter(appWidgetId, R.id.widget_configuration_list_view, serviceIntent);
        widget.setEmptyView(R.id.widget_recipe_list_view, R.id.empty_view);
        widget.setOnClickPendingIntent(R.id.widget_container, pendingIntent);
    
        //appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_recipe_list_view);
        appWidgetManager.updateAppWidget(appWidgetId, widget);
    }
    

    在线:

    widget.setremoteadapter(应用程序widgetid, r.id.widget_configuration_list_view,serviceintent);

    这是错误的列表视图,R.ID全局名称空间很容易出错。应该是:

    widget.setremoteadapter(r.id.widget_recipe_list_view,serviceintent);

    这是小部件中远程视图中的ListView。

    还要注意,我将“setremoteadapter”更改为使用不推荐使用的其他版本。

    一旦进行了此更改,就会在widgetService中调用ongetViewFactory。但是,这会导致数据库崩溃:

    java.lang.RuntimeException: Unable to bind to service intellidev.co.bakingapp.widget.WidgetService@15361cf with Intent { dat=intent: cmp=intellidev.co.bakingapp/.widget.WidgetService (has extras) }: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
        at android.app.ActivityThread.handleBindService(ActivityThread.java:3538)
        at android.app.ActivityThread.-wrap2(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1758)
        at android.os.Handler.dispatchMessage(Handler.java:108)
        at android.os.Looper.loop(Looper.java:206)
        at android.app.ActivityThread.main(ActivityThread.java:6749)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:845)
     Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
        at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:204)
        at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:232)
        at intellidev.co.bakingapp.data.daos.RecipeDao_Impl.getRecipe(RecipeDao_Impl.java:129)
        at intellidev.co.bakingapp.data.sources.RecipeLocalSource.getRecipe(RecipeLocalSource.java:47)
        at intellidev.co.bakingapp.widget.WidgetViewFactory.<init>(WidgetViewFactory.java:24)
        at intellidev.co.bakingapp.widget.WidgetService.onGetViewFactory(WidgetService.java:12)
        at android.widget.RemoteViewsService.onBind(RemoteViewsService.java:241)
        at android.app.ActivityThread.handleBindService(ActivityThread.java:3524)
        at android.app.ActivityThread.-wrap2(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1758) 
        at android.os.Handler.dispatchMessage(Handler.java:108) 
        at android.os.Looper.loop(Looper.java:206) 
        at android.app.ActivityThread.main(ActivityThread.java:6749) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:845) 
    

    但是我会把这个留给你,因为我认为既然远程查看工厂正在被调用,你已经准备好取得更多的进展了。干杯!