【问题标题】:Widget Data Lost on run of heavy application运行繁重的应用程序时丢失小部件数据
【发布时间】:2012-04-27 08:24:16
【问题描述】:

我为我的应用创建了一个小部件。一切正常,小部件中显示的所有数据都正确显示。但是有时,当我运行其他应用程序(例如相机)并开始拍摄视频几秒钟并停止视频并关闭相机时会发生什么,然后突然在我的小部件中显示的所有数据都丢失了,并且在小部件中什么也没有显示.我不知道在我在 Android 2.3.3 中运行我的应用程序之前是否会出现这个问题,但是当我将手机更新到 Android 4.0 时,这个问题就出现了。

根据我设置的时间间隔更新小部件,丢失的数据再次出现。所以我的问题是为什么会发生这种数据丢失,这是我必须在我的代码中做的事情。请帮我解决这个问题。

我用过的代码

Widget_app_provider.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget_layout"
    android:minHeight="56dp"
    android:minWidth="56dp"
    android:updatePeriodMillis="2100000" />

WidgetLayout.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/appwidget_bg_clickable" >

    <ImageView
        android:id="@+id/backgroundImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:contentDescription="@string/tracking_status_faq_imageview_text"
        android:scaleType="fitXY" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center_horizontal|center_vertical" >

        <TextView
            android:id="@+id/txt_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#5f5f5f"
            android:textSize="14dp" >
        </TextView>
    </LinearLayout>

</RelativeLayout>

Widget.java 文件

public class Widget extends AppWidgetProvider implements Utilities
    {
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 
    {      
        // Read data from register before  updating the widget
        CycleManager.getSingletonObject().readHistoryDateFromFile(context);
        CycleManager.getSingletonObject().ComputeAverages();
        
        // To prevent any ANR timeouts, we perform the update in a service
        context.startService(new Intent(context, UpdateService.class));
    }

    public static class UpdateService extends Service 
    {
        @Override
        public void onStart(Intent intent, int startId) 
        {
            // Build the widget update for today
            RemoteViews updateViews = getValueFromCycleManager(this);

            // Push update for this widget to the home screen
            ComponentName thisWidget = new ComponentName(this, Widget.class);
            AppWidgetManager manager = AppWidgetManager.getInstance(this);
            manager.updateAppWidget(thisWidget, updateViews);
        }

        @Override
        public IBinder onBind(Intent arg0){
            // TODO Auto-generated method stub
            return null;
        }
        public RemoteViews getValueFromCycleManager(Context context) 
        {
            RemoteViews remoteViews = null;
            remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
                        
            Date currentDate = calInstance.getTime();
            
            // set No of days remaining for next cycle start to the widgets 
            Date dtStart = CycleManager.getSingletonObject().getStartDate();
            int iAvgCycleLength = CycleManager.getSingletonObject().getAvgCycleTime();
            
            calInstance.setTime(dtStart);
            calInstance.add(Calendar.DATE, iAvgCycleLength);            
            Date dtNextCycleDate = calInstance.getTime();   
            
            Long noOfDaysLeft = dtNextCycleDate.getTime()- currentDate.getTime();
            noOfDaysLeft = ((noOfDaysLeft / (1000 * 60 * 60)) + 1) / 24;
            
            remoteViews.setTextViewText(R.id.txt_date, Long.toString(noOfDaysLeft));        
        }
    }
}

【问题讨论】:

  • 如果设备因为内存不足而关闭您的进程,即使是单例也会从内存中删除(实际上是内存中的所有内容)。可能是一个原因,但 Idk
  • 我明白你的意思。你能简要说明一下吗?这对我会有帮助。
  • 如果您依赖于保存在static 变量中的某种状态并且您的进程被终止,您将像在设备重启后那样启动。因此,您必须以一种始终可以重建其状态的方式设计您的小部件(因为您从文件中读取,所以看起来您这样做了)。我不知道你的问题到底是什么,也许它只是被杀死的服务(顺便说一句,你应该实现 onStartCommand 而不是 onStart 并从那里返回 START_REDELIVER_INTENT
  • 并在完成后调用 stopSelf(startId)。或者使用 IntentService 为您完成棘手的部分并且应该非常适合您的任务。
  • 好的,我会试着告诉你..

标签: android android-widget


【解决方案1】:

尝试实现一个IntentService,它应该可以更好地处理被杀死的问题。您需要在 onHandleIntent 中完成工作,该工作会根据您在 context.startService(new Intent(context, UpdateService.class)); 中指定的意图进行调用。

public static class UpdateService extends IntentService 
{

    public UpdateService() 
    {
        super("UpdateService");
    }

    @Override
    protected void onHandleIntent(Intent intent)
    {
        // Build the widget update for today
        RemoteViews updateViews = getValueFromCycleManager(this);

        // Push update for this widget to the home screen
        ComponentName thisWidget = new ComponentName(this, Widget.class);
        AppWidgetManager manager = AppWidgetManager.getInstance(this);
        manager.updateAppWidget(thisWidget, updateViews);
    }

    public RemoteViews getValueFromCycleManager(Context context) 
    {
        RemoteViews remoteViews = null;
        remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

        Date currentDate = calInstance.getTime();

        // set No of days remaining for next cycle start to the widgets 
        Date dtStart = CycleManager.getSingletonObject().getStartDate();
        int iAvgCycleLength = CycleManager.getSingletonObject().getAvgCycleTime();

        calInstance.setTime(dtStart);
        calInstance.add(Calendar.DATE, iAvgCycleLength);            
        Date dtNextCycleDate = calInstance.getTime();   

        Long noOfDaysLeft = dtNextCycleDate.getTime()- currentDate.getTime();
        noOfDaysLeft = ((noOfDaysLeft / (1000 * 60 * 60)) + 1) / 24;

        remoteViews.setTextViewText(R.id.txt_date, Long.toString(noOfDaysLeft));        
    }
}

【讨论】:

  • 好的..意味着不需要 onStart 方法,因为我在 UpdateService 类上使用过..
  • 是的 IntentService 是一个专门的子类,您应该在其中实现 onHandleIntent。对于常规的Service,它将是onStartCommand,而onStart 已被弃用,根本不应使用。
  • 是的,问题已解决,但对你所做的事情有点困惑。在我的初始代码中,小部件正确显示内容,但只有当我打开其他一些应用程序(如相机)并开始拍摄视频然后关闭相机时,我的应用程序小部件中显示的所有数据都会丢失。我不明白的是,使用相机或其他一些繁重的应用程序如何导致我的应用程序小部件丢失。虽然它们之间没有联系..以及您的代码如何解决问题
  • @Anshuman Android 需要更多内存,因此它正在关闭不需要这么多内存的应用程序。当繁重的应用程序关闭服务再次启动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多