重新调用remoteView而不是创建新的?

时间:2015-05-16 02:18:08

标签: android widget remoteview

我有一个Flashlight小部件在启动器重新启动后停止响应,例如在系统中更改日期时,启动器 重置在我的手机上。根据SO:Link上的这个帖子,我需要更新 remoteView ,而不是每次都创建新的。但是,我不明白如何在我的代码中实现这一点。我有一个提供者和接收者。

注意:小部件在30分钟后重新开始工作,因为这是我的小部件在 appwidget-provider XML中更新的时间。

提供者:



public class WidgetProvider extends AppWidgetProvider {
   @Override
  public void onUpdate(Context context, AppWidgetManager appWidgetManager,
    int[] appWidgetIds) {
    final int N = appWidgetIds.length;
    for (int i = 0; i < N; i++) {
      int appWidgetId = appWidgetIds[i];

      Intent receiver = new Intent(context, FlashlightWidgetReceiver.class);
      receiver.setAction("COM_FLASHLIGHT");
      receiver.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
      PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, receiver, 0);

      RemoteViews views = new RemoteViews(context.getPackageName(),
        R.layout.appwidget_layout);
      views.setOnClickPendingIntent(R.id.imageButton, pendingIntent);
      //appWidgetManager.updateAppWidget(appWidgetId, views);
      appWidgetManager.partiallyUpdateAppWidget(appWidgetId, views);
    }

  }
}
&#13;
&#13;
&#13;

接收器:

&#13;
&#13;
public class FlashlightWidgetReceiver extends BroadcastReceiver {
  private static boolean isLightOn = false;
  private static Camera camera;

  @Override
  public void onReceive(Context context, Intent intent) {
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);

    if (isLightOn) {
      views.setImageViewResource(R.id.imageButton, R.drawable.btn_switch_off);
    } else {
      views.setImageViewResource(R.id.imageButton, R.drawable.btn_switch_on);
    }

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    appWidgetManager.updateAppWidget(new ComponentName(context, WidgetProvider.class),
      views);

    if (isLightOn) {
      if (camera != null) {
        camera.stopPreview();
        camera.release();
        camera = null;
        isLightOn = false;
      }

    } else {
      // Open the default i.e. the first rear facing camera.
      camera = Camera.open();

      if (camera == null) {
        Toast.makeText(context, "No Camera!", Toast.LENGTH_SHORT).show();
      } else {
        // Set the torch flash mode
        Camera.Parameters param = camera.getParameters();
        param.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
        try {
          camera.setParameters(param);
          camera.startPreview();
          isLightOn = true;
        } catch (Exception e) {
          Toast.makeText(context, "No Camera!", Toast.LENGTH_SHORT).show();
        }
      }
    }
  }
}
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:0)

我的一个小部件出现了这个问题,我解决它的方法是存储对RemoteViews对象的静态引用。所以我添加了一个类来将每个appWidgetId与它的RemoteViews对象相关联:

public class WidgetInfo {
    int appWidgetId;
    RemoteViews view;
    boolean clickHandlersIntialized;

    public WidgetInfo(int id, RemoteViews v){
        appWidgetId = id;
        view = v;
        clickHandlersInitialized = false;
    }
}

然后在提供程序中创建了这些对象的静态列表:

private static ArrayList<WidgetInfo> widgetList = new ArrayList<WidgetInfo>();

然后在提供程序中创建此方法,给出appWidgetId将返回相应的WidgetInfo对象

public WidgetInfo getInfo(Context context, int id) {
    for (int i = 0; i < widgetList.size(); i++) {
        if (widgetList.get(i).appWidgetId == id) {
            // if there is already a WidgetInfo object in the list
            // with this id, return the object
            return widgetList.get(i);
        }
    }
    // otherwise, create a new WidgetInfo object with a new RemoteViews
    // and add it to the list
    WidgetInfo newInfo = new WidgetInfo(id, new RemoteViews(context.getPackageName(), R.layout.appwidget_layout));
    widgetList.add(newInfo);
    return newInfo;
}

然后在提供程序的onUpdate方法中,可以使用getInfo获取WidgetInfo对象,然后在现有视图成员上调用方法。例如:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
    final int N = appWidgetIds.length;
    for (int i = 0; i < N; i++) {
      int appWidgetId = appWidgetIds[i];

      WidgetInfo info = getInfo(context, appWidgetId);
      RemoteViews views = info.view; 
      // this prevents the click handlers from being initialized multiple times
      if(!info.clickHandlersInitialized){
          Intent receiver = new Intent(context, FlashlightWidgetReceiver.class);
          receiver.setAction("COM_FLASHLIGHT");
          receiver.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
          PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, receiver, 0);
          views.setOnClickPendingIntent(R.id.imageButton, pendingIntent);
          info.clickHandlersInitialized = true;
      }

      //appWidgetManager.updateAppWidget(appWidgetId, views);
      appWidgetManager.partiallyUpdateAppWidget(appWidgetId, views);
    }
}

答案 1 :(得分:0)

好吧,伙计们,我终于有时间一劳永逸地解决这个问题:)

我为提供者创建了更多方法,而不是在onUpdate中执行所有操作,这是一个重要的方法:

&#13;
&#13;
 public static PendingIntent buildButtonPendingIntent(Context context) {
   Intent intent = new Intent();
   intent.setAction("COM_FLASHLIGHT");
   return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
 }
&#13;
&#13;
&#13;

当使用下面的代码点击小部件时,通过接收器调用此方法:

&#13;
&#13;
private void turnFlash(Context context) {
  RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);
  views.setOnClickPendingIntent(R.id.imageButton, WidgetProvider.buildButtonPendingIntent(context));
}
&#13;
&#13;
&#13;

这就是全部,不再打嗝!