Android 历史内容观察者
Posted
技术标签:
【中文标题】Android 历史内容观察者【英文标题】:Android History Content Observer 【发布时间】:2013-05-14 16:05:02 【问题描述】:我实现了历史内容观察器,但它的行为很奇怪。对于历史中的每一次更改,它的 onChange() 函数都会运行 3-5 次。
static class BrowserOberser extends ContentObserver
public BrowserOberser()
super(null);
@Override
public boolean deliverSelfNotifications()
return true;
@Override
public void onChange(boolean selfChange)
super.onChange(selfChange);
Log.d("History", "onChange: " + selfChange);
我还使用
注册了我的观察者BrowserOberser observer = new BrowserOberser();
getApplication().getContentResolver().registerContentObserver(Browser.BOOKMARKS_URI, true, observer );
并在清单中添加了所需的权限。
代码运行良好,但 onChange();每次历史变化运行 3-5 次 谁能帮我解决这个问题?
【问题讨论】:
***.com/questions/6026547/… 对我没有帮助。 我观察到的是第一次和第三次运行之间的区别是:在第一次运行中,标题与 url 相同,但在第三次运行中出现了适当的标题。所以这可能是因为页面加载的阶段。但它到底是什么?为什么运行次数不同? 如果您需要更多信息,请发表评论 【参考方案1】:这就是我最终为我的案例解决问题的方法(我想在历史发生变化时阅读历史)
@Override
public void onChange(boolean selfChange)
super.onChange(selfChange);
/**
* Get SharedPreferneces of the user
*/
SharedPreferences pref= myContext.getSharedPreferences("com.tpf.sbrowser",
Context.MODE_PRIVATE);
long wherelong = pref.getLong("Date", 0);
DatabaseManager db=new DatabaseManager(myContext,1);
String[] proj = new String[] Browser.BookmarkColumns.TITLE,
Browser.BookmarkColumns.URL, BookmarkColumns.DATE,;
String sel = Browser.BookmarkColumns.BOOKMARK + " = 0";
Cursor mCur = myContext.getContentResolver().query(
Browser.BOOKMARKS_URI, proj, sel, null, null);
Log.d("onChange", "cursorCount"+mCur.getCount());
mCur.moveToFirst();
String title = "";
String url = "";
long lastVisitedDate=0;
DbMessage msg = new DbMessage(lastVisitedDate,url, title);
/**
* Start reading the user history and dump into database
*/
if(mCur.moveToFirst() && mCur.getCount() > 0)
while (mCur.isAfterLast() == false)
title =mCur.getString(0);
url = mCur.getString(1);
lastVisitedDate =mCur.getLong(2);
if ((lastVisitedDate>wherelong) && (!title.equals(url)))
msg.set(lastVisitedDate, url, title);
db.InsertWithoutEnd(msg);
pref.edit().putBoolean("BrowserHistoryRead", true).commit();
pref.edit().putLong("Date", lastVisitedDate).commit();
myContext.updateTime(wherelong,lastVisitedDate);
wherelong=lastVisitedDate;
mCur.moveToNext();
但是,如果有人能分辨出 onChange 的哪个迭代(在问题的简单代码中)与页面加载中的哪个状态完全对应,那就太好了。 据我所知,在第一次迭代中,标题与 url 相同,在第三次迭代中,出现了正确的页面标题。但是在重定向期间,onChange 被调用了 5 次。那么有人可以确认哪个迭代对应哪个阶段吗?
【讨论】:
【参考方案2】:我想我可能会找到答案。 首先我想说我的英语有限,希望你能理解我。
确实,onChange();
会针对历史记录的每次更改运行多次,至少两次。
因为当用户使用浏览器浏览网站时,系统会在数据库中添加一个历史记录,并调用onChange();
。但是现在系统不知道 url 的标题。系统得到url的标题后,系统更新数据库,第二次调用onChange();
。
而且,如果在此期间url正在重定向,每次系统得到一个新的url时,系统也会更新数据库,所以onChange();也被称为。 所以,我认为每次更改都会调用 onChange 多次。 希望你能听懂我的英文。
【讨论】:
【参考方案3】:更新历史的确切方式是您可能不想依赖的实现细节。与其尝试根据各个字段的值来猜测更新是否完成,我建议每次调用onChange(..)
时重新启动一个计时器。如果计时器到期,您可以合理地确定历史记录已完成更新。
编辑如何使用计时器的示例:
static class BrowserOberser extends ContentObserver implements Runnable
private Handler h;
public BrowserOberser()
super(null);
h = new Handler();
@Override
public boolean deliverSelfNotifications()
return true;
@Override
public void onChange(boolean selfChange)
super.onChange(selfChange);
h.removeCallbacks(this);
h.postDelayed(this, 500);
public void run()
Log.d("history observer", "change timer elapsed");
【讨论】:
嗯,这也是一个不错的方法,我尝试过,但没有奏效。 1) 猜测历史何时完成更新也很棘手。假设用户在页面加载过程中失去了互联网连接,这将导致标题与 url 相同(这是基于我的实际观察)。 2)您打算如何实施?onChange()
将在每次 url 加载时被调用 5 次,所以你不能只是暂停它,因为这不会产生预期的结果。
如果你能告诉我更新历史的确切方式是什么,我将不胜感激(当然赏金也是你的)。
好吧,这种方法很好,但问题 1) 仍然存在。如果用户网络很慢并且站点很重,则可能需要更长的时间。我将延迟时间增加到 5000,有时会重复进入。但我真的很感激这个答案:) 因此赏金
我尝试将延迟时间增加到 20000(假设该页面肯定会在 20 秒内加载,否则我会得到错误的结果),它使浏览器非常慢,并且记录日志的次数也没有非常一致。所以不,这不是理想的解决方案以上是关于Android 历史内容观察者的主要内容,如果未能解决你的问题,请参考以下文章
设计模式 观察者模式 以Android中TextView文本内容发生变化为背景
设计模式 观察者模式 以Android中TextView文本内容发生变化为背景