【问题标题】:Ice Cream Sandwich StrictMode冰淇淋三明治严格模式
【发布时间】:2012-03-21 01:41:16
【问题描述】:

我正在使用 ICS 和 Widgets,偶然发现了一个我似乎无法正确调试的问题。

应用程序有一个主活动(WidgetActivity)、一个小部件配置(WidgetConfigure)和一个提供者(WidgetProvider)。小部件的布局(下面的代码)有一个父 LinearLayout 和两个子 LinearLayout。这两个孩子都被设置为隐形。在我的提供商的onUpdate 中,我实例化了该小部件的 RemoteViews 对象,并尝试将第一个 LinearLayout 设置为可见。

当放置在主屏幕上时,小部件会显示,但两个孩子不会(预期)。当onUpdate 被调用时,子进程没有设置为可见。在 adb 中,我得到的是来自 StrictMode 的一堆警告,关于小部件无法将其状态写入磁盘。读取和写入存在违反政策的规定。由于我实际上并没有在任何地方进行任何读写操作,因此我认为这是一个操作系统调用。

我的问题 - 这个 StrictMode 会导致我的视​​图不改变可见性吗?我粗略地理解,StrictMode 允许我确定我的 UI 线程中哪里有慢代码。但我不只是想盲目地覆盖或提供新的 StrictMode 设置而不了解发生了什么。

正如 adb 所示,我的 onReceive 被调用(如果您再次等待 180000 毫秒),但我的子视图未设置为可见。我不知道为什么。

这是代码。小部件布局 xml、提供程序、adb 跟踪:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFF"
    android:orientation="vertical" >

    <include layout="@layout/widget_next_season" />

    <include layout="@layout/widget_upcoming_game" />

</LinearLayout>

public class WidgetProvider extends AppWidgetProvider {

    private static String TAG = "### WidgetProvider";

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        Log.d(TAG, "onUpdate");

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
        Log.d(TAG, "Got Views");
        views.setViewVisibility(R.id.layout_one, View.VISIBLE);
        Log.d(TAG, "Should've set visibility");
    }
}

D/### WidgetProvider(522):onUpdate D/### WidgetProvider(522):获得了意见 D/### WidgetProvider(522): 应该设置可见性 I/ActivityManager(84): 启动 proc com.android.quicksearchbox 广播 com.android.quicksearchbox/.CorporaUpdateReceiver: pid=536 uid=10011 gids={3003} D/dalvikvm(34):GC_EXPLICIT 释放 37K,4% 释放 9901K/10243K,暂停 4ms+6ms D/dalvikvm(84):GC_CONCURRENT 释放 496K,5% 释放 12726K/13383K,暂停 11ms+43ms D/StrictMode(84):StrictMode 策略违规; ~duration=2436 毫秒:android.os.StrictMode$StrictModeDiskReadViolation:策略=151 违规=2 D/StrictMode(84):在 android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1074) D/StrictMode(84):在 libcore.io.BlockGuardOs.open(BlockGuardOs.java:94) D/StrictMode(84):在 libcore.io.IoBridge.open(IoBridge.java:390) D/StrictMode(84):在 java.io.FileOutputStream.(FileOutputStream.java:88) D/StrictMode(84):在 com.android.server.AppWidgetService.writeStateToFileLocked(AppWidgetService.java:1220) D/StrictMode(84):在 com.android.server.AppWidgetService.saveStateLocked(AppWidgetService.java:1204) D/StrictMode(84):在 com.android.server.AppWidgetService$2.onReceive(AppWidgetService.java:1503) D/StrictMode(84):在 android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:728) D/StrictMode(84):在 android.os.Handler.handleCallback(Handler.java:605) D/StrictMode(84): 在 android.os.Handler.dispatchMessage(Handler.java:92) D/StrictMode(84):在 android.os.Looper.loop(Looper.java:137) D/StrictMode(84):在 com.android.server.ServerThread.run(SystemServer.java:744) D/StrictMode(84):StrictMode 策略违规; ~duration=2301 毫秒:android.os.StrictMode$StrictModeDiskWriteViolation:策略=151 违规=1 D/StrictMode(84):在 android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1048) D/StrictMode(84):在 libcore.io.BlockGuardOs.write(BlockGuardOs.java:178) D/StrictMode(84):在 libcore.io.IoBridge.write(IoBridge.java:447) D/StrictMode(84):在 java.io.FileOutputStream.write(FileOutputStream.java:187) D/StrictMode(84):在 com.android.internal.util.FastXmlSerializer.flushBytes(FastXmlSerializer.java:212) D/StrictMode(84):在 com.android.internal.util.FastXmlSerializer.flush(FastXmlSerializer.java:233) D/StrictMode(84):在 com.android.internal.util.FastXmlSerializer.endDocument(FastXmlSerializer.java:183) D/StrictMode(84):在 com.android.server.AppWidgetService.writeStateToFileLocked(AppWidgetService.java:1266) D/StrictMode(84):在 com.android.server.AppWidgetService.saveStateLocked(AppWidgetService.java:1204) D/StrictMode(84):在 com.android.server.AppWidgetService$2.onReceive(AppWidgetService.java:1503) D/StrictMode(84):在 android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:728) D/StrictMode(84):在 android.os.Handler.handleCallback(Handler.java:605) D/StrictMode(84): 在 android.os.Handler.dispatchMessage(Handler.java:92) D/StrictMode(84):在 android.os.Looper.loop(Looper.java:137) D/StrictMode(84):在 com.android.server.ServerThread.run(SystemServer.java:744)

【问题讨论】:

    标签: android android-widget


    【解决方案1】:

    原因实际上是 StrictMode。我通过确保我的网络代码在Service 中解决了这个问题,而不是在小部件的onUpdate 中。尽管如此,Android 仍然抱怨网络和磁盘访问违反了 StrictMode。

    为了解决这个问题,我修改了 StrictMode 策略,并在完成后将其重置。我只是围绕网络代码调用这些函数。

    /**
     * Prevent exceptions from doing disk and network operations in a service
     */
    protected static void setPermissiveThreadPolicy() {
        // set StrictMode to allow network/disk in service
        oldThreadPolicy = StrictMode.getThreadPolicy();
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(oldThreadPolicy).permitNetwork().permitDiskReads().permitDiskWrites().build());
    }
    
    /**
     * Reset thread policy to previously known state for consistency
     */
    protected static void resetThreadPolicy() {
        if (oldThreadPolicy != null) {
            // reset to old policy
            StrictMode.setThreadPolicy(oldThreadPolicy);
        }
    }
    

    【讨论】:

      【解决方案2】:

      要添加 jlindenbaum 贡献的内容,而不是自己管理线程策略,这里有一个很好的帮助类,可以确保您不会忘记重置线程策略。

      public class ThreadPolicyManager {
      
      // ========== Singleton ==========
      private static ThreadPolicyManager sInstance;
      public static ThreadPolicyManager getInstance()
      {
          if(sInstance == null)
          {
              sInstance = new ThreadPolicyManager();
          }
          return sInstance;
      }
      
      private ThreadPolicyManager(){}
      
      // ========== Class ==========
      
      private StrictMode.ThreadPolicy mPreviousThreadPolicy;
      
      /**
       * Prevent exceptions from doing disk and network operations in a service
       */
      private void setPermissiveThreadPolicy() {
          mPreviousThreadPolicy = StrictMode.getThreadPolicy();
          StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(mPreviousThreadPolicy).permitNetwork().permitDiskReads().permitDiskWrites().build());
      }
      
      /**
       * Reset thread policy to previously known state for consistency
       */
      private void resetThreadPolicy() {
          if (mPreviousThreadPolicy != null) {
              StrictMode.setThreadPolicy(mPreviousThreadPolicy);
          }
      }
      
      /**
       * This will temporarily set the thread policy to permissive,
       * execute the unit of work, and then reset the thread policy
       */
      public void executePermissiveUnit(PermissiveUnit unit)
      {
          setPermissiveThreadPolicy();
          unit.executeUnitOfWork();
          resetThreadPolicy();
      }
      
      // ========= PermissiveUnit ========
      
      /**
       * This is a functor to allow a unit of work to be executed
       * permissively
       */
      public static abstract class PermissiveUnit{
          public abstract void executeUnitOfWork();
      }
      
      }
      

      并使用它:

      ThreadPolicyManager.getInstance().executePermissiveUnit(new ThreadPolicyManager.PermissiveUnit(){
          @Override
          public void executeUnitOfWork() {
              //TODO whatever needs to be executed
          }
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-02
        • 1970-01-01
        • 1970-01-01
        • 2013-03-29
        • 2012-03-11
        • 2014-03-26
        • 1970-01-01
        相关资源
        最近更新 更多