每秒重绘一次小部件

时间:2014-03-07 10:59:39

标签: android performance android-widget

我想用第二只手表创建一个时钟小部件。 是的,我已经读过,小部件不是为了快速刷新而设计的。

小部件应该成为一个蛋计时器,只有当用户主动启动它时才会生成动画,因此它可能对电池寿命和性能没有那么差,因为我只在用户主动使用它时使用这种高刷新率。

目前我启动的服务每1000毫秒发布一次延迟的runnable。

Handler mTimeRecordLongTouchedHandler = new Handler();
Runnable mTimeRecordLongTouched = new Runnable() {
    public void run() {

        remoteViews.setTextViewText(R.id.tv_widget_watch, _fmtTime.print(new DateTime()));
        Bitmap bmpSource = _bmpSource.copy(Bitmap.Config.ARGB_8888, true);

        Canvas canvas = new Canvas(bmpSource);


        DateTime dtNow = new DateTime();
        int iSeconds = dtNow.getSecondOfMinute();

        float radius = _bmpSource.getWidth() / 2;
        float mX = _bmpSource.getWidth() / 2;
        float mY = _bmpSource.getWidth() / 2;

        float pX = mX + radius * FloatMath.cos(iSeconds * 6);
        float pY = mY + radius * FloatMath.sin(iSeconds * 6);

        canvas.drawLine(mX, mY, pX, pY, paint3);

        remoteViews.setImageViewBitmap(R.id.iv_tower, bmpSource);

        manager.updateAppWidget(thiswidget, remoteViews);
        iCounter++;

        // if (bmpLast != null) {
        // bmpLast.recycle();
        // }
        // bmpLast = bmpSource;

        mTimeRecordLongTouchedHandler.postDelayed(mTimeRecordLongTouched, 1000);
    }
};

几秒钟后,我得到:“android.os.TransactionTooLargeException”。 对于这个异常,我没有堆栈跟踪,但我想这是因为我不回收我新创建的位图。 之后的例外是:“系统服务器死了?”这里我有一个堆栈跟踪:

03-07 11:26:28.374: E/AndroidRuntime(13422): FATAL EXCEPTION: main
03-07 11:26:28.374: E/AndroidRuntime(13422): java.lang.RuntimeException: system server dead?
03-07 11:26:28.374: E/AndroidRuntime(13422):    at android.appwidget.AppWidgetManager.updateAppWidget(AppWidgetManager.java:554)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at com.mxp.time.service.WidgetService$1.run(WidgetService.java:90)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at android.os.Handler.handleCallback(Handler.java:730)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at android.os.Handler.dispatchMessage(Handler.java:92)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at android.os.Looper.loop(Looper.java:137)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at android.app.ActivityThread.main(ActivityThread.java:5493)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at java.lang.reflect.Method.invokeNative(Native Method)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at java.lang.reflect.Method.invoke(Method.java:525)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at dalvik.system.NativeStart.main(Native Method)
03-07 11:26:28.374: E/AndroidRuntime(13422): Caused by: android.os.TransactionTooLargeException
03-07 11:26:28.374: E/AndroidRuntime(13422):    at android.os.BinderProxy.transact(Native Method)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at com.android.internal.appwidget.IAppWidgetService$Stub$Proxy.updateAppWidgetProvider(IAppWidgetService.java:736)
03-07 11:26:28.374: E/AndroidRuntime(13422):    at android.appwidget.AppWidgetManager.updateAppWidget(AppWidgetManager.java:551)
03-07 11:26:28.374: E/AndroidRuntime(13422):    ... 10 more

我认为只需回收我的位图就可以轻松解决这个问题

if (bmpLast != null) {
            bmpLast.recycle();
        }
        bmpLast = bmpSource;

但这只是让我想到下一个问题:

03-07 11:28:22.964: E/AndroidRuntime(14559): FATAL EXCEPTION: main
03-07 11:28:22.964: E/AndroidRuntime(14559): java.lang.IllegalStateException: Can't parcel a recycled bitmap
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.graphics.Bitmap.checkRecycled(Bitmap.java:273)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.graphics.Bitmap.writeToParcel(Bitmap.java:1332)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.widget.RemoteViews$BitmapCache.writeBitmapsToParcel(RemoteViews.java:988)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.widget.RemoteViews.writeToParcel(RemoteViews.java:2573)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at com.android.internal.appwidget.IAppWidgetService$Stub$Proxy.updateAppWidgetProvider(IAppWidgetService.java:730)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.appwidget.AppWidgetManager.updateAppWidget(AppWidgetManager.java:551)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at com.mxp.time.service.WidgetService$1.run(WidgetService.java:90)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.os.Handler.handleCallback(Handler.java:730)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.os.Handler.dispatchMessage(Handler.java:92)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.os.Looper.loop(Looper.java:137)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at android.app.ActivityThread.main(ActivityThread.java:5493)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at java.lang.reflect.Method.invokeNative(Native Method)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at java.lang.reflect.Method.invoke(Method.java:525)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
03-07 11:28:22.964: E/AndroidRuntime(14559):    at dalvik.system.NativeStart.main(Native Method)

我已经缓存了我的最后一个位图,只有当新的位图被转发到小部件时才回收它。为什么我会得到这个例外?

谁想要包裹我的最后一个位图?保持小部件对我传入的所有位图的引用???

干杯, 斯蒂芬

2 个答案:

答案 0 :(得分:1)

你应该像这样回收位图

if (bmpLast != null) {
        bmpLast.recycle();
        bmpLast=null;//you must do it
    }

除此之外还有另一个问题,你应该使用alarmmanager更新小部件,与Runnable()相比,它会减少电量;

答案 1 :(得分:1)

您的部分问题可能是您挂在RemoteViews对象上并继续向其添加“操作”。 RemoteViews不执行任何智能重复操作,只是将它们附加到列表中,因此您可以有效地保留对您推送的每个Bitmap的引用。