【问题标题】:Redraw Widget every second每秒重绘 Widget
【发布时间】:2014-03-07 10:59:38
【问题描述】:

我想创建一个带有秒针的时钟小部件。 是的,我已经读过小部件的设计不是为了快速刷新。

这个小部件应该变成一个鸡蛋计时器,只有当用户主动启动它时才会有动画,所以它可能对电池寿命和性能一点也不坏,因为我只在用户主动使用它时才使用这种高刷新率。 .

目前我启动了一个服务,它每 1000 毫秒发布一个延迟的可运行对象。

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)

我已经缓存了我的最后一个位图,并且仅在将新位图转发到小部件时才回收它。为什么我会得到这个异常?

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

干杯, 斯蒂芬

【问题讨论】:

  • 您能否重新粘贴错误日志并使用代码格式?它们无法阅读。
  • 我更新了我的问题。

标签: android performance android-widget


【解决方案1】:

你应该像这样回收位图

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

除此之外还有另一个问题,您应该使用alarmmanager 来更新小部件,与Runnable() 相比,它会消耗更少的电池;

【讨论】:

  • 其实我用的是服务。这个 Runnable 刚刚在我的服务“onStart()”中启动。我没有看到使用 AlarmManager 的任何好处。实际上我看到了一些缺点:1.)我需要注册一个接收器 2.)我需要一个额外的权限
  • 无需注册额外的receiver Appwidget提供包含onReceive方法如onupdate。你可以在 onupdate 中设置 ararmmanager,它会在同一个类中调用 onReceive。
  • 您是否通过添加 bmpLast=null 进行了检查;在您的代码中
  • 查看stackoverflow.com/questions/20651197/…我如何使用appwidgetprovidre类的onReceive
  • 这是我的第一个小部件,所以你比我更专家 :)
【解决方案2】:

您的部分问题可能是您坚持使用 RemoteViews 对象并不断向其添加“操作”。 RemoteViews 不会对操作进行任何智能重复数据删除,它只是将它们附加到一个列表中,因此您可以有效地保留对您推入其中的每个 Bitmap 的引用。

【讨论】:

    猜你喜欢
    • 2019-12-03
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 2016-05-17
    • 2012-01-11
    • 2016-09-02
    相关资源
    最近更新 更多