当前位置: 首页 > 知识库问答 >
问题:

Kotlin代码“不要将Android上下文类放在静态字段中”投诉

龚沛
2023-03-14

我有一个用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代码中不可用,如何正确地在其中初始化变量?

我检查了关于这个主题的早期线程,找不到(或理解)适用于这里的答案。

共有2个答案

巫马英豪
2023-03-14

我能够通过将活动上下文作为参数传递给启动本机应用程序的函数,然后将其作为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函数中有了可用的工作应用程序上下文,接下来的问题是如何使用它来设置内容视图。我会再提一个问题。

感谢所有做出贡献的人。

伍嘉
2023-03-14

永远不要将任何android上下文放在静态字段中(在静态编程语言中,该字段进入伴随对象),这是一种不好的做法,因为这样会导致内存泄漏。

如果要访问类中的上下文,请在其构造函数中将上下文传递给它,或者如果类类似于活动,请使用getApplicationContext()访问上下文。

在您的示例中,您根本不需要存储上下文,因为您的活动实际上是一个context本身(您可以使用thisas 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”的原因,因为它试图打印当前未创建的当前实例。因此,我认为这就是为什么您会遇到编译时错误。

  • 你能帮我用下面的代码吗。错误是:“不能在静态上下文中使用此”