FBreader多端同步心得补充

本文介绍了一种在不同软件层间实现属性ID与段落位置同步的方法。通过解析C++层内部链接,将属性ID及其对应的段落位置传递给Java层,并在Java层保存这些映射关系,从而实现了根据ID获取位置或根据位置获取ID的功能。

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

接上篇继续,说到通过已知的属性id取到对应的位置,却没有解决根据当前阅读页的段落位置或者笔记位置取到其属性id.这样就会造成一个问题,我只能用其他端的id来跳转到指定的位置阅读,自己却没有属性id来表示同步位置.
后来又无脑的翻找已一下,在JavaNativeFormatPlugin.cpp中找到相关的代码,initInternalHyperlinks()方法中的model.internalHyperlinks()就是存储了属性id与段落位置,在上篇中取到的id实际上也是这里持久化的产物.那么我只需将此处的id与位置关系回传给java层并保存下来就差不多了.至于是选择缓存到本地还是内存,还是根据实际情况来判断吧,我这就简单放在内存中.
相关回传的代码(不会c++,low代码别见笑)

static bool initInternalHyperlinks(JNIEnv *env, jobject javaModel, BookModel &model, const std::string &cacheDir) {
	ZLCachedMemoryAllocator allocator(131072, cacheDir, "nlinks");

	ZLUnicodeUtil::Ucs2String ucs2id;
	ZLUnicodeUtil::Ucs2String ucs2modelId;

	const std::map<std::string,BookModel::Label> &links = model.internalHyperlinks();
	std::map<std::string,BookModel::Label>::const_iterator it = links.begin();
	for (; it != links.end(); ++it) {
		const std::string &id = it->first;
		const BookModel::Label &label = it->second;
		//将解析的属性回传给java层的BookModel=====start
		JString idj(env, id.substr());
		AndroidUtil::Method_BookModel_AttrIds->call(javaModel, idj.j(), label.ParagraphNumber);
		//将解析的属性回传给java层的BookModel=====end
		if (label.Model.isNull()) {
			continue;
		}
		ZLUnicodeUtil::utf8ToUcs2(ucs2id, id);
		ZLUnicodeUtil::utf8ToUcs2(ucs2modelId, label.Model->id());
		const std::size_t idLen = ucs2id.size() * 2;
		const std::size_t modelIdLen = ucs2modelId.size() * 2;

		char *ptr = allocator.allocate(idLen + modelIdLen + 8);
		ZLCachedMemoryAllocator::writeUInt16(ptr, ucs2id.size());
		ptr += 2;
		std::memcpy(ptr, &ucs2id.front(), idLen);
		ptr += idLen;
		ZLCachedMemoryAllocator::writeUInt16(ptr, ucs2modelId.size());
		ptr += 2;
		std::memcpy(ptr, &ucs2modelId.front(), modelIdLen);
		ptr += modelIdLen;
		ZLCachedMemoryAllocator::writeUInt32(ptr, label.ParagraphNumber);
	}
	allocator.flush();

	JString linksDirectoryName(env, allocator.directoryName(), false);
	JString linksFileExtension(env, allocator.fileExtension(), false);
	jint linksBlocksNumber = allocator.blocksNumber();
	AndroidUtil::Method_BookModel_initInternalHyperlinks->call(javaModel, linksDirectoryName.j(), linksFileExtension.j(), linksBlocksNumber);
	return !env->ExceptionCheck();
}

其中AndroidUtil::Method_BookModel_AttrIds->call()方法请依葫芦画瓢!!!
然后在BookModel.java中定义方法接收

protected SparseArray<String> links = new SparseArray<>();
public void attrIds(String attrId, int paragraphIndex){
		if (attrId.contains("#")){
			//之所以这里有#号,可以看上篇的attrId组成
			links.put(paragraphIndex, attrId.split("#")[1]);
		}
	}

紧接着在需要的地方调用,即做到了通过id取位置,也可以做到通过位置取id


	public int getParagraphIndexByAttrId(String attrId){
		if (links != null){
			int index = links.indexOfValue(attrId);
			return links.keyAt(index);
		}
		return -1;
	}

	public String getAttrIdByParagraphIndex(int paragraphIndex){
		if (links != null){
			return links.get(paragraphIndex);
		}
		return "";
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值