打开一个子活动多次引起尽管被破坏的InstanceCountViolation个子、InstanceCountViolation

2023-09-06 03:34:19 作者:这少年是败类

我的工作,有被称为一个较低的水平活动 RecordView 显示记录的详细信息,如图像,它的拍摄日期和时间的项目,以及纬度/经度信息。而不是试图操纵相机地理标记,并获得EXIF数据我想实现一个位置监听器来获得,其中第一次拍摄的图像的位置(按钮preSS)。这种方法的工作原理 - 我得到我的位置,以显示正确更新数据库中的记录(返回到视图后从一开始就显示的位置)。不过,如果我背出电流 RecordView 键,然后输入两个以上(任意组合)的计划将与错误崩溃 InstanceCountViolation (下文转载完整的错误)。当我重写 RecordView 的生命周期方法来显示当每个被调用,我们发现,它再次被调用之前被销毁。也就是说,它不会出现一个以上的 RecordView 存在于任何给定的时间。

I'm working on a project that has a lower level activity called RecordView to display record details such as an image, the date and time it was taken, and the latitude/longitude information. Rather than trying to manipulate the camera to geotag and access exif data I'm trying to implement a location listener to get the location where the image is first taken (on the button press). This approach works - I get my location to display and update the record in the database correctly (returning to the view later displays the location from the beginning). However, if I back out of the current RecordView and then enter two more (any combination) the program will crash with the error InstanceCountViolation (full error reprinted below). When I override the lifetime methods of RecordView to display when each is called we find that it is destroyed before being called again. That is to say, it doesn't appear that more than a single RecordView exists at any given time.

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

So my question boils down to this: where is that error coming from and how can I fix it?

东西撒谎被破坏?是LocationListener的围坐在什么地方,造成的问题?有什么事情无关,可能将提供一个虚假的错误?

Is something lying about being destroyed? Is the LocationListener sitting around somewhere and causing problems? Is it something unrelated that might be providing a bogus error?

另外,我应该做的可怕的硬codeD修复和刚起来的 RecordView 情况下,限制允许吗?还是继续追缉另一种方法(作为一个例子,我尝试用 PendingIntent.getBroadcast(...)呼叫请求单个更新)?

Also, should I do the horrible hard coded fix and just up the limit of RecordView instances allowed? Or continue hunting for another approach (as an example I'm attempting to request a single update using a PendingIntent.getBroadcast(...) call)?

有关引用此错误出现在模拟器上的3.1和实际的平板电脑(一个Xoom的,3.1)。注释掉监听更新code似乎避免了崩溃(修改2 :我似乎已经错了)。在code,因为它涉及到侦听低于(它可以在公开方法中找到 updateLocation RecordView 类)。

For reference this error has appeared on the emulator for 3.1 and on an actual tablet (a Xoom, 3.1). Commenting out the listener update code seems to avoid the crash (EDIT 2: I appear to have been wrong about that). The code as it relates to the listener is below (it can be found inside a public method updateLocation inside the RecordView class).

    // 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)

编辑:

两件事情我已经确定。

Two things I've determined.

首先,当LogCat中显示了 RecordView 活动的破坏 LocationListener的正确断开(破坏?这是空反正)。但是听者似乎从坟墓那边进行更新,因为它是 - 那就是,我有时会看到我的吐司消息对更高层次的活动屏和GPS信息对GPS的更新似乎已经更新

The first is that when Logcat shows the destruction of the RecordView activity the LocationListener is correctly disconnected (destroyed? It's null anyway). However the listener seems to update from beyond the grave as it were - that is, I sometimes see my Toast message about a GPS update on the higher level activities screen and the GPS information appears to have been updated.

第二个是,它不完全是说每崩溃 - 这似乎是强制关闭 RecordView ,而不是整个应用程序。该应用的主要块似乎只是基本上被最小化。

The second is that it isn't exactly crashing per say - it appears to be Force Closing the RecordView rather than the entire app. The main chunk of the app seems to just basically be minimized.

编辑2:

我们最近增加了使用新的活性preference屏幕,这有相同的 InstanceCountViolation 误差为 RecordView 。我们已经证实,没有在对出现错误的行为被改变:只需要打开几次。我们如何打开我们的子活动的主要活动下面是一个例子:

We recently added a preference screen using a new activity and this has the same InstanceCountViolation error as the RecordView. We've verified that nothing has to be changed in the activity for the error to occur: it only needs to be opened a few times. An example of how we open our sub-activities from the main activities is below:

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); 

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

So now I'm wondering if there's a problem in how the Intent is handling activity creation and deletion.

推荐答案

我知道这是旧的文章。只是为了家伙谁正在寻找解决方案,并解释了这个问题。

I know that this is old post. Just for guys who is looking for solution and explanation to this problem.

在情况下,有InstanceCountViolation异常就意味着有可能是真的有活动泄漏或问题,这是关系到如何detectActivityLeaks检查是在Android SDK中实现的。

In case there is InstanceCountViolation exception it means that there can be real with Activity leak or problem which is related to how detectActivityLeaks check is implemented in Android SDK.

要确定是否这是一个问题,我可以推荐以下职位:泄漏检测活动的Andr​​oid 。如果你会看到有拿着引用这次活动的对象不涉及到Android框架,那么你必须应固定你的问题。

To identify if this is a problem I can recommend the following post: Detecting leaked Activities in Android. If you will see that there are objects holding a reference to this activity which don't related to Android Framework then you have a problem which should be fixed by you.

在情况下,有拿着引用这项活动不涉及到Android框架比它意味着你有相关的detectActivityLeaks检查是如何实现的问题,遇到的任何对象。在这种情况下失败的活动解决问题,而不必关闭detectActivityLeaks,你可以简单地运行的的System.gc()的下面的示例开始活动调试配置像以前一样:

In case there are no objects holding a reference to this activity which don't related to Android Framework than it means that you encountered with the problem related to how detectActivityLeaks check is implemented. In this case to fix the problem with failed activity without turning off detectActivityLeaks you can simply run System.gc() before starting activity in debug configuration like in the following example:

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

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

更多信息,在此回答。