我有一个用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转换为Kotlin。转换后,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 版本一样,但类变量主活动上下文已从主活动的顶部移动到伴随对象。现在,该应用程序再次运行良好,但Android Studio抱怨主要活动上下文变量声明:
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 Android运行时间: 科特林.未初始化属性访问异常: lateinit 属性 mainActivity上下文尚未初始化
03-18 16:08:52.788 7467 7467 E AndroidRuntime: atcom.foo.bar.MainActivity.updateStatus(MainActivity.kt:362)
可以肯定的是,变量是(像以前一样)在onCreate函数中初始化的。
问题:
为什么初始化在runOnUIThread代码中不可用,如何正确地在其中初始化变量?
我检查了关于这个主题的早期线程,找不到(或理解)适用于这里的答案。
我能够通过将活动上下文作为参数传递给启动本机应用程序的函数,然后将其作为updateState函数的参数传递回MainActive,从而完全摆脱main ActivityContext变量:
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函数中有了可用的工作应用程序上下文,接下来的问题是如何使用它来设置内容视图。我会再提一个问题。
感谢所有做出贡献的人。
永远不要将任何android上下文放在静态
字段中(在静态编程语言
中,该字段进入伴随对象
),这是一种不好的做法,因为这样会导致内存泄漏。
如果要访问类中的上下文,请在其构造函数中将上下文传递给它,或者如果类类似于活动,请使用getApplicationContext()
访问上下文。
在您的示例中,您根本不需要存储上下文,因为您的活动实际上是一个context
本身(您可以使用this
as context)。
问题内容: 有些问题的标题相似,但所有问题都与您在构造函数中获得的上下文有关。 有带有项目的RecyclerView和其他带有播放\暂停按钮的视图。 此类允许该视图一次仅播放一个文件。如果正在播放view_1,然后在view_2上按播放,则将播放file_2。 此类中有一个 ImageButton mPlayPauseButton。需要将view_1的 ImageButton 设置为paused_
问题内容: 这个问题已经在这里有了答案 : 7年前关闭。 可能重复: 为什么我会得到“无法从静态上下文引用的非静态变量”? 这是代码 错误说: 非静态类 Node 不能从静态上下文中引用 为什么不应该在main()方法中引用Node类? 问题答案: Java中的非静态嵌套类包含对父类 实例 的隐式引用。因此,要实例化a ,您还需要具有一个实例。在静态上下文(主要方法)中,没有要引用的实例。因此,编
我的应用程序中有两个类: runner类包含我的方法,我尝试在该方法中从Tasks类调用一个方法: 在我的Runner中,当我试图调用Tasks类中的createTaskList()方法时,我得到以下错误: 我该怎么解决这个?
问题内容: 当尝试从另一个类中调用一个方法时,我的方法出现错误 说非静态字符串不能从静态上下文中引用。变量不是静态的,但是我仍然有这个问题吗? 我现在的主程序大块(很抱歉地方的草率编码) InfixToPostfixParens的代码 问题答案: 您的代码与以下代码(编译)有何不同?
问题内容: 您能帮我用下面的代码吗?错误是: “不能在静态上下文中使用此” 问题答案: 参见,“ this”关键字指的是当前对象,这是由于正在执行哪种方法。不能使用类的实例调用静态方法。这就是为什么不能在上面的示例中以静态方法使用“ this”的原因,因为它试图打印当前未创建的当前实例。因此,我认为这就是为什么您会遇到编译时错误。
你能帮我用下面的代码吗。错误是:“不能在静态上下文中使用此”