findclass在Android平臺中只允許在主線程(UI)中使用,所以我們要在其他線程中使用只能一次性findclass所有的class,並生成一個Global的引用。這樣我們就可以在其他線程(如果是非Java線程,需要AttachCurrentThread一下)使用找個class的全局引用了。
- ClassReferenceHolder
WebRTC封裝的一個類,可以拿出來在其他地方使用。
使用方式就是全局只需要一個ClassReferenceHolder對象,找個對象只需要在UI線程構造一下就好了,不需要的時候調用FreeReferences釋放資源。
class ClassReferenceHolder {
public:
explicit ClassReferenceHolder(JNIEnv* jni) {
LoadClass(jni, "java/nio/ByteBuffer");
LoadClass(jni, "java/util/ArrayList");
LoadClass(jni, "java/util/Set");
}
~ClassReferenceHolder();
void FreeReferences(JNIEnv* jni) {
for (std::map<std::string, jclass>::const_iterator it = classes_.begin();
it != classes_.end(); ++it) {
jni->DeleteGlobalRef(it->second);
}
classes_.clear();
}
jclass GetClass(const std::string& name) {
std::map<std::string, jclass>::iterator it = classes_.find(name);
assert(it != classes_.end());
return it->second;
}
private:
void LoadClass(JNIEnv* jni, const std::string& name) {
jclass localRef = jni->FindClass(name.c_str());
if (!jni->ExceptionCheck()) {
// jni->ExceptionDescribe();
// jni->ExceptionClear()
// TODO
}
jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef));
if (!jni->ExceptionCheck()) {
// jni->ExceptionDescribe();
// jni->ExceptionClear()
// TODO
}
bool inserted = classes_.insert(std::make_pair(name, globalRef)).second;
if (inserted) {
// TODO
}
}
std::map<std::string, jclass> classes_;
};
// called on main thread
static ClassReferenceHolder* g_class_reference_holder = nullptr;
// Returns a global reference guaranteed to be valid for the lifetime of the
// process.
jclass FindClass(JNIEnv* jni, const char* name) {
return g_class_reference_holder->GetClass(name);
}