Android 冰淇淋三明治
我在玩IC和小部件,偶然发现了一个我似乎无法正确调试的问题 应用程序有一个主活动(WidgetActivity)、一个小部件配置(WidgetConfigure)和一个提供程序(WidgetProvider)。小部件的布局(下面的代码)有一个父LinearLayout和两个子LinearLayout。这两个孩子都被设置为不可见。在我的提供者的Android 冰淇淋三明治,android,android-widget,Android,Android Widget,我在玩IC和小部件,偶然发现了一个我似乎无法正确调试的问题 应用程序有一个主活动(WidgetActivity)、一个小部件配置(WidgetConfigure)和一个提供程序(WidgetProvider)。小部件的布局(下面的代码)有一个父LinearLayout和两个子LinearLayout。这两个孩子都被设置为不可见。在我的提供者的onUpdate中,我实例化了该小部件的RemoteViews对象,并尝试将第一个LinearLayout设置为可见 小部件显示在主屏幕上时,但两个孩子不显
onUpdate
中,我实例化了该小部件的RemoteViews对象,并尝试将第一个LinearLayout设置为可见
小部件显示在主屏幕上时,但两个孩子不显示(预期)。调用onUpdate
时,子项未设置为可见。在adb中,我得到的是来自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>
D/####WidgetProvider(522):未更新 D/####WidgetProvider(522):获取视图 D/####WidgetProvider(522):应该设置可见性 I/ActivityManager(84):为广播com.android.quicksearchbox/.CorporateUpdateReceiver启动proc com.android.quicksearchbox:pid=536 uid=10011 gids={3003} D/dalvikvm(34):GC_显式释放37K,4%释放9901K/10243K,暂停4ms+6ms D/dalvikvm(84):GC_并发释放496K,5%释放12726K/13383K,暂停11ms+43ms D/StrictMode(84):StrictMode策略违反~持续时间=2436毫秒:android.os.StrictMode$StrictModeDiskReadViolation:policy=151 violation=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/stricmode(84):位于com.android.server.ServerThread.run(SystemServer.java:744) D/StrictMode(84):StrictMode策略违反~持续时间=2301毫秒:android.os.StrictMode$StrictModeDiskWriteVolation:policy=151冲突=1 D/StrictMode(84):位于android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1048) D/StrictMode(84):位于libcore.io.BlockGuardOs.write(BlockGuardOs.java:178) D/stricmode(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/stricmode(84):位于com.android.server.ServerThread.run(SystemServer.java:744)
事实上,原因在于严格的模式。我已经解决了这个问题,确保我的网络代码在
服务中,而不是在小部件的更新中。尽管如此,Android仍然抱怨违反了严格的网络和光盘访问模式
为了解决这个问题,我修改了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);
}
}
为了补充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
}
});
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
}
});