Observable 中的光标在方向改变时未关闭

Cursor in observable not closed on orientation change

虽然 运行 在严格模式下,当 phone 的方向改变时,我的应用程序会崩溃并显示错误

A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks. java.lang.Throwable: Explicit termination method 'close' not called

奇怪的是,如果我 运行 应用程序处于调试模式并完全放置断点 cursor.close() 只是为了确保它确实被命中,所有断点都会被命中并且应用程序永远不会崩溃。

这是我的片段,它调用另一个包含所有 SqlBrite 查询和游标的 class(为简洁起见,代码已被缩短)。

public class MenuSummary extends Fragment{

private DbHelper dbHelper;
private Observable<?> income1, income2;
private Observable imin;
private Subscription s;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    dbHelper = new DbHelper(getContext());
}

@Override
public void onPause(){
    super.onPause();
    s.unsubscribe();
}

@Override
public void onResume(){
    super.onResume();
    displaySummary(selectedYear,selectedMonth);
}

@Override
public void onStop() {
    super.onStop();
}

@Override
public void onActivityCreated(Bundle savedInstanceState){
    super.onActivityCreated(savedInstanceState);
}

private void displaySummary(final int selectedYear, final int selectedMonth){

    income1 = dbHelper.getIncome(selectedYear,selectedMonth,1);
    income2 = dbHelper.getIncome(selectedYear,selectedMonth,2);

    List<Observable<?>> myObservables = Arrays.asList(income1,income2);
    imin = Observable.combineLatest(myObservables, new FuncN<List<BigDecimal>>() {
        @Override
        public List<BigDecimal> call(Object... args) {
            List<BigDecimal> listIncome = new ArrayList<~>();
            listIncome.add((BigDecimal) args[0]);
            listIncome.add((BigDecimal) args[1]);
            return listIncome ;
        }
    }
).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
s = imin.subscribe(new Action1<List<BigDecimal>>() {
@Override
public void call(List<BigDecimal> expensesAndBalance) {
    //do plenty of view.settext here
}});
}

下面是包含函数 getIncome 的 DbHelper class 的样子:

谁能指出我哪里出错了?

   public class DbHelper {

        private MySQLiteHelper mySQLiteHelper;
        SqlBrite sqlBrite = new SqlBrite.Builder().build();
        BriteDatabase briteDb;
        Subscription subscription;

        private static DbHelper instance;
        public DbHelper(Context context) {
            mySQLiteHelper = new MySQLiteHelper(context);
            sqlBrite = new SqlBrite.Builder().build();
            briteDb = sqlBrite.wrapDatabaseHelper(mySQLiteHelper,Schedulers.io());
        }

        public Observable<BigDecimal> getIncome(final int endYear, final int endMonth, final int moneyJar){
        final String[] args = new String[]{moneyJar + "", endYear + "", endMonth + "", endYear + "", };
        Observable<BigDecimal> myObservable;
        myObservable = briteDb.createQuery(MySQLiteHelper.TABLE_INCOME, "SELECT total FROM " + MySQLiteHelper.TABLE_INCOME +
                " WHERE moneyJar = ? AND ((year = ? AND month <= ?) OR (year < ?)) and isDeleted = 0", args)
                .map(new Func1<SqlBrite.Query, BigDecimal>() {
                    @Override
                    public BigDecimal call(SqlBrite.Query query) {
                        Cursor cursor = query.run();
                        BigDecimal income, incomeTotal = new BigDecimal(0);
                        if (cursor != null) {
                            try {
                                if (cursor.getCount() > 0 && cursor.moveToFirst()) {
                                    do {
                                        income = new BigDecimal(cursor.getString(cursor.getColumnIndex("total")));
                                        incomeTotal = incomeTotal.add(income);
                                    } while (cursor.moveToNext());
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            } finally {
                                cursor.close();
                            }
                        }
                        return incomeTotal;
                    }
                });
        return myObservable;
    }
}

您没有关闭 BriteDatabase 实例。

您应该在关闭片段时执行此操作:

briteDb.close();

来自docs

Close the underlying SQLiteOpenHelper and remove cached readable and writeable databases. This does not prevent existing observables from retaining existing references as well as attempting to create new ones for new subscriptions.