安卓CursorLoader引发死循环程序的探究

本文详细探讨了CursorLoader和ContentProvider的工作原理,包括创建Loader、查询过程、变更通知机制及常见循环调用问题的解决策略。通过分析,帮助读者理解两者结合使用时的关键步骤和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在探究之前,需要确认下CursorLoader和ContentProvider的基本流程,以便于提供有力的理论支持,这次死循环调用

消耗时间比较久,根本原因是没有搞清楚CursorLoader和ContentProvider的结合过程

1.创建cursorLoader

@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle arg1)
{
 //创建一个cursorLoader,确定了当收到变化通知时,如何进行 query

//cursorLoader第一次加载时,会触发查询,查询会触发观察者的注册过程

//离开了loader 所在界面,loader查询不会被触发的,返回界面时触发
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor returnCursor)

//当查询完成,会窒息onLoadFinished,经过测试,目前发现都是在主线中

2.


try {
    cursor = db.query(tableName, projection, finalSelection, selectionArgs,
                  null, null, sortOrder);
} catch (Exception e) {
    e.printStackTrace();
}

if (cursor != null) {

//实际是注册观察者,监听范围是 DBAuthority.DB_AUTHORITY_URI)

//根据实践认为,如果没有cursorLoader存在,这个注册是无效的
    cursor.setNotificationUri(getContext().getContentResolver(), DBAuthority.DB_AUTHORITY_URI);
}

 

3.内容发送变更通知观察者

SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
String tableName = getUriMatcher().getTableName(match);
int affectedRows = 0;
try {
   B: affectedRows = db.update(tableName, values,    selection, selectionArgs);
} catch (Exception e) {
    e.printStackTrace();
}

A:getContext().getContentResolver().notifyChange(uri, null);

 

A的含义是通知所有观察者,uri对应的内容发生变化了,注意,根据实践测试,请不要认为只有监控这个uri的观察者才能收到

如果B的操作不执行,那么A的通知不会生效

4.循环问题分析:

cursorLoader首次加载---刷新界面---item从本地数据库获取信息失败---item 请求网络成功(但是没有item需要的数据)---修改数据库---触发第一步的cuerLoader变化‘

5.循环解决方案:

item请求网络的原因是item从本地获取信息失败,所以请求网络。

我们控制网络请求只能进行一次,避免反复请求

 

其他问题:数据库操作慢是因为接口没有增量返回,导致大量数据库操作,占用了线程池,可以在contentProvider相关操作打日志观察的到

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值