我有一个用Java编写的基于Android Studio的应用程序。我工作得很好 并且不会导致Android Studio抱怨任何事情:
public class MainActivity extends AppCompatActivity {
static Context maincActivityContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivityContext = getApplicationContext();
...
}
/* JNI function called from c++ */
private void updateStatus(String event, final String call) {
...
runOnUiThread(new Runnable() {
@Override
public void run() {
TextView caller_uri = new TextView(mainActivityContext);
...
}
});
}
...
}
然后我去找Android Studio将其转换为Java 到科特林。转换后,MainActivity看起来像这样:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainActivityContext = applicationContext
...
}
/* JNI function called from C++ */
private void updateStatus(String event, final String call) {
...
runOnUiThread(new Runnable() {
@Override
public void run() {
TextView caller_uri = new TextView(mainActivityContext);
...
}
});
}
companion object {
internal lateinit var mainActivityContext: Context
...
}
}
否则在Java版本中,但类变量mainActivityContext 从MainActivity的顶部移动到伴侣对象。现在又来了 应用程序工作正常,但Android Studio抱怨 mainActivityContext变量声明:
Do not place Android context classes in static fields
然后我将声明移回了Java版本中的位置:
class MainActivity : AppCompatActivity() {
internal lateinit var mainActivityContext: Context
override fun onCreate(savedInstanceState: Bundle?) {
mainActivityContext = applicationContext
...
并且Android Studio很满意。但是,当我试图 运行应用程序,它崩溃了这样:
03-18 16:08:52.788 7467 7467 E AndroidRuntime:kotlin.UninitializedPropertyAccessException:lateinit属性mainActivityContext尚未初始化
03-18 16:08:52.788 7467 7467 E AndroidRuntime:at com.foo.bar.MainActivity.updateStatus(MainActivity.kt:362)
确定变量是(像之前一样)在onCreate函数中初始化。
问题:
为什么runOnUIThread代码中没有初始化,以及在那里初始化变量的正确方法是什么?
我之前检查了有关此主题的主题,但无法找到(或理解)这里适用的答案。
答案 0 :(得分:1)
永远不要在static
字段(Kotlin
中进入companion object
)中放置任何Android上下文,这是一种不好的做法,因为你可以通过这种方式获得内存泄漏。 / p>
如果要访问类中的上下文,或者在其构造函数中传递上下文,或者如果类类似于活动,请使用getApplicationContext()
来访问上下文。
在您的示例中,您根本不需要存储上下文,因为您的活动实际上是Context
本身(您可以使用this
作为上下文)。
答案 1 :(得分:0)
异常的原因是因为在初始化之前访问lateint属性。
尝试更换:
internal lateinit var mainActivityContext: Context
与
var appContext: Context? = null
答案 2 :(得分:0)
我能够通过将活动上下文作为参数传递给启动本机应用程序的函数,然后将其作为updateStatus函数的参数传递回MainActivity,从而完全摆脱mainActivityContext变量:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
Thread(Runnable { nativeAppStart(applicationContext) }).start()
}
}
原生应用程序如下所示:
static jobject *appContext;
JNIEXPORT void JNICALL
Java_com_tutpro_baresip_MainActivity_baresipStart(JNIEnv *env, jobject thiz, jobject *context)
{
appContext = context;
...
}
及其updateStatus调用如下所示:
jmethodID statusId = (*env)->GetMethodID(env, pctx->jniHelperClz,
"updateStatus",
"(Landroid/content/Context;Ljava/lang/String)V");
...
(*env)->CallVoidMethod(env, pctx->jniHelperObj, statusId, appContext, status);
现在我在updateStatus函数中有可用的应用程序上下文,接下来的问题是如何使用它来设置内容视图。我将发布另一个关于它的问题。
感谢所有贡献者。