1

我有一个 android 应用程序,我在其中使用光标和列表视图。我在运行 android 版本为 2.1 时开发了这个应用程序。我决定不使用 StartmanagingCursor() 和 stopmanagingcursor() 因为当我从一个活动转移到另一个活动时它们的行为不稳定。事实上,我创建了一个静态函数,它调用每个生命周期事件来管理活动游标。下面是这个函数的完整代码。

public static void onBegin(Object extraMethodName, Activity activity,
            Utils.lifeStatus lastStatus, Utils.lifeStatus currentStatus) {
        Method method;
        Utils.currentActivity = activity.getLocalClassName() + "_"
                + Integer.toString(activity.getTaskId());

        if (!Utils.lifecycleCheck(lastStatus, currentStatus)) {
            DBAdapter.open(activity);
            if (extraMethodName != null) {
                try {
                    method = activity.getClass().getSuperclass()
                            .getDeclaredMethod    (extraMethodName.toString());
                    method.setAccessible(true);
                    method.invoke(activity);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    }

    public static void onEnd(Object extraMethodName, Activity activity,
            Utils.lifeStatus lastStatus, Utils.lifeStatus currentStatus) {
        Method method;
        Log.i("Utils.currentActivity", Utils.currentActivity);
        Log.i("ActivityClosing",
                activity.getLocalClassName() + "_"
                        + Integer.toString(activity.getTaskId()));
        if (Utils.lifecycleCheck(lastStatus, currentStatus)) {
            if (Utils.currentActivity.equals(activity.getLocalClassName() + "_"
                    + Integer.toString(activity.getTaskId()))) {
                if (extraMethodName != null) {
                    try {
                        method = activity.getClass().getSuperclass()
                                .getDeclaredMethod(extraMethodName.toString());
                        method.setAccessible(true);
                        method.invoke(activity);
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                DBAdapter.close();
            }
        }
    }
      public static boolean lifecycleCheck(Utils.lifeStatus lastStatus,
            Utils.lifeStatus newStatus) {
        boolean result = false;

        if (lastStatus != null) {
            switch (lastStatus) {
            case PAUSE:
            case DESTROY:
            case STOP:
                result = false;
                break;
            case RESUME:
            case START:
            case RESTART:
            case ONACTIVITYRESULT:
                result = true;
                break;

            default:
                result = false;
            }
        } else {
            result = false;
        }

        return result;
    }

其中extramethod是onBegin函数中每个activity的初始化函数和onEnd函数中的关闭游标函数。

在我决定创建一个基本 Activity 之前,这些函数一直很完美,其中我有一个光标和一个适配器,所有其他活动都从 base 继承。此活动还管理生命周期。(下面是完整的代码)。在那次更改之后,我在 android v4.0 中部署了我的应用程序,我的客户报告我说它在随机情况下崩溃。复制错误对我来说非常困难,但我可以看到,当应用程序崩溃时,我会将奇怪的重复数据从客户端带到服务器。

   package baseActivities;

public class BaseListActivity extends ListActivity {
    protected BaseCursorAdapter _cAdapter;
    protected BaseGridCursorAdapter _gridAdapter;
    protected BaseImageCursorAdapter _imageAdapter;
    protected String TAG = "BaseActivity";
    private static Utils.lifeStatus _lastStatus = Utils.lifeStatus.DESTROY;
    public Cursor _cursor;

    public enum filterTypes{
        query,category,subcategory,promitheutis
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Context cnt=this.getApplicationContext();

        Thread.UncaughtExceptionHandler mUEHandler = new Thread.UncaughtExceptionHandler() {

            @Override
            public void uncaughtException(Thread t, Throwable e) {

                Intent i = new Intent(cnt, MainActivity.class);
                i.putExtra("ERROR", 1);

                AlarmManager alm = (AlarmManager) cnt
                        .getSystemService(Context.ALARM_SERVICE);
                alm.set(AlarmManager.RTC, System
                        .currentTimeMillis() + 1000,
                        PendingIntent.getActivity(
                                cnt,
                                0,
                                i, 0));
                Process.killProcess(Process.myPid());
            }
        };

       // Thread.setDefaultUncaughtExceptionHandler(mUEHandler);
    }

    protected void setupForm() throws Exception {

    }

    public void search(HashMap<filterTypes,Object> FilterParams)
    {

    }

    public void openRowDetails(int position,String quantity)
    {

    }


    public void back_click(View v) throws Exception {
        finish();
    }


    @Override
    protected void onStart() {
        super.onStart();
        Utils.onBegin("setupForm", this, _lastStatus, Utils.lifeStatus.START);
        _lastStatus = Utils.lifeStatus.START;
        Log.i(TAG, "onStart()");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Utils.onBegin("setupForm", this, _lastStatus, Utils.lifeStatus.RESTART);
        _lastStatus = Utils.lifeStatus.RESTART;
        Log.i(TAG, "onRestart()");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Utils.onBegin("setupForm", this, _lastStatus, Utils.lifeStatus.RESUME);
        String settedLanguage = Utils.getLanguage();
        Utils.SetLaguage(settedLanguage == null ? Settings.LANGUAGE
                : settedLanguage, this.getBaseContext());
        _lastStatus = Utils.lifeStatus.RESUME;
        Log.i(TAG, "onResume()");

    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // Saving activity state
        Log.i(TAG, "onSaveInstanceState()");
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.i(TAG, "onRestoreInstanceState()");
    }

    @Override
    protected void onPause() {
        super.onPause();
        // Another activity is taking focus (this activity is about to be
        // "paused").
        Utils.onEnd("prepareToCloseDB", this, _lastStatus,
                Utils.lifeStatus.PAUSE);
        Log.i(TAG, "onPause()");
        _lastStatus = Utils.lifeStatus.PAUSE;
    }

    @Override
    protected void onStop() {
        super.onStop();
        // The activity is no longer visible (it is now "stopped")
        setListAdapter(null);
        Utils.onEnd("prepareToCloseDB", this, _lastStatus,
                Utils.lifeStatus.STOP);
        Log.i(TAG, "onStop()");
        _lastStatus = Utils.lifeStatus.STOP;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // The activity is about to be destroyed.
        setListAdapter(null);
        Utils.onEnd("prepareToCloseDB", this, _lastStatus,
                Utils.lifeStatus.DESTROY);
        Log.i(TAG, "onDestroy()");
        _lastStatus = Utils.lifeStatus.DESTROY;
    }

    @SuppressWarnings("unused") 
    protected void prepareToCloseDB() {
        TextView emptyTextView = ((TextView)findViewById(android.R.id.empty));
        if(emptyTextView!=null)
        {
            emptyTextView.setText(this.getResources().getString(R.string.parakalw_perimenete));
        }
        if (_cursor != null) {
            if (!_cursor.isClosed()) {
                _cursor.close();
            }
        }
    }
}

以下是我从我的应用程序中收集的日志之一。

-----------------EXCEPTION START--------------------
26/01/2013 15:05:58
 -----------------STAACKTRACE--------------------
 Don't have database lock!
 Class:android.database.sqlite.SQLiteDatabase | File:SQLiteDatabase.java | Method:verifyLockOwner | Line:2090
 Class:android.database.sqlite.SQLiteDatabase | File:SQLiteDatabase.java | Method:endTransaction | Line:690
 Class:myapp.myapp.FindMeetingActivity | File:FindMeetingActivity.java | Method:deleteMeeting | Line:235
 Class:myapp.myapp.FindMeetingActivity | File:FindMeetingActivity.java | Method:onContextItemSelected | Line:142
 Class:android.app.Activity | File:Activity.java | Method:onMenuItemSelected | Line:2538
 Class:com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback | File:PhoneWindow.java | Method:onMenuItemSelected | Line:3521
 Class:com.android.internal.view.menu.MenuBuilder | File:MenuBuilder.java | Method:dispatchMenuItemSelected | Line:735
 Class:com.android.internal.view.menu.MenuItemImpl | File:MenuItemImpl.java | Method:invoke | Line:149
 Class:com.android.internal.view.menu.MenuBuilder | File:MenuBuilder.java | Method:performItemAction | Line:874
 Class:com.android.internal.view.menu.MenuDialogHelper | File:MenuDialogHelper.java | Method:onClick | Line:167
 Class:com.android.internal.app.AlertController$AlertParams$3 | File:AlertController.java | Method:onItemClick | Line:924
 Class:android.widget.AdapterView | File:AdapterView.java | Method:performItemClick | Line:292
 Class:android.widget.AbsListView | File:AbsListView.java | Method:performItemClick | Line:1058
 Class:android.widget.AbsListView$PerformClick | File:AbsListView.java | Method:run | Line:2514
 Class:android.widget.AbsListView$1 | File:AbsListView.java | Method:run | Line:3168
 Class:android.os.Handler | File:Handler.java | Method:handleCallback | Line:605
 Class:android.os.Handler | File:Handler.java | Method:dispatchMessage | Line:92
 Class:android.os.Looper | File:Looper.java | Method:loop | Line:137
 Class:android.app.ActivityThread | File:ActivityThread.java | Method:main | Line:4444
 Class:java.lang.reflect.Method | File:Method.java | Method:invokeNative | Line:-2
 Class:java.lang.reflect.Method | File:Method.java | Method:invoke | Line:511
 Class:com.android.internal.os.ZygoteInit$MethodAndArgsCaller | File:ZygoteInit.java | Method:run | Line:787
 Class:com.android.internal.os.ZygoteInit | File:ZygoteInit.java | Method:main | Line:554
 Class:dalvik.system.NativeStart | File:NativeStart.java | Method:main | Line:-2
 ---------------EXCEPION END----------------------

你能帮我理解为什么会这样吗?它是由我的基本活动问题引起的,还是由 android v4.0 的更改引起的。?

感谢我们的帮助!

4

0 回答 0