findclass

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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章