2011-07-06 32 views
8

我正在研究一个名为RecordView的较低级别活动的项目,用于显示记录详细信息,如图像,拍摄的日期和时间以及纬度/经度信息。我试图实现一个位置监听器来获取图像第一次拍摄的位置(按下按钮),而不是试图操纵相机来进行地理标记和访问exif数据。这种方法是有效的 - 我可以正确地显示和更新数据库中的记录(稍后返回视图显示从头开始的位置)。但是,如果我退出当前的RecordView,然后再输入两个(任意组合),程序将崩溃,并显示错误InstanceCountViolation(下面转载完整的错误)。当我调用RecordView的生命期方法显示每个被调用时,我们发现它被再次调用之前被销毁。也就是说,在任何给定时间似乎都不存在多于一个的RecordView多次打开子活动会导致InstanceCountViolation被摧毁

所以我的问题归结为:这个错误来自哪里,我该如何解决它?

被摧毁的东西在撒谎吗? LocationListener是否坐在某处并导致问题?它可能提供了一个虚假错误吗?

此外,我应该做可怕的硬编码修复,并刚刚限制RecordView实例允许?或者继续寻找另一种方法(例如,我试图使用PendingIntent.getBroadcast(...)调用请求单个更新)?

仅供参考,此模拟器上3.1和实际平板电脑(Xoom,3.1)上出现此错误。评论听众更新代码似乎避免了崩溃(编辑2:我似乎错了)。与听众相关的代码如下(可在RecordView类中的公共方法updateLocation内找到)。

// Listener for the update request 
    LocationListener locListener = new LocationListener() { 
     // Store the currentRecord so the listener can update it after return 
     Record currentRecord = record; 
     GeoDatabase database = data; 
     @Override 
     public void onLocationChanged(Location location) { 
      if (location != null) { 
       myLocation = location; 
       Log.d(TAG, "Location pulled as " + myLocation); 
       String lat = Location.convert(myLocation.getLatitude(), 
         Location.FORMAT_SECONDS); 
       String lon = Location.convert(myLocation.getLongitude(), 
         Location.FORMAT_SECONDS); 

       // Update the record values 
       currentRecord.setRecordLatitude(lat); 
       currentRecord.setRecordLongitude(lon); 
       database.updateRecord(currentRecord); 
       Log.d(TAG, "Record values now listed as "+ record.getValues()); 

       // Update the text boxes 
       latitude.setText(lat); 
       longitude.setText(lon); 

       Toast.makeText(getBaseContext(),"GPS location updated", 
         Toast.LENGTH_LONG).show(); 
      } else { 
       Log.w(TAG, "Passed location is null!"); 
       Toast.makeText(getBaseContext(), 
         "GPS error - unusable location", 
         Toast.LENGTH_LONG).show(); 
      } 
     } 

     @Override 
     public void onProviderDisabled(String provider) { 
      Toast.makeText(getBaseContext(), 
        "GPS disabled", Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onProviderEnabled(String provider) { 
      Toast.makeText(getBaseContext(), 
        "GPS enabled", Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onStatusChanged(String provider, int status, Bundle extras) { 
     } 
    }; 

    lm.requestSingleUpdate(LocationManager.GPS_PROVIDER, locListener, null); 

完整的错误:

android.os.StrictMode$InstanceCountViolation:class [program path].RecordView; instances=3; limit=2 
    at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1) 

编辑:

两件事情我已经确定。

第一个是当Logcat显示RecordView活动被破坏时,LocationListener被正确断开(销毁?无论如何,它是空的)。然而,听众似乎是从坟墓之外更新 - 也就是说,我有时会看到我的Toast消息关于更高级别活动屏幕上的GPS更新,并且GPS信息似乎已经更新。

其次,它并不完全崩溃说 - 它似乎是力量关闭RecordView而不是整个应用程序。应用程序的主要部分似乎基本上被最小化。

编辑2:

最近,我们使用一个新的活动添加偏好屏幕,这具有相同的InstanceCountViolation误差作为RecordView。我们已经证实,在错误发生的活动中不需要改变任何东西:它只需要打开几次。我们如何从主要活动开启我们的子活动下面是一个例子:

Intent intent = new Intent(this.getActivity() 
     .getApplicationContext(), RecordView.class); 
Bundle extras = new Bundle(); 
extras.putString("tableName", "table1"); 
extras.putInt("id", mId); 
extras.putBoolean("newRecord", false); 
extras.putLong("folder_id", mFolderId); 
extras.putString("type", recordList.get(mId).getTableName()); 
intent.putExtras(extras); 

startActivity(intent); 

所以现在我想知道如果有在做的目的是如何处理的活动创建和删除的问题。

+0

嘿,你有没有想过这个?我刚刚参加了一个偏好活动。 –

+0

@AndyD不幸的是没有。当我们关闭严格模式时,它似乎运行正常,但显然这不是一个真正的解决方案... – thegrinner

+0

我刚才问到类似的问题,才发现这一个:http://stackoverflow.com/questions/15368187/android -strict-mode-detected-multiple-activity-instance-violation-but-i-no-no – Jules

回答

0

好像不应该需要它,但你有没有打过电话

lm.removeUpdates(locListener);

到注销监听?

0

我知道这是旧帖子。只为那些正在寻找解决方案并解释这个问题的人。

如果存在InstanceCountViolation异常,则意味着可能存在Activity泄漏问题或与Android SDK中detectActivityLeaks检查的实现有关的问题。

要确定是否这是一个问题,我可以推荐以下文章:Detecting leaked Activities in Android。如果您将看到有对象持有对此活动的引用,这些引用与Android Framework无关,那么您有一个问题应该由您来解决。

如果没有对象持有对此活动的引用而与Android Framework无关,则表示您遇到与detectActivityLeaks检查的实现有关的问题。在这种情况下,失败的活动来解决这个问题,而不必关闭detectActivityLeaks你可以简单地在调试配置在下面的示例开始活动像以前一样运行System.gc()的

if (BuildConfig.DEBUG) 
{   
    System.gc(); 
} 

Intent intent = new Intent(context, SomeActivity.class); 
this.startActivity(intent); 

更多信息,在此提供answer