Ada*_*ski 6 c++ java java-native-interface android react-native
我有一个Android应用程序,它同时使用React Native和JNI.C++(通过JUCE库的一个分支)用于生成其中一个视图.
React Native要求从重写的方法返回一个新的视图实例createViewInstance(context)
.每次更新包含此视图的React Native组件时,似乎都会调用此方法.
这是我的(简化)实现:
protected JuceViewHolder createViewInstance(ThemedReactContext themedReactContext) {
JuceBridge juceBridge = JuceBridge.getInstance();
juceViewHolder = new JuceViewHolder(themedReactContext);
// JNI method: this will trigger JuceBridge.createNewView
MainActivity.createJuceWindow(juceViewHolder);
return juceViewHolder;
Run Code Online (Sandbox Code Playgroud)
}
供参考,createJuceWindow
定义为:
JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, createJuceWindow, jobject, (JNIEnv* env, jclass, jobject view))
{
JuceView::getInstance().createJuceWindow(view);
}
Run Code Online (Sandbox Code Playgroud)
哪个叫:
void createJuceWindow(jobject view)
{
viewToAttachTo = GlobalRef(view); // [GlobalRef][1] manages NewGlobalRef
myComponent = std::unique_ptr<MyComponent> (new MyComponent);
myComponent->setVisible (true);
myComponent->setOpaque(true);
if (viewToAttachTo.get() == nullptr)
DBG ("createJuceWindow: viewToAttachTo null!!!");
myComponent->setBounds(Desktop::getInstance().getDisplays().getMainDisplay().userArea);
myComponent->addToDesktop (0, viewToAttachTo.get()); // This passes in the `jobject` held by GlobalRef
}
Run Code Online (Sandbox Code Playgroud)
我已将JuceViewHolder
派生与ViewGroup 分开,并通过JNI将其传递给C++函数,以附加ComponentPeerView
从(C++)AndroidComponentPeer
构造函数生成的(Java)
AndroidComponentPeer (Component& comp, const int windowStyleFlags, void* viewToAttachTo)
: ComponentPeer (comp, windowStyleFlags),
usingAndroidGraphics (false),
fullScreen (false),
sizeAllocated (0),
scale ((float) Desktop::getInstance().getDisplays().getMainDisplay().scale)
{
// NB: must not put this in the initialiser list, as it invokes a callback,
// which will fail if the peer is only half-constructed.
if (viewToAttachTo == nullptr) DBG ("viewToAttachTo null");
view = GlobalRef (android.bridge.callObjectMethod (JuceBridge.createNewView,
(jboolean) component.isOpaque(),
(jlong) this,
(jobject) viewToAttachTo));
if (view.get() == nullptr)
DBG ("view null!");
else
DBG ("got view.");
if (isFocused())
handleFocusGain();
}
Run Code Online (Sandbox Code Playgroud)
通过createNewView
方法:(简化在这里)
public final ComponentPeerView createNewView (boolean opaque, long host, ViewGroup viewToAttachTo)
{
ComponentPeerView v = new ComponentPeerView (viewToAttachTo.getContext(), opaque, host);
viewToAttachTo.addView(v);
return v;
}
Run Code Online (Sandbox Code Playgroud)
host
是指向C++ AndroidComponentPeer
实例的指针.
这最初工作,但似乎如果我切换到另一个视图或活动和/或切换回C++视图,我得到类似于以下崩溃:
JNI ERROR (app bug): accessed deleted global reference 0x100566
art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: use of deleted global reference 0x100566
art/runtime/java_vm_ext.cc:410] from void com.juce.JuceBridge$ComponentPeerView.focusChanged(long, boolean)
Run Code Online (Sandbox Code Playgroud)
我目前的假设是错误是由于void*
指针在某些时候因为垃圾收集器移动底层对象而变得过时,如本文所述.我从文章中得到的是jobject
应该用来代替指针.
但是Component::addToDesktop
我使用的方法的方法签名使用void*
:
virtual void addToDesktop (int windowStyleFlags,
void* nativeWindowToAttachTo = nullptr);
Run Code Online (Sandbox Code Playgroud)
(这是iOS中用于传递本机UIView
以附加Component
到的方法)
我的假设有效吗?如果是这样,是否可以安全地转换void*
指向Java对象的指针,将其存储为jobject
(通过NewGlobalRef)然后将其传递回Java?
归档时间: |
|
查看次数: |
923 次 |
最近记录: |